diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2014-01-11 14:02:19 +0100 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-01-14 21:28:39 +0000 |
commit | 478028e088d6a94666d8a776be2cd2291faf3bbd (patch) | |
tree | 8bebc11e20820e4a61b1ccbe8dd7ab9881571a15 /sound/soc | |
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')
-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 4e2bed89a4a..560a7787d8a 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 if (ret == 0) { if (dma_caps.cmd_pause) hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; + if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT) + hw.info |= SNDRV_PCM_INFO_BATCH; } return snd_soc_set_runtime_hwparams(substream, &hw); @@ -187,6 +189,21 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( dma_data->filter_data); } +static bool dmaengine_pcm_can_report_residue(struct dma_chan *chan) +{ + struct dma_slave_caps dma_caps; + int ret; + + ret = dma_get_slave_caps(chan, &dma_caps); + if (ret != 0) + return true; + + if (dma_caps.residue_granularity == DMA_RESIDUE_GRANULARITY_DESCRIPTOR) + return false; + + return true; +} + static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) { 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) max_buffer_size); if (ret) goto err_free; + + /* + * This will only return false if we know for sure that at least + * one channel does not support residue reporting. If the DMA + * driver does not implement the slave_caps API we rely having + * the NO_RESIDUE flag set manually in case residue reporting is + * not supported. + */ + if (!dmaengine_pcm_can_report_residue(pcm->chan[i])) + pcm->flags |= SND_DMAENGINE_PCM_FLAG_NO_RESIDUE; } return 0; |