summaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-generic-dmaengine-pcm.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-12-10 19:11:02 +0100
committerMark Brown <broonie@linaro.org>2013-12-11 12:15:05 +0100
commit5eda87b890f867b098e5566b5543642851e8b9c3 (patch)
tree5edf24b4a89f7f9893701dedd96dea7c083402ea /sound/soc/soc-generic-dmaengine-pcm.c
parentMerge branch 'topic/defer_probe' of git://git.infradead.org/users/vkoul/slave... (diff)
downloadlinux-5eda87b890f867b098e5566b5543642851e8b9c3.tar.xz
linux-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 '')
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c20
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,