diff options
| -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 cbc9c96ce1f4..41949af3baae 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
| @@ -305,6 +305,20 @@ static void dmaengine_pcm_request_chan_of(struct dmaengine_pcm *pcm, | |||
| 305 | } | 305 | } |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | static void dmaengine_pcm_release_chan(struct dmaengine_pcm *pcm) | ||
| 309 | { | ||
| 310 | unsigned int i; | ||
| 311 | |||
| 312 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; | ||
| 313 | i++) { | ||
| 314 | if (!pcm->chan[i]) | ||
| 315 | continue; | ||
| 316 | dma_release_channel(pcm->chan[i]); | ||
| 317 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
| 318 | break; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 308 | /** | 322 | /** |
| 309 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device | 323 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device |
| 310 | * @dev: The parent device for the PCM device | 324 | * @dev: The parent device for the PCM device |
| @@ -315,6 +329,7 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
| 315 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) | 329 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) |
| 316 | { | 330 | { |
| 317 | struct dmaengine_pcm *pcm; | 331 | struct dmaengine_pcm *pcm; |
| 332 | int ret; | ||
| 318 | 333 | ||
| 319 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); | 334 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
| 320 | if (!pcm) | 335 | if (!pcm) |
| @@ -326,11 +341,20 @@ int snd_dmaengine_pcm_register(struct device *dev, | |||
| 326 | dmaengine_pcm_request_chan_of(pcm, dev); | 341 | dmaengine_pcm_request_chan_of(pcm, dev); |
| 327 | 342 | ||
| 328 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) | 343 | if (flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE) |
| 329 | return snd_soc_add_platform(dev, &pcm->platform, | 344 | ret = snd_soc_add_platform(dev, &pcm->platform, |
| 330 | &dmaengine_no_residue_pcm_platform); | 345 | &dmaengine_no_residue_pcm_platform); |
| 331 | else | 346 | else |
| 332 | return snd_soc_add_platform(dev, &pcm->platform, | 347 | ret = snd_soc_add_platform(dev, &pcm->platform, |
| 333 | &dmaengine_pcm_platform); | 348 | &dmaengine_pcm_platform); |
| 349 | if (ret) | ||
| 350 | goto err_free_dma; | ||
| 351 | |||
| 352 | return 0; | ||
| 353 | |||
| 354 | err_free_dma: | ||
| 355 | dmaengine_pcm_release_chan(pcm); | ||
| 356 | kfree(pcm); | ||
| 357 | return ret; | ||
| 334 | } | 358 | } |
| 335 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); | 359 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); |
| 336 | 360 | ||
| @@ -345,7 +369,6 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
| 345 | { | 369 | { |
| 346 | struct snd_soc_platform *platform; | 370 | struct snd_soc_platform *platform; |
| 347 | struct dmaengine_pcm *pcm; | 371 | struct dmaengine_pcm *pcm; |
| 348 | unsigned int i; | ||
| 349 | 372 | ||
| 350 | platform = snd_soc_lookup_platform(dev); | 373 | platform = snd_soc_lookup_platform(dev); |
| 351 | if (!platform) | 374 | if (!platform) |
| @@ -353,15 +376,8 @@ void snd_dmaengine_pcm_unregister(struct device *dev) | |||
| 353 | 376 | ||
| 354 | pcm = soc_platform_to_pcm(platform); | 377 | pcm = soc_platform_to_pcm(platform); |
| 355 | 378 | ||
| 356 | for (i = SNDRV_PCM_STREAM_PLAYBACK; i <= SNDRV_PCM_STREAM_CAPTURE; i++) { | ||
| 357 | if (pcm->chan[i]) { | ||
| 358 | dma_release_channel(pcm->chan[i]); | ||
| 359 | if (pcm->flags & SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX) | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | snd_soc_remove_platform(platform); | 379 | snd_soc_remove_platform(platform); |
| 380 | dmaengine_pcm_release_chan(pcm); | ||
| 365 | kfree(pcm); | 381 | kfree(pcm); |
| 366 | } | 382 | } |
| 367 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); | 383 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); |
