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 | ||
---|---|---|
31 | 31 | |
32 | 32 | struct jz4740_runtime_data { |
33 | 33 | unsigned long dma_period; |
34 | unsigned long dma_period_left; | |
34 | 35 | dma_addr_t dma_start; |
35 | 36 | dma_addr_t dma_pos; |
36 | 37 | dma_addr_t dma_end; |
... | ... | |
67 | 68 | if (prtd->dma_pos == prtd->dma_end) |
68 | 69 | prtd->dma_pos = prtd->dma_start; |
69 | 70 | |
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) | |
71 | 75 | count = prtd->dma_end - prtd->dma_pos; |
72 | 76 | else |
73 | count = prtd->dma_period; | |
77 | count = prtd->dma_period_left; | |
74 | 78 | |
75 | 79 | jz4740_dma_disable(prtd->dma); |
76 | 80 | |
... | ... | |
85 | 89 | jz4740_dma_set_transfer_count(prtd->dma, count); |
86 | 90 | |
87 | 91 | prtd->dma_pos += count; |
92 | prtd->dma_period_left -= count; | |
88 | 93 | |
89 | 94 | jz4740_dma_enable(prtd->dma); |
90 | 95 | } |
... | ... | |
96 | 101 | struct snd_pcm_runtime *runtime = substream->runtime; |
97 | 102 | struct jz4740_runtime_data *prtd = runtime->private_data; |
98 | 103 | |
99 | snd_pcm_period_elapsed(substream); | |
104 | if (prtd->dma_period_left == 0) | |
105 | snd_pcm_period_elapsed(substream); | |
100 | 106 | |
101 | 107 | jz4740_pcm_start_transfer(prtd, substream); |
102 | 108 | } |
... | ... | |
133 | 139 | runtime->dma_bytes = params_buffer_bytes(params); |
134 | 140 | |
135 | 141 | prtd->dma_period = params_period_bytes(params); |
142 | prtd->dma_period_left = 0; | |
136 | 143 | prtd->dma_start = runtime->dma_addr; |
137 | 144 | prtd->dma_pos = prtd->dma_start; |
138 | 145 | prtd->dma_end = prtd->dma_start + runtime->dma_bytes; |
... | ... | |
160 | 167 | if (!prtd->dma) |
161 | 168 | return -EBUSY; |
162 | 169 | |
170 | prtd->dma_period_left = 0; | |
163 | 171 | prtd->dma_pos = prtd->dma_start; |
164 | 172 | |
165 | 173 | return 0; |
... | ... | |
219 | 227 | if (prtd == NULL) |
220 | 228 | return -ENOMEM; |
221 | 229 | |
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 | ||
222 | 237 | snd_soc_set_runtime_hwparams(substream, &jz4740_pcm_hardware); |
223 | 238 | |
224 | 239 | runtime->private_data = prtd; |
Branches:
ben-wpan
ben-wpan-stefan
5396a9238205f20f811ea57898980d3ca82df0b6
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9