summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/imx-pcm-dma-v2.c
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2017-11-20 16:23:21 +0800
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:51:25 +0800
commitdeaa49291f50a23bff3157ed2881196ab642fe0d (patch)
tree2b00f168f1102f69879f617dd304425dd98001b3 /sound/soc/fsl/imx-pcm-dma-v2.c
parentd3a4db61b001f416a06eca5fe37776c71251dbbf (diff)
MLK-16885-2: ASoC: imx-pcm-dma-v2: query the caps of dma
query the caps of dma, then update the hw parameters according the caps. for EDMA can't support 24bit sample, but we didn't add any constraint, that cause issues. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Diffstat (limited to 'sound/soc/fsl/imx-pcm-dma-v2.c')
-rw-r--r--sound/soc/fsl/imx-pcm-dma-v2.c70
1 files changed, 63 insertions, 7 deletions
diff --git a/sound/soc/fsl/imx-pcm-dma-v2.c b/sound/soc/fsl/imx-pcm-dma-v2.c
index 5ac9fc7365fe..acad77241af8 100644
--- a/sound/soc/fsl/imx-pcm-dma-v2.c
+++ b/sound/soc/fsl/imx-pcm-dma-v2.c
@@ -22,13 +22,11 @@
#include "imx-pcm.h"
-static const struct snd_pcm_hardware imx_pcm_hardware = {
+static struct snd_pcm_hardware imx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME,
+ SNDRV_PCM_INFO_MMAP_VALID,
.buffer_bytes_max = IMX_SSI_DMABUF_SIZE,
.period_bytes_min = 128,
.period_bytes_max = 65532, /* Limited by SDMA engine */
@@ -100,9 +98,13 @@ static int imx_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_dmaengine_dai_dma_data *dma_data;
+ struct dma_slave_caps dma_caps;
+ struct dma_chan *chan;
+ u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
int ret;
-
- snd_soc_set_runtime_hwparams(substream, &imx_pcm_hardware);
+ int i;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
@@ -123,12 +125,66 @@ static int imx_pcm_open(struct snd_pcm_substream *substream)
return ret;
}
+ chan = snd_dmaengine_pcm_get_chan(substream);
+
+ ret = dma_get_slave_caps(chan, &dma_caps);
+ if (ret == 0) {
+ if (dma_caps.cmd_pause)
+ imx_pcm_hardware.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
+ if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
+ imx_pcm_hardware.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 = 0; 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)))
+ imx_pcm_hardware.formats |= (1LL << i);
+ break;
+ default:
+ /* Unsupported types */
+ break;
+ }
+ }
+
+ snd_soc_set_runtime_hwparams(substream, &imx_pcm_hardware);
+
ret = snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
if (ret < 0)
return ret;
-
return 0;
}