aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-generic-dmaengine-pcm.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2013-12-10 13:11:02 -0500
committerMark Brown <broonie@linaro.org>2013-12-11 06:15:05 -0500
commit5eda87b890f867b098e5566b5543642851e8b9c3 (patch)
tree5edf24b4a89f7f9893701dedd96dea7c083402ea /sound/soc/soc-generic-dmaengine-pcm.c
parentd3ae8835301043ed84c8e78ecb06d5f0b0548f4a (diff)
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/soc/soc-generic-dmaengine-pcm.c')
-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[] = {
287 [SNDRV_PCM_STREAM_CAPTURE] = "rx", 287 [SNDRV_PCM_STREAM_CAPTURE] = "rx",
288}; 288};
289 289
290static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, 290static int dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
291 struct device *dev, const struct snd_dmaengine_pcm_config *config) 291 struct device *dev, const struct snd_dmaengine_pcm_config *config)
292{ 292{
293 unsigned int i; 293 unsigned int i;
294 const char *name; 294 const char *name;
295 struct dma_chan *chan;
295 296
296 if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT | 297 if ((pcm->flags & (SND_DMAENGINE_PCM_FLAG_NO_DT |
297 SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) || 298 SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME)) ||
298 !dev->of_node) 299 !dev->of_node)
299 return; 300 return 0;
300 301
301 if (config->dma_dev) { 302 if (config->dma_dev) {
302 /* 303 /*
@@ -318,13 +319,22 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm,
318 name = dmaengine_pcm_dma_channel_names[i]; 319 name = dmaengine_pcm_dma_channel_names[i];
319 if (config->chan_names[i]) 320 if (config->chan_names[i])
320 name = config->chan_names[i]; 321 name = config->chan_names[i];
321 pcm->chan[i] = dma_request_slave_channel(dev, name); 322 chan = dma_request_slave_channel_reason(dev, name);
323 if (IS_ERR(chan)) {
324 if (PTR_ERR(pcm->chan[i]) == -EPROBE_DEFER)
325 return -EPROBE_DEFER;
326 pcm->chan[i] = NULL;
327 } else {
328 pcm->chan[i] = chan;
329 }
322 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) 330 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
323 break; 331 break;
324 } 332 }
325 333
326 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) 334 if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX)
327 pcm->chan[1] = pcm->chan[0]; 335 pcm->chan[1] = pcm->chan[0];
336
337 return 0;
328} 338}
329 339
330static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) 340static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm)
@@ -360,7 +370,9 @@ int snd_dmaengine_pcm_register(struct device *dev,
360 pcm->config = config; 370 pcm->config = config;
361 pcm->flags = flags; 371 pcm->flags = flags;
362 372
363 dmaengine_pcm_request_chan_of(pcm, dev, config); 373 ret = dmaengine_pcm_request_chan_of(pcm, dev, config);
374 if (ret)
375 goto err_free_dma;
364 376
365 if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) 377 if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
366 ret = snd_soc_add_platform(dev, &pcm->platform, 378 ret = snd_soc_add_platform(dev, &pcm->platform,