diff options
author | Mark Brown <broonie@linaro.org> | 2013-12-09 13:44:55 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-12-09 13:44:55 -0500 |
commit | a715d01e9c8177634bd7c22e67c9088282744569 (patch) | |
tree | cd496ee4ca3775e3df76c1dcc8999bcf1335a57e | |
parent | 11b3a7add2841aa698aa0a32396b6db413c22eda (diff) | |
parent | 6b9f3e65282b3bd7ed77e7b2b1edfe7cfed48115 (diff) |
Merge remote-tracking branch 'asoc/fix/dma' into asoc-dma
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index fbc28a799e06..1cb3494cf278 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -313,6 +313,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, | |||
313 | pcm->chan[1] = pcm->chan[0]; | 313 | pcm->chan[1] = pcm->chan[0]; |
314 | } | 314 | } |
315 | 315 | ||
316 | static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) | ||
317 | { | ||
318 | unsigned int i; | ||
319 | |||
320 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; | ||
321 | i++) { | ||
322 | if (!pcm->chan[i]) | ||
323 | continue; | ||
324 | dma_release_channel(pcm->chan[i]); | ||
325 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
326 | break; | ||
327 | } | ||
328 | } | ||
329 | |||
316 | /** | 330 | /** |
317 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device | 331 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device |
318 | * @dev: The parent device for the PCM device | 332 | * @dev: The parent device for the PCM device |
@@ -323,6 +337,7 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
323 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) | 337 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) |
324 | { | 338 | { |
325 | struct dmaengine_pcm *pcm; | 339 | struct dmaengine_pcm *pcm; |
340 | int ret; | ||
326 | 341 | ||
327 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 342 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
328 | if (!pcm) | 343 | if (!pcm) |
@@ -334,11 +349,20 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
334 | dmaengine_pcm_request_chan_of(pcm, dev); | 349 | dmaengine_pcm_request_chan_of(pcm, dev); |
335 | 350 | ||
336 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | 351 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) |
337 | return snd_soc_add_platform(dev, &pcm->platform, | 352 | ret = snd_soc_add_platform(dev, &pcm->platform, |
338 | &dmaengine_no_residue_pcm_platform); | 353 | &dmaengine_no_residue_pcm_platform); |
339 | else | 354 | else |
340 | return snd_soc_add_platform(dev, &pcm->platform, | 355 | ret = snd_soc_add_platform(dev, &pcm->platform, |
341 | &dmaengine_pcm_platform); | 356 | &dmaengine_pcm_platform); |
357 | if (ret) | ||
358 | goto err_free_dma; | ||
359 | |||
360 | return 0; | ||
361 | |||
362 | err_free_dma: | ||
363 | dmaengine_pcm_release_chan(pcm); | ||
364 | kfree(pcm); | ||
365 | return ret; | ||
342 | } | 366 | } |
343 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); | 367 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); |
344 | 368 | ||
@@ -353,7 +377,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
353 | { | 377 | { |
354 | struct snd_soc_platform *platform; | 378 | struct snd_soc_platform *platform; |
355 | struct dmaengine_pcm *pcm; | 379 | struct dmaengine_pcm *pcm; |
356 | unsigned int i; | ||
357 | 380 | ||
358 | platform = snd_soc_lookup_platform(dev); | 381 | platform = snd_soc_lookup_platform(dev); |
359 | if (!platform) | 382 | if (!platform) |
@@ -361,15 +384,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
361 | 384 | ||
362 | pcm = soc_platform_to_pcm(platform); | 385 | pcm = soc_platform_to_pcm(platform); |
363 | 386 | ||
364 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
365 | if (pcm->chan[i]) { | ||
366 | dma_release_channel(pcm->chan[i]); | ||
367 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
368 | break; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | snd_soc_remove_platform(platform); | 387 | snd_soc_remove_platform(platform); |
388 | dmaengine_pcm_release_chan(pcm); | ||
373 | kfree(pcm); | 389 | kfree(pcm); |
374 | } | 390 | } |
375 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); | 391 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); |