aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@linaro.org>2013-12-09 13:44:55 -0500
committerMark Brown <broonie@linaro.org>2013-12-09 13:44:55 -0500
commita715d01e9c8177634bd7c22e67c9088282744569 (patch)
treecd496ee4ca3775e3df76c1dcc8999bcf1335a57e
parent11b3a7add2841aa698aa0a32396b6db413c22eda (diff)
parent6b9f3e65282b3bd7ed77e7b2b1edfe7cfed48115 (diff)
Merge remote-tracking branch 'asoc/fix/dma' into asoc-dma
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c38
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
316static 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
362err_free_dma:
363 dmaengine_pcm_release_chan(pcm);
364 kfree(pcm);
365 return ret;
342} 366}
343EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_register); 367EXPORT_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}
375EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); 391EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister);