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...
thanks,
Takashi