ASoC: mxs-pcm: Request DMA channel early
authorLars-Peter Clausen <lars@metafoo.de>
Wed, 22 Feb 2012 09:49:07 +0000 (10:49 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 22 Feb 2012 13:21:49 +0000 (13:21 +0000)
Request the DMA channel in the PCM open callback instead of the hwparams
callback, this allows us to let open fail if no dma channel is available. This
also fixes a bug where the channel will be requested multiple times if hwparams
is called multiple times.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
sound/soc/mxs/mxs-pcm.c

index 06c18ecffbb437eb49910dfe445eaf89e0ccd8a2..5b8c8d3140605e8a53b109fc0219ed7755f2718b 100644 (file)
@@ -85,8 +85,7 @@ static bool filter(struct dma_chan *chan, void *param)
        return true;
 }
 
-static int mxs_dma_alloc(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *params)
+static int mxs_dma_alloc(struct snd_pcm_substream *substream)
 {
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -112,11 +111,7 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
        struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
        unsigned long dma_addr;
        struct dma_chan *chan;
-       int ret;
 
-       ret = mxs_dma_alloc(substream, params);
-       if (ret)
-               return ret;
        chan = iprtd->dma_chan;
 
        iprtd->periods = params_periods(params);
@@ -143,19 +138,6 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_mxs_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
-
-       if (iprtd->dma_chan) {
-               dma_release_channel(iprtd->dma_chan);
-               iprtd->dma_chan = NULL;
-       }
-
-       return 0;
-}
-
 static int snd_mxs_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -208,6 +190,12 @@ static int snd_mxs_open(struct snd_pcm_substream *substream)
                return ret;
        }
 
+       ret = mxs_dma_alloc(substream);
+       if (ret) {
+               kfree(iprtd);
+               return ret;
+       }
+
        snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
 
        return 0;
@@ -218,6 +206,7 @@ static int snd_mxs_close(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct mxs_pcm_runtime_data *iprtd = runtime->private_data;
 
+       dma_release_channel(iprtd->dma_chan);
        kfree(iprtd);
 
        return 0;
@@ -239,7 +228,6 @@ static struct snd_pcm_ops mxs_pcm_ops = {
        .close          = snd_mxs_close,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = snd_mxs_pcm_hw_params,
-       .hw_free        = snd_mxs_pcm_hw_free,
        .trigger        = snd_mxs_pcm_trigger,
        .pointer        = snd_mxs_pcm_pointer,
        .mmap           = snd_mxs_pcm_mmap,