Commit 478028e0 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Mark Brown

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: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 93b943ed
...@@ -144,6 +144,8 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea ...@@ -144,6 +144,8 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
if (ret == 0) { if (ret == 0) {
if (dma_caps.cmd_pause) if (dma_caps.cmd_pause)
hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME; 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); return snd_soc_set_runtime_hwparams(substream, &hw);
...@@ -187,6 +189,21 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel( ...@@ -187,6 +189,21 @@ static struct dma_chan *dmaengine_pcm_compat_request_channel(
dma_data->filter_data); 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) static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
{ {
struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); 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,6 +256,16 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd)
max_buffer_size); max_buffer_size);
if (ret) if (ret)
goto err_free; 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; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment