diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-12-10 11:11:02 -0700 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-12-11 11:15:05 +0000 |
commit | 5eda87b890f867b098e5566b5543642851e8b9c3 (patch) | |
tree | 5edf24b4a89f7f9893701dedd96dea7c083402ea /sound | |
parent | d3ae8835301043ed84c8e78ecb06d5f0b0548f4a (diff) | |
download | linux-stable-5eda87b890f867b098e5566b5543642851e8b9c3.tar.gz linux-stable-5eda87b890f867b098e5566b5543642851e8b9c3.tar.bz2 linux-stable-5eda87b890f867b098e5566b5543642851e8b9c3.zip |
ASoC: dmaengine: support deferred probe for DMA channels
Enhance dmaengine_pcm_request_chan_of() to support deferred probe for
DMA channels, by using the new dma_request_slave_channel_or_err() API.
This prevents snd_dmaengine_pcm_register() from succeeding without
acquiring DMA channels due to the relevant DMA controller not yet being
registered.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 5b70c556fba3..585eaa69e8c3 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -287,16 +287,17 @@ static const char * const dmaengine_pcm_dma_channel_names[] = { [SNDRV_PCM_STREAM_CAPTURE] = "rx", }; -static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, +static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, struct device *dev, const struct snd_dmaengine_pcm_config *config) { unsigned int i; const char *name; + struct dma_chan *chan; if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || !dev->of_node) - return; + return 0; if (config->dma_dev) { /* @@ -318,13 +319,22 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, name = dmaengine_pcm_dma_channel_names[i]; if (config->chan_names[i]) name = config->chan_names[i]; - pcm->chan[i] = dma_request_slave_channel(dev, name); + chan = dma_request_slave_channel_reason(dev, name); + if (IS_ERR(chan)) { + if (PTR_ERR(pcm->chan[i]) == -EPROBE_DEFER) + return -EPROBE_DEFER; + pcm->chan[i] = NULL; + } else { + pcm->chan[i] = chan; + } if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) break; } if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) pcm->chan[1] = pcm->chan[0]; + + return 0; } static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) @@ -360,7 +370,9 @@ int snd_dmaengine_pcm_register(struct device *dev, pcm->config = config; pcm->flags = flags; - dmaengine_pcm_request_chan_of(pcm, dev, config); + ret = dmaengine_pcm_request_chan_of(pcm, dev, config); + if (ret) + goto err_free_dma; if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) ret = snd_soc_add_platform(dev, &pcm->platform, |