|
@@ -119,7 +119,10 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
|
|
|
struct snd_dmaengine_dai_dma_data *dma_data;
|
|
|
struct dma_slave_caps dma_caps;
|
|
|
struct snd_pcm_hardware hw;
|
|
|
- int ret;
|
|
|
+ u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
|
|
|
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
|
|
|
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
|
|
|
+ int i, ret;
|
|
|
|
|
|
if (pcm->config && pcm->config->pcm_hardware)
|
|
|
return snd_soc_set_runtime_hwparams(substream,
|
|
@@ -146,6 +149,38 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
|
|
|
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.dstn_addr_widths;
|
|
|
+ else
|
|
|
+ addr_widths = dma_caps.src_addr_widths;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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)))
|
|
|
+ hw.formats |= (1LL << i);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Unsupported types */
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return snd_soc_set_runtime_hwparams(substream, &hw);
|