diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-01-11 08:02:19 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-01-14 16:28:39 -0500 |
commit | 478028e088d6a94666d8a776be2cd2291faf3bbd (patch) | |
tree | 8bebc11e20820e4a61b1ccbe8dd7ab9881571a15 /sound/soc/soc-generic-dmaengine-pcm.c | |
parent | 93b943edfc5e439f7b843535e0bb0f7d2371f67f (diff) |
ASoC: generic-dmaengine-pcm: Check DMA residue granularity
The dmaengine framework now exposes the granularity with which it is able to
report the transfer residue for a certain DMA channel. Check the granularity in
the generic dmaengine PCM driver and
a) Set the SNDRV_PCM_INFO_BATCH if the granularity is per period or worse.
b) Fallback to the (race condition prone) period counting if the driver does
not support any residue reporting.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/soc-generic-dmaengine-pcm.c')
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 4e2bed89a4a4..560a7787d8a7 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -144,6 +144,8 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
144 | if (ret == 0) { | 144 | if (ret == 0) { |
145 | if (dma_caps.cmd_pause) | 145 | if (dma_caps.cmd_pause) |
146 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; | 146 | hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; |
147 | if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) | ||
148 | hw.info |= SNDRV_PCM_INFO_BATCH; | ||
147 | } | 149 | } |
148 | 150 | ||
149 | return snd_soc_set_runtime_hwparams(substream, &hw); | 151 | return snd_soc_set_runtime_hwparams(substream, &hw); |
@@ -187,6 +189,21 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( | |||
187 | dma_data->filter_data); | 189 | dma_data->filter_data); |
188 | } | 190 | } |
189 | 191 | ||
192 | static bool dmaengine_pcm_can_report_residue(struct dma_chan *chan) | ||
193 | { | ||
194 | struct dma_slave_caps dma_caps; | ||
195 | int ret; | ||
196 | |||
197 | ret = dma_get_slave_caps(chan, &dma_caps); | ||
198 | if (ret != 0) | ||
199 | return true; | ||
200 | |||
201 | if (dma_caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) | ||
202 | return false; | ||
203 | |||
204 | return true; | ||
205 | } | ||
206 | |||
190 | static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | 207 | static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) |
191 | { | 208 | { |
192 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); | 209 | struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); |
@@ -239,6 +256,16 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
239 | max_buffer_size); | 256 | max_buffer_size); |
240 | if (ret) | 257 | if (ret) |
241 | goto err_free; | 258 | goto err_free; |
259 | |||
260 | /* | ||
261 | * This will only return false if we know for sure that at least | ||
262 | * one channel does not support residue reporting. If the DMA | ||
263 | * driver does not implement the slave_caps API we rely having | ||
264 | * the NO_RESIDUE flag set manually in case residue reporting is | ||
265 | * not supported. | ||
266 | */ | ||
267 | if (!dmaengine_pcm_can_report_residue(pcm->chan[i])) | ||
268 | pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; | ||
242 | } | 269 | } |
243 | 270 | ||
244 | return 0; | 271 | return 0; |