Skip to content

Commit

Permalink
ASoC: generic-dmaengine-pcm: Check DMA residue granularity
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Lars-Peter Clausen authored and Mark Brown committed Jan 14, 2014
1 parent 93b943e commit 478028e
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions sound/soc/soc-generic-dmaengine-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 478028e

Please sign in to comment.