--- ./sound/arm/omap-alsa-dma.c_orig 2005-11-28 09:58:01.601413144 +0100 +++ ./sound/arm/omap-alsa-dma.c 2005-11-28 10:41:38.272618656 +0100 @@ -37,6 +37,8 @@ * in dma handling and port to alsa structures. * * 2005-11-25 Dirk Behme - Added L/R Channel Interchange fix as proposed by Ajaya Babu + * + * 2005-11-28 Dirk Behme - Fix DMA issues that all 5-10s a short audio part is repeated */ #include @@ -55,6 +57,7 @@ #include #include #include +#include #include #include @@ -126,7 +129,23 @@ static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED; +struct audio_isr_work_item { + int current_lch; + u16 ch_status; + struct audio_stream *s; +}; + +static char work_item_running = 0; static char nr_linked_channels = 1; +static struct audio_isr_work_item work1, work2; + +/*********************************** MODULE SPECIFIC FUNCTIONS PROTOTYPES *************/ + +static void audio_dsr_handler(unsigned long); +static DECLARE_TASKLET(audio_isr_work1, audio_dsr_handler, + (unsigned long)&work1); +static DECLARE_TASKLET(audio_isr_work2, audio_dsr_handler, + (unsigned long)&work2); /*********************************** MODULE SPECIFIC FUNCTIONS ***********************/ @@ -414,6 +433,33 @@ int omap_start_sound_dma(struct audio_st } +/*************************************************************************************** + * + * ISR related functions + * + **************************************************************************************/ +/* The work item handler */ +static void audio_dsr_handler(unsigned long inData) +{ + void *data = (void *)inData; + struct audio_isr_work_item *work = data; + struct audio_stream *s = (work->s); + + FN_IN; + DPRINTK("lch=%d,status=0x%x, data=%p as=%p\n", sound_curr_lch, + ch_status, data, s); + if (AUDIO_QUEUE_EMPTY(s)) { + FN_OUT(-1); + return; + } + + AUDIO_INCREMENT_HEAD(s); /* Empty the queue */ + + /* Try to fill again */ + audio_dma_callback(s); + FN_OUT(0); +} + /* * ISRs have to be short and smart.. * Here we call alsa handling, after some error checking @@ -438,8 +484,26 @@ static void sound_dma_irq_handler(int so return; } - if (ch_status & DCSR_END_BLOCK) - audio_dma_callback(s); + if (AUDIO_QUEUE_LAST(s)) + omap_audio_stop_dma(s); + + /* Start the work item - we ping pong the work items */ + if (!work_item_running) { + work1.current_lch = sound_curr_lch; + work1.ch_status = ch_status; + work1.s = s; + /* schedule tasklet 1 */ + tasklet_schedule(&audio_isr_work1); + work_item_running = 1; + } else { + work2.current_lch = sound_curr_lch; + work2.ch_status = ch_status; + work2.s = s; + /* schedule tasklet 2 */ + tasklet_schedule(&audio_isr_work2); + work_item_running = 0; + } + FN_OUT(0); return; }