Commit 3c19a0a2bdb31beed5da10caab1323aeb924cee3
Exists in
master
and in
16 other branches
Merge remote-tracking branch 'asoc/fix/dma' into asoc-linus
Showing 1 changed file Side-by-side Diff
sound/soc/soc-generic-dmaengine-pcm.c
... | ... | @@ -305,6 +305,20 @@ |
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 | 323 | * snd_dmaengine_pcm_register - Register a dmaengine based PCM device |
310 | 324 | * @dev: The parent device for the PCM device |
... | ... | @@ -315,6 +329,7 @@ |
315 | 329 | const struct snd_dmaengine_pcm_config *config, unsigned int flags) |
316 | 330 | { |
317 | 331 | struct dmaengine_pcm *pcm; |
332 | + int ret; | |
318 | 333 | |
319 | 334 | pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); |
320 | 335 | if (!pcm) |
321 | 336 | |
322 | 337 | |
... | ... | @@ -326,11 +341,20 @@ |
326 | 341 | dmaengine_pcm_request_chan_of(pcm, dev); |
327 | 342 | |
328 | 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 | 345 | &dmaengine_no_residue_pcm_platform); |
331 | 346 | else |
332 | - return snd_soc_add_platform(dev, &pcm->platform, | |
347 | + ret = snd_soc_add_platform(dev, &pcm->platform, | |
333 | 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 | 359 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); |
336 | 360 | |
... | ... | @@ -345,7 +369,6 @@ |
345 | 369 | { |
346 | 370 | struct snd_soc_platform *platform; |
347 | 371 | struct dmaengine_pcm *pcm; |
348 | - unsigned int i; | |
349 | 372 | |
350 | 373 | platform = snd_soc_lookup_platform(dev); |
351 | 374 | if (!platform) |
352 | 375 | |
... | ... | @@ -353,15 +376,8 @@ |
353 | 376 | |
354 | 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 | 379 | snd_soc_remove_platform(platform); |
380 | + dmaengine_pcm_release_chan(pcm); | |
365 | 381 | kfree(pcm); |
366 | 382 | } |
367 | 383 | EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); |