Root/target/linux/xburst/patches-3.2/0016-ASoC-JZ4740-Support-buffer-size-that-is-not-a-multip.patch

1From 8a5087fe59e31efb8641e704058328997c3c8ff1 Mon Sep 17 00:00:00 2001
2From: Maarten ter Huurne <maarten@treewalker.org>
3Date: Wed, 10 Aug 2011 00:25:11 +0200
4Subject: [PATCH 16/28] ASoC: JZ4740: Support buffer size that is not a
5 multiple of period size.
6
7This fixes glitches triggered by libao, which sets time-based intervals
8instead of byte-based intervals like SDL does.
9
10Thanks to Paul Cercueil for figuring out that the buffer size was causing
11the glitches and to Lars Clausen for helping me write the fix.
12---
13 sound/soc/jz4740/jz4740-pcm.c | 21 ++++++++++++++++++---
14 1 files changed, 18 insertions(+), 3 deletions(-)
15
16diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
17index d1989cd..1f9a005 100644
18--- a/sound/soc/jz4740/jz4740-pcm.c
19+++ b/sound/soc/jz4740/jz4740-pcm.c
20@@ -31,6 +31,7 @@
21 
22 struct jz4740_runtime_data {
23     unsigned long dma_period;
24+ unsigned long dma_period_left;
25     dma_addr_t dma_start;
26     dma_addr_t dma_pos;
27     dma_addr_t dma_end;
28@@ -67,10 +68,13 @@ static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd,
29     if (prtd->dma_pos == prtd->dma_end)
30         prtd->dma_pos = prtd->dma_start;
31 
32- if (prtd->dma_pos + prtd->dma_period > prtd->dma_end)
33+ if (prtd->dma_period_left == 0)
34+ prtd->dma_period_left = prtd->dma_period;
35+
36+ if (prtd->dma_pos + prtd->dma_period_left > prtd->dma_end)
37         count = prtd->dma_end - prtd->dma_pos;
38     else
39- count = prtd->dma_period;
40+ count = prtd->dma_period_left;
41 
42     jz4740_dma_disable(prtd->dma);
43 
44@@ -85,6 +89,7 @@ static void jz4740_pcm_start_transfer(struct jz4740_runtime_data *prtd,
45     jz4740_dma_set_transfer_count(prtd->dma, count);
46 
47     prtd->dma_pos += count;
48+ prtd->dma_period_left -= count;
49 
50     jz4740_dma_enable(prtd->dma);
51 }
52@@ -96,7 +101,8 @@ static void jz4740_pcm_dma_transfer_done(struct jz4740_dma_chan *dma, int err,
53     struct snd_pcm_runtime *runtime = substream->runtime;
54     struct jz4740_runtime_data *prtd = runtime->private_data;
55 
56- snd_pcm_period_elapsed(substream);
57+ if (prtd->dma_period_left == 0)
58+ snd_pcm_period_elapsed(substream);
59 
60     jz4740_pcm_start_transfer(prtd, substream);
61 }
62@@ -133,6 +139,7 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
63     runtime->dma_bytes = params_buffer_bytes(params);
64 
65     prtd->dma_period = params_period_bytes(params);
66+ prtd->dma_period_left = 0;
67     prtd->dma_start = runtime->dma_addr;
68     prtd->dma_pos = prtd->dma_start;
69     prtd->dma_end = prtd->dma_start + runtime->dma_bytes;
70@@ -160,6 +167,7 @@ static int jz4740_pcm_prepare(struct snd_pcm_substream *substream)
71     if (!prtd->dma)
72         return -EBUSY;
73 
74+ prtd->dma_period_left = 0;
75     prtd->dma_pos = prtd->dma_start;
76 
77     return 0;
78@@ -219,6 +227,13 @@ static int jz4740_pcm_open(struct snd_pcm_substream *substream)
79     if (prtd == NULL)
80         return -ENOMEM;
81 
82+ /* Force period and buffer size to be a multiple of the DMA transfer
83+ * size, which is 16 bytes. */
84+ snd_pcm_hw_constraint_step(runtime, 0,
85+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
86+ snd_pcm_hw_constraint_step(runtime, 0,
87+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
88+
89     snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware);
90 
91     runtime->private_data = prtd;
92--
931.7.5.4
94
95

Archive Download this file



interactive