diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2013-04-15 19:19:51 +0200 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-04-17 14:21:36 +0100 |
commit | c999836d37c6c1125e856f68877ae13952baa61a (patch) | |
tree | 77ca9109474b59a6a811e36784f3fed5b3458a2e /sound/soc | |
parent | 28c4468b00a1e55e08cc20117de968f7c6275441 (diff) |
ASoC: dmaengine_pcm: Add support for compat platforms
Add support for platforms which don't use devicetree yet or have to optionally
support a non-devicetree way to request the DMA channel. The patch adds the
compat_request_channel and compat_filter_fn callbacks to the
snd_dmaengine_pcm_config struct. If the compat_request_channel is implemented it
will be used to request the DMA channel. If not dma_request_channel with
compat_filter_fn as the filter function will be used to request the channel.
The patch also exports the snd_dmaengine_pcm_request_chan() function, since
compat platforms will want to use it to request their DMA channel.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Tested-by: Stephen Warren <swarren@nvidia.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/soc-dmaengine-pcm.c | 14 | ||||
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 32 |
2 files changed, 39 insertions, 7 deletions
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c index b0420a75f41..aa924d9b798 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/soc/soc-dmaengine-pcm.c @@ -254,7 +254,16 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream) } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer); -static struct dma_chan *dmaengine_pcm_request_channel(dma_filter_fn filter_fn, +/** + * snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM + * @filter_fn: Filter function used to request the DMA channel + * @filter_data: Data passed to the DMA filter function + * + * Returns NULL or the requested DMA channel. + * + * This function request a DMA channel for usage with dmaengine PCM. + */ +struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, void *filter_data) { dma_cap_mask_t mask; @@ -265,6 +274,7 @@ static struct dma_chan *dmaengine_pcm_request_channel(dma_filter_fn filter_fn, return dma_request_channel(mask, filter_fn, filter_data); } +EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); /** * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream @@ -320,7 +330,7 @@ int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, dma_filter_fn filter_fn, void *filter_data) { return snd_dmaengine_pcm_open(substream, - dmaengine_pcm_request_channel(filter_fn, filter_data)); + snd_dmaengine_pcm_request_channel(filter_fn, filter_data)); } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index acfc9269899..d6e63805638 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -29,6 +29,7 @@ struct dmaengine_pcm { struct dma_chan *chan[SNDRV_PCM_STREAM_CAPTURE + 1]; const struct snd_dmaengine_pcm_config *config; struct snd_soc_platform platform; + bool compat; }; static struct dmaengine_pcm *soc_platform_to_pcm(struct snd_soc_platform *p) @@ -121,6 +122,19 @@ static void dmaengine_pcm_free(struct snd_pcm *pcm) snd_pcm_lib_preallocate_free_for_all(pcm); } +static struct dma_chan *dmaengine_pcm_compat_request_channel( + struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_substream *substream) +{ + struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); + + if (pcm->config->compat_request_channel) + return pcm->config->compat_request_channel(rtd, substream); + + return snd_dmaengine_pcm_request_channel(pcm->config->compat_filter_fn, + snd_soc_dai_get_dma_data(rtd->cpu_dai, substream)); +} + static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct dmaengine_pcm *pcm = soc_platform_to_pcm(rtd->platform); @@ -134,6 +148,11 @@ static int dmaengine_pcm_new(struct snd_soc_pcm_runtime *rtd) if (!substream) continue; + if (!pcm->chan[i] && pcm->compat) { + pcm->chan[i] = dmaengine_pcm_compat_request_channel(rtd, + substream); + } + if (!pcm->chan[i]) { dev_err(rtd->platform->dev, "Missing dma channel for stream: %d\n", i); @@ -171,6 +190,7 @@ static const struct snd_soc_platform_driver dmaengine_pcm_platform = { .ops = &dmaengine_pcm_ops, .pcm_new = dmaengine_pcm_new, .pcm_free = dmaengine_pcm_free, + .probe_order = SND_SOC_COMP_ORDER_LATE, }; static const char * const dmaengine_pcm_dma_channel_names[] = { @@ -190,18 +210,20 @@ int snd_dmaengine_pcm_register(struct device *dev, struct dmaengine_pcm *pcm; unsigned int i; - if (!dev->of_node) - return -EINVAL; - pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); if (!pcm) return -ENOMEM; pcm->config = config; - for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { - pcm->chan[i] = of_dma_request_slave_channel(dev->of_node, + if (flags & SND_DMAENGINE_PCM_FLAG_COMPAT) + pcm->compat = true; + + if (!(flags & SND_DMAENGINE_PCM_FLAG_NO_DT) && dev->of_node) { + for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { + pcm->chan[i] = of_dma_request_slave_channel(dev->of_node, dmaengine_pcm_dma_channel_names[i]); + } } return snd_soc_add_platform(dev, &pcm->platform, |