[alsa-devel] appl_ptr and DMA overrun at end of stream

Takashi Iwai tiwai at suse.de
Mon May 11 11:53:24 CEST 2009

At Thu, 7 May 2009 12:23:51 -0400,
Jon Smirl wrote:
> I am having problem with DMA overrun at the end of the audio stream.
> Is there an official way to know the address of the last valid audio
> sample?
> mpc5200 ac97 is keeping a bunch of descriptors queued in a loop to
> continuously play music. I believe this is the way ALSA wants it. Now
> say the last period is
> half full. ALSA fills the other half with silence. When that period
> finishes playing it will generate an interrupt. ALSA comes back from
> that interrupt with trigger(STOP).
> But, our CPU is slow compared to a 3Ghz desktop, there is considerable
> latency from the period end interrupt to trigger(STOP) getting called.
>  So the DMA hardware starts playing the next period before
> trigger(STOP) can get the DMA stopped.  I turned off tried turning off
> BestComm, flushing the FIFO, and turning off the audio clocks.  None
> can be done fast enough. That next period contains stale data from
> further back in the stream. When the front part of it plays it makes a
> burst of noise.
> What I need is the address of the end of valid data in the buffer. I
> need that address so that I can program the DMA automatically stop at
> end of stream and not overrun. Search around in the guys of ALSA I
> found appl_ptr. I can use appl_ptr to determine the location of end of
> stream and prevent DMA overrun. When there is no valid data I don't
> enqueue the
> descriptor.

Right.  This is the value to check in your case.

>  s->appl_ptr track the previous value of  s->runtime->control->appl_ptr.
> The difference between these two is the amount of valid data in the buffer.
> When this difference goes to zero, I stop queue new buffers to ALSA.

Yes, that'll work, I guess.

> That fixes the DMA overrun.
> static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
> {
>        struct bcom_bd *bd;
>        while (s->appl_ptr < s->runtime->control->appl_ptr) {

You'd need to think of boundary overlap, too.
It's a bit nasty because we wrap the value at runtime->boundary...



More information about the Alsa-devel mailing list