ASoC: pcm_dmaengine: Extract snd_dmaengine_pcm_refine_runtime_hwparams
authorShengjiu Wang <shengjiu.wang@nxp.com>
Fri, 27 Sep 2019 01:46:11 +0000 (09:46 +0800)
committerMark Brown <broonie@kernel.org>
Tue, 1 Oct 2019 11:18:25 +0000 (12:18 +0100)
When set the runtime hardware parameters, we may need to query
the capability of DMA to complete the parameters.

This patch is to Extract this operation from
dmaengine_pcm_set_runtime_hwparams function to a separate function
snd_dmaengine_pcm_refine_runtime_hwparams, that other components
which need this feature can call this function.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Reviewed-by: Nicolin Chen <nicoleotsuka@gmail.com>
Link: https://lore.kernel.org/r/d728f65194e9978cbec4132b522d4fed420d704a.1569493933.git.shengjiu.wang@nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/dmaengine_pcm.h
sound/core/pcm_dmaengine.c
sound/soc/soc-generic-dmaengine-pcm.c

index c679f61..b652206 100644 (file)
@@ -83,6 +83,11 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
        const struct snd_dmaengine_dai_dma_data *dma_data,
        struct dma_slave_config *config);
 
+int snd_dmaengine_pcm_refine_runtime_hwparams(
+       struct snd_pcm_substream *substream,
+       struct snd_dmaengine_dai_dma_data *dma_data,
+       struct snd_pcm_hardware *hw,
+       struct dma_chan *chan);
 
 /*
  * Try to request the DMA channel using compat_request_channel or
index 89a0592..5749a8a 100644 (file)
@@ -369,4 +369,87 @@ int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream)
 }
 EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close_release_chan);
 
+/**
+ * snd_dmaengine_pcm_refine_runtime_hwparams - Refine runtime hw params
+ * @substream: PCM substream
+ * @dma_data: DAI DMA data
+ * @hw: PCM hw params
+ * @chan: DMA channel to use for data transfers
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function will query DMA capability, then refine the pcm hardware
+ * parameters.
+ */
+int snd_dmaengine_pcm_refine_runtime_hwparams(
+       struct snd_pcm_substream *substream,
+       struct snd_dmaengine_dai_dma_data *dma_data,
+       struct snd_pcm_hardware *hw,
+       struct dma_chan *chan)
+{
+       struct dma_slave_caps dma_caps;
+       u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+                         BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+                         BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+       snd_pcm_format_t i;
+       int ret = 0;
+
+       if (!hw || !chan || !dma_data)
+               return -EINVAL;
+
+       ret = dma_get_slave_caps(chan, &dma_caps);
+       if (ret == 0) {
+               if (dma_caps.cmd_pause && dma_caps.cmd_resume)
+                       hw->info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
+               if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
+                       hw->info |= SNDRV_PCM_INFO_BATCH;
+
+               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+                       addr_widths = dma_caps.dst_addr_widths;
+               else
+                       addr_widths = dma_caps.src_addr_widths;
+       }
+
+       /*
+        * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
+        * hw.formats set to 0, meaning no restrictions are in place.
+        * In this case it's the responsibility of the DAI driver to
+        * provide the supported format information.
+        */
+       if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK))
+               /*
+                * Prepare formats mask for valid/allowed sample types. If the
+                * dma does not have support for the given physical word size,
+                * it needs to be masked out so user space can not use the
+                * format which produces corrupted audio.
+                * In case the dma driver does not implement the slave_caps the
+                * default assumption is that it supports 1, 2 and 4 bytes
+                * widths.
+                */
+               for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) {
+                       int bits = snd_pcm_format_physical_width(i);
+
+                       /*
+                        * Enable only samples with DMA supported physical
+                        * widths
+                        */
+                       switch (bits) {
+                       case 8:
+                       case 16:
+                       case 24:
+                       case 32:
+                       case 64:
+                               if (addr_widths & (1 << (bits / 8)))
+                                       hw->formats |= pcm_format_to_bits(i);
+                               break;
+                       default:
+                               /* Unsupported types */
+                               break;
+                       }
+               }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_refine_runtime_hwparams);
+
 MODULE_LICENSE("GPL");
index 5552c66..f2c98a9 100644 (file)
@@ -118,12 +118,7 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
        struct device *dma_dev = dmaengine_dma_dev(pcm, substream);
        struct dma_chan *chan = pcm->chan[substream->stream];
        struct snd_dmaengine_dai_dma_data *dma_data;
-       struct dma_slave_caps dma_caps;
        struct snd_pcm_hardware hw;
-       u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-                         BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
-                         BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
-       snd_pcm_format_t i;
        int ret;
 
        if (pcm->config && pcm->config->pcm_hardware)
@@ -145,56 +140,12 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
        if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
                hw.info |= SNDRV_PCM_INFO_BATCH;
 
-       ret = dma_get_slave_caps(chan, &dma_caps);
-       if (ret == 0) {
-               if (dma_caps.cmd_pause && dma_caps.cmd_resume)
-                       hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
-               if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
-                       hw.info |= SNDRV_PCM_INFO_BATCH;
-
-               if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-                       addr_widths = dma_caps.dst_addr_widths;
-               else
-                       addr_widths = dma_caps.src_addr_widths;
-       }
-
-       /*
-        * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep
-        * hw.formats set to 0, meaning no restrictions are in place.
-        * In this case it's the responsibility of the DAI driver to
-        * provide the supported format information.
-        */
-       if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK))
-               /*
-                * Prepare formats mask for valid/allowed sample types. If the
-                * dma does not have support for the given physical word size,
-                * it needs to be masked out so user space can not use the
-                * format which produces corrupted audio.
-                * In case the dma driver does not implement the slave_caps the
-                * default assumption is that it supports 1, 2 and 4 bytes
-                * widths.
-                */
-               for (i = SNDRV_PCM_FORMAT_FIRST; i <= SNDRV_PCM_FORMAT_LAST; i++) {
-                       int bits = snd_pcm_format_physical_width(i);
-
-                       /*
-                        * Enable only samples with DMA supported physical
-                        * widths
-                        */
-                       switch (bits) {
-                       case 8:
-                       case 16:
-                       case 24:
-                       case 32:
-                       case 64:
-                               if (addr_widths & (1 << (bits / 8)))
-                                       hw.formats |= pcm_format_to_bits(i);
-                               break;
-                       default:
-                               /* Unsupported types */
-                               break;
-                       }
-               }
+       ret = snd_dmaengine_pcm_refine_runtime_hwparams(substream,
+                                                       dma_data,
+                                                       &hw,
+                                                       chan);
+       if (ret)
+               return ret;
 
        return snd_soc_set_runtime_hwparams(substream, &hw);
 }