[alsa-devel] alsa buffer underrun
邱昇譽
m943040028 at gmail.com
Tue Oct 20 06:39:51 CEST 2009
Dear Alsa developers:
I enconter a problem about alsa buffer underrun, and have no idea how to
solve it.
It's great if you can spent a little of your spare time to read this.
Thanks.
Our CPU, (a arm processor running at 162Mhz) using I2S to communicate with
codec.
The i2s hardware is simply a FIFO which generates an interrupt when the FIFO
data is below the
programed watermark(and relevant bit in status register will be set),
then we re-fill data into FIFO in interrupt handler
the interrupt handler code fragment will like this
static irqreturn_t dw_tdm_handler(int irq, void *data)
{
struct dw_tdm_dev *dev = (struct dw_tdm_dev *)data;
struct platform_device *pdev = dev->pdev;
struct snd_pcm_substream *substream = dev->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
u16 *buf = (u16 *)runtime->dma_area;
u32 status = dw_tdm_read_reg(TDM_INT_ STATUS);
unsigned int bytes_remain =
runtime->dma_bytes - dev->dma_pos;
buf += dev->dma_pos / sizeof(u16);
/* tx fifo is running low, reload new data for it */
if (status & TX_INT) {
int i;
unsigned int empty_banks =
TX_EMPTY_BANKS(dw_tdm_read_reg(TDM_STATUS));
/* 2 FIFO lines each bank */
unsigned int bytes_to_write = empty_banks * 4;
bytes_to_write = min(bytes_remain, bytes_to_write);
dev_dbg(&pdev->dev, "dma_pos = %d\n",
dev->dma_pos);
dev_dbg(&pdev->dev, "hw_ptr = %d\n",
frames_to_bytes(runtime, runtime->status->hw_ptr));
/* re-fill data, 1 sample contains 4 bytes */
for (i = 0; i < bytes_to_write / 4; i++) {
dw_tdm_write_reg(TDM_TX_FIFO, *buf++); /* left
channel */
dw_tdm_write_reg(TDM_TX_FIFO, *buf++); /* right
channel */
}
dev->dma_pos += bytes_to_write;
if (bytes_remain == bytes_to_write)
dev->dma_pos = 0;
}
/* rx fifo is running full, consume data from it */
if (status & RX_INT) {
/* TODO */
}
dev_dbg(&pdev->dev, "period elapsed\n");
snd_pcm_period_elapsed(substream);
/* clear interupt status */
dw_tdm_write_reg(TDM_INT_CLR, status);
return IRQ_HANDLED;
}
This runs into buffer underflow problem, when I use aplay to play a wav
file,
it seems user-space process doesn't accquire any cpu time, after out i2s h/w
start to work(, and generate interrupts)
output look like below: (strings in <> is my comments)
# aplay /1.wav
Playing WAVE '/1.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
snd_pcm_lib_write1: avail = 8160 <aplay start to fill buffer>
snd_pcm_lib_write1: avail = 7904
snd_pcm_lib_write1: avail = 7648
snd_pcm_lib_write1: avail = 7392
snd_pcm_lib_write1: avail = 7136
snd_pcm_lib_write1: avail = 6880
snd_pcm_lib_write1: avail = 6624
snd_pcm_lib_write1: avail = 6368
snd_pcm_lib_write1: avail = 6112
snd_pcm_lib_write1: avail = 5856
snd_pcm_lib_write1: avail = 5600
snd_pcm_lib_write1: avail = 5344
snd_pcm_lib_write1: avail = 5088
snd_pcm_lib_write1: avail = 4832
snd_pcm_lib_write1: avail = 4576
snd_pcm_lib_write1: avail = 4320
snd_pcm_lib_write1: avail = 4064
snd_pcm_lib_write1: avail = 3808
snd_pcm_lib_write1: avail = 3552
snd_pcm_lib_write1: avail = 3296
snd_pcm_lib_write1: avail = 3040
snd_pcm_lib_write1: avail = 2784
snd_pcm_lib_write1: avail = 2528
snd_pcm_lib_write1: avail = 2272
snd_pcm_lib_write1: avail = 2016
snd_pcm_lib_write1: avail = 1760
snd_pcm_lib_write1: avail = 1504
snd_pcm_lib_write1: avail = 1248
snd_pcm_lib_write1: avail = 992
snd_pcm_lib_write1: avail = 736
snd_pcm_lib_write1: avail = 480
snd_pcm_lib_write1: avail = 224
snd_pcm_lib_write1: avail = 0 <write completed, trigger pcm stream>
<i2s h/w start to work, and consume all the buffers, in this period, aplay
has no chance to re-fill buffer, and underrun occurs>
underrun!!! (at least 19.991 ms long)
snd_pcm_lib_write1: avail = 8160
snd_pcm_lib_write1: avail = 8128
snd_pcm_lib_write1: avail = 7872
snd_pcm_lib_write1: avail = 7616
snd_pcm_lib_write1: avail = 7360
snd_pcm_lib_write1: avail = 7104
snd_pcm_lib_write1: avail = 6848
snd_pcm_lib_write1: avail = 6592
snd_pcm_lib_write1: avail = 6336
snd_pcm_lib_write1: avail = 6080
snd_pcm_lib_write1: avail = 5824
snd_pcm_lib_write1: avail = 5568
snd_pcm_lib_write1: avail = 5312
snd_pcm_lib_write1: avail = 5056
snd_pcm_lib_write1: avail = 4800
snd_pcm_lib_write1: avail = 4544
snd_pcm_lib_write1: avail = 4288
snd_pcm_lib_write1: avail = 4032
snd_pcm_lib_write1: avail = 3776
snd_pcm_lib_write1: avail = 3520
snd_pcm_lib_write1: avail = 3264
snd_pcm_lib_write1: avail = 3008
snd_pcm_lib_write1: avail = 2752
snd_pcm_lib_write1: avail = 2496
snd_pcm_lib_write1: avail = 2240
snd_pcm_lib_write1: avail = 1984
snd_pcm_lib_write1: avail = 1728
snd_pcm_lib_write1: avail = 1472
snd_pcm_lib_write1: avail = 1216
snd_pcm_lib_write1: avail = 960
snd_pcm_lib_write1: avail = 704
snd_pcm_lib_write1: avail = 448
snd_pcm_lib_write1: avail = 192
snd_pcm_lib_write1: avail = 0
underrun!!! (at least 18.479 ms long)
Any ideas or suggestions?
More information about the Alsa-devel
mailing list