Date:2011-08-10 00:25:11 (12 years 1 month ago)
Author:Maarten ter Huurne
Commit:fcc71f3634c3aa6c77222256eb09b97f44dd5961
Message:ASoC: JZ4740: Support buffer size that is not a multiple of period size.

This fixes glitches triggered by libao, which sets time-based intervals
instead of byte-based intervals like SDL does.

Thanks to Paul Cercueil for figuring out that the buffer size was causing
the glitches and to Lars Clausen for helping me write the fix.
Files: sound/soc/jz4740/jz4740-pcm.c (7 diffs)

Change Details

sound/soc/jz4740/jz4740-pcm.c
3131
3232struct jz4740_runtime_data {
3333    unsigned long dma_period;
34    unsigned long dma_period_left;
3435    dma_addr_t dma_start;
3536    dma_addr_t dma_pos;
3637    dma_addr_t dma_end;
...... 
6768    if (prtd->dma_pos == prtd->dma_end)
6869        prtd->dma_pos = prtd->dma_start;
6970
70    if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
71    if (prtd->dma_period_left == 0)
72        prtd->dma_period_left = prtd->dma_period;
73
74    if (prtd->dma_pos + prtd->dma_period_left > prtd->dma_end)
7175        count = prtd->dma_end - prtd->dma_pos;
7276    else
73        count = prtd->dma_period;
77        count = prtd->dma_period_left;
7478
7579    jz4740_dma_disable(prtd->dma);
7680
...... 
8589    jz4740_dma_set_transfer_count(prtd->dma, count);
8690
8791    prtd->dma_pos += count;
92    prtd->dma_period_left -= count;
8893
8994    jz4740_dma_enable(prtd->dma);
9095}
...... 
96101    struct snd_pcm_runtime *runtime = substream->runtime;
97102    struct jz4740_runtime_data *prtd = runtime->private_data;
98103
99    snd_pcm_period_elapsed(substream);
104    if (prtd->dma_period_left == 0)
105        snd_pcm_period_elapsed(substream);
100106
101107    jz4740_pcm_start_transfer(prtd, substream);
102108}
...... 
133139    runtime->dma_bytes = params_buffer_bytes(params);
134140
135141    prtd->dma_period = params_period_bytes(params);
142    prtd->dma_period_left = 0;
136143    prtd->dma_start = runtime->dma_addr;
137144    prtd->dma_pos = prtd->dma_start;
138145    prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
...... 
160167    if (!prtd->dma)
161168        return -EBUSY;
162169
170    prtd->dma_period_left = 0;
163171    prtd->dma_pos = prtd->dma_start;
164172
165173    return 0;
...... 
219227    if (prtd == NULL)
220228        return -ENOMEM;
221229
230    /* Force period and buffer size to be a multiple of the DMA transfer
231     * size, which is 16 bytes. */
232    snd_pcm_hw_constraint_step(runtime, 0,
233                   SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
234    snd_pcm_hw_constraint_step(runtime, 0,
235                   SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
236
222237    snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
223238
224239    runtime->private_data = prtd;

Archive Download the corresponding diff file



interactive