All of lore.kernel.org
 help / color / mirror / Atom feed
* alsa buffer underrun
@ 2009-10-20  4:39 邱昇譽
  0 siblings, 0 replies; only message in thread
From: 邱昇譽 @ 2009-10-20  4:39 UTC (permalink / raw)
  To: alsa-devel

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?

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-10-20  4:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-20  4:39 alsa buffer underrun 邱昇譽

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.