ASoC: dmaengine-pcm: Make requesting the DMA channel at PCM open optional
authorLars-Peter Clausen <lars@metafoo.de>
Mon, 15 Apr 2013 17:19:48 +0000 (19:19 +0200)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 17 Apr 2013 13:17:54 +0000 (14:17 +0100)
Refactor the dmaengine PCM library to allow the DMA channel to be requested
before opening a PCM substream. snd_dmaengine_pcm_open() now expects a DMA
channel instead of a filter function and filter parameter as its parameters.
snd_dmaengine_pcm_close() is updated to not release the DMA channel. This allows
a dmaengine based PCM driver to request its channels before the substream is
opened.

The patch also introduces two new functions, snd_dmaengine_pcm_open_request_chan()
and snd_dmaengine_pcm_close_release_chan(), which have the same signature and
behaviour of the old snd_dmaengine_pcm_{open,close}() and internally use the new
variants of these functions. All users of snd_dmaengine_pcm_{open,close}() are
updated to use snd_dmaengine_pcm_open_request_chan() and
snd_dmaengine_pcm_close_release_chan().

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Tested-by: Stephen Warren <swarren@nvidia.com>
Tested-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/sound/dmaengine_pcm.h
sound/soc/atmel/atmel-pcm-dma.c
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/fsl/imx-pcm-dma.c
sound/soc/mxs/mxs-pcm.c
sound/soc/omap/omap-pcm.c
sound/soc/pxa/mmp-pcm.c
sound/soc/soc-dmaengine-pcm.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/tegra_pcm.c
sound/soc/ux500/ux500_pcm.c

index 95620428a59b840f022d8798136d8828bc1da9aa..d015d67e75c3bef118c257219b38c812a502fffb 100644 (file)
@@ -39,9 +39,13 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
 snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream *substream);
 
 int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
-       dma_filter_fn filter_fn, void *filter_data);
+       struct dma_chan *chan);
 int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
 
+int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
+       dma_filter_fn filter_fn, void *filter_data);
+int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);
+
 struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream);
 
 /**
index bb07989762d5be6ac5be6bb8cb75c2a630090173..1d38fd0bc4e26bd49772d7e030efb7e283e5687f 100644 (file)
@@ -155,7 +155,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
        if (ssc->pdev)
                sdata = ssc->pdev->dev.platform_data;
 
-       ret = snd_dmaengine_pcm_open(substream, filter, sdata);
+       ret = snd_dmaengine_pcm_open_request_chan(substream, filter, sdata);
        if (ret) {
                pr_err("atmel-pcm: dmaengine pcm open failed\n");
                return -EINVAL;
@@ -171,7 +171,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
 
        return 0;
 err:
-       snd_dmaengine_pcm_close(substream);
+       snd_dmaengine_pcm_close_release_chan(substream);
        return ret;
 }
 
@@ -197,7 +197,7 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
 
 static struct snd_pcm_ops atmel_pcm_ops = {
        .open           = atmel_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = atmel_pcm_hw_params,
        .prepare        = atmel_pcm_dma_prepare,
index 298946f790eba8c8c9b420fe6b32af98708d2aaa..48803269037847ef7ad272fc07d61dc6d6590d0f 100644 (file)
@@ -69,7 +69,8 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
 
        snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
 
-       return snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter,
+       return snd_dmaengine_pcm_open_request_chan(substream,
+                       ep93xx_pcm_dma_filter,
                        snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
 }
 
@@ -100,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops ep93xx_pcm_ops = {
        .open           = ep93xx_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = ep93xx_pcm_hw_params,
        .hw_free        = ep93xx_pcm_hw_free,
index ee838c8a3b1168fe664285c5be61a7e3e5d92c97..c6647825bdd55290308c71708edf993d3e9444d1 100644 (file)
@@ -100,7 +100,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream)
 
 static struct snd_pcm_ops imx_pcm_ops = {
        .open           = snd_imx_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = snd_imx_pcm_hw_params,
        .trigger        = snd_dmaengine_pcm_trigger,
index ebbef8597554e27fe2575b14ea01f6c46392c724..7bceb16d0fd95f8c18ea4da0a66cf8bdb377a9ac 100644 (file)
@@ -87,7 +87,7 @@ static int snd_mxs_open(struct snd_pcm_substream *substream)
 
        snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
 
-       return snd_dmaengine_pcm_open(substream, filter,
+       return snd_dmaengine_pcm_open_request_chan(substream, filter,
                snd_soc_dai_get_dma_data(rtd->cpu_dai, substream));
 }
 
@@ -104,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops mxs_pcm_ops = {
        .open           = snd_mxs_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = snd_mxs_pcm_hw_params,
        .trigger        = snd_dmaengine_pcm_trigger,
index c8e272f9c2de0be4a14fbcbad07b46b7aad2d8f4..c28e042f2208175fa73d07d51587cf6bec150ac4 100644 (file)
@@ -118,8 +118,9 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)
 
        dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
-       return snd_dmaengine_pcm_open(substream, omap_dma_filter_fn,
-                                     dma_data->filter_data);
+       return snd_dmaengine_pcm_open_request_chan(substream,
+                                                  omap_dma_filter_fn,
+                                                  dma_data->filter_data);
 }
 
 static int omap_pcm_mmap(struct snd_pcm_substream *substream,
@@ -135,7 +136,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops omap_pcm_ops = {
        .open           = omap_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = omap_pcm_hw_params,
        .hw_free        = omap_pcm_hw_free,
index 6c3980252bf6f0a98e04bfce072bfc0c3bdd19c9..3499300152648599d0ef8f38abcd63bbfd322c75 100644 (file)
@@ -131,7 +131,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
        dma_data.dma_res = r;
        dma_data.ssp_id = cpu_dai->id;
 
-       return snd_dmaengine_pcm_open(substream, filter, &dma_data);
+       return snd_dmaengine_pcm_open_request_chan(substream, filter,
+                   &dma_data);
 }
 
 static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
@@ -148,7 +149,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
 
 struct snd_pcm_ops mmp_pcm_ops = {
        .open           = mmp_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = mmp_pcm_hw_params,
        .trigger        = snd_dmaengine_pcm_trigger,
index a9a300acb506fafabe55490fb0f32b397c8ceff4..b0420a75f4120788b6ad10e74838a25053deb12c 100644 (file)
@@ -254,44 +254,38 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
 
-static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
-       dma_filter_fn filter_fn, void *filter_data)
+static struct dma_chan *dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
+       void *filter_data)
 {
        dma_cap_mask_t mask;
 
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
        dma_cap_set(DMA_CYCLIC, mask);
-       prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
-
-       if (!prtd->dma_chan)
-               return -ENXIO;
 
-       return 0;
+       return dma_request_channel(mask, filter_fn, filter_data);
 }
 
 /**
  * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
  * @substream: PCM substream
- * @filter_fn: Filter function used to request the DMA channel
- * @filter_data: Data passed to the DMA filter function
+ * @chan: DMA channel to use for data transfers
  *
  * Returns 0 on success, a negative error code otherwise.
  *
- * This function will request a DMA channel using the passed filter function and
- * data. The function should usually be called from the pcm open callback.
- *
- * Note that this function will use private_data field of the substream's
- * runtime. So it is not availabe to your pcm driver implementation. If you need
- * to keep additional data attached to a substream use
- * snd_dmaengine_pcm_{set,get}_data.
+ * The function should usually be called from the pcm open callback. Note that
+ * this function will use private_data field of the substream's runtime. So it
+ * is not availabe to your pcm driver implementation.
  */
 int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
-       dma_filter_fn filter_fn, void *filter_data)
+       struct dma_chan *chan)
 {
        struct dmaengine_pcm_runtime_data *prtd;
        int ret;
 
+       if (!chan)
+               return -ENXIO;
+
        ret = snd_pcm_hw_constraint_integer(substream->runtime,
                                            SNDRV_PCM_HW_PARAM_PERIODS);
        if (ret < 0)
@@ -301,11 +295,7 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
        if (!prtd)
                return -ENOMEM;
 
-       ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
-       if (ret < 0) {
-               kfree(prtd);
-               return ret;
-       }
+       prtd->dma_chan = chan;
 
        substream->runtime->private_data = prtd;
 
@@ -313,6 +303,27 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
 
+/**
+ * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
+ * @substream: PCM substream
+ * @filter_fn: Filter function used to request the DMA channel
+ * @filter_data: Data passed to the DMA filter function
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function will request a DMA channel using the passed filter function and
+ * data. The function should usually be called from the pcm open callback. Note
+ * that this function will use private_data field of the substream's runtime. So
+ * it is not availabe to your pcm driver implementation.
+ */
+int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
+       dma_filter_fn filter_fn, void *filter_data)
+{
+       return snd_dmaengine_pcm_open(substream,
+                   dmaengine_pcm_request_channel(filter_fn, filter_data));
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
+
 /**
  * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
  * @substream: PCM substream
@@ -321,11 +332,26 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
 {
        struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
 
-       dma_release_channel(prtd->dma_chan);
        kfree(prtd);
 
        return 0;
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
 
+/**
+ * snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
+ * @substream: PCM substream
+ *
+ * Releases the DMA channel associated with the PCM substream.
+ */
+int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream)
+{
+       struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+       dma_release_channel(prtd->dma_chan);
+
+       return snd_dmaengine_pcm_close(substream);
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
+
 MODULE_LICENSE("GPL");
index db75d72c480561b6bbf8080a031412c297c44c3e..ba66a3f370a376fe364c44472a8ca8776510a3a8 100644 (file)
@@ -64,7 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
        if (ret)
                return ret;
 
-       return snd_dmaengine_pcm_open(substream, dma_data->filter, dma_data)
+       return snd_dmaengine_pcm_open_request_chan(substream, dma_data->filter,
+                               dma_data);
 }
 
 static int spear_pcm_mmap(struct snd_pcm_substream *substream,
@@ -79,7 +80,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops spear_pcm_ops = {
        .open           = spear_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = spear_pcm_hw_params,
        .hw_free        = spear_pcm_hw_free,
index f91d08bc175386de1aa8ce495f76ab19c1df8edb..32d08119dd87b471afe026f5b84f5c4083f3e9de 100644 (file)
@@ -66,7 +66,7 @@ static int tegra_pcm_open(struct snd_pcm_substream *substream)
        /* Set HW params now that initialization is complete */
        snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
 
-       ret = snd_dmaengine_pcm_open(substream, NULL, NULL);
+       ret = snd_dmaengine_pcm_open_request_chan(substream, NULL, NULL);
        if (ret) {
                dev_err(dev, "dmaengine pcm open failed with err %d\n", ret);
                return ret;
@@ -144,7 +144,7 @@ static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops tegra_pcm_ops = {
        .open           = tegra_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = tegra_pcm_hw_params,
        .hw_free        = tegra_pcm_hw_free,
index 09b5364e5095f03af167f2564f59405f8bea6662..a7d4f04e5964e84f7cae14f413f1897d1c5e2c57 100644 (file)
@@ -125,8 +125,8 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
                dma_cfg->dst_info.data_width = mem_data_width;
        }
 
-
-       ret = snd_dmaengine_pcm_open(substream, stedma40_filter, dma_cfg);
+       ret = snd_dmaengine_pcm_open_request_chan(substream, stedma40_filter,
+                       dma_cfg);
        if (ret) {
                dev_dbg(dai->dev,
                        "%s: ERROR: snd_dmaengine_pcm_open failed (%d)!\n",
@@ -211,7 +211,7 @@ static int ux500_pcm_mmap(struct snd_pcm_substream *substream,
 
 static struct snd_pcm_ops ux500_pcm_ops = {
        .open           = ux500_pcm_open,
-       .close          = snd_dmaengine_pcm_close,
+       .close          = snd_dmaengine_pcm_close_release_chan,
        .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = ux500_pcm_hw_params,
        .hw_free        = ux500_pcm_hw_free,