diff options
| -rw-r--r-- | include/sound/dmaengine_pcm.h | 12 | ||||
| -rw-r--r-- | sound/core/pcm_dmaengine.c | 11 | ||||
| -rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 57 |
3 files changed, 55 insertions, 25 deletions
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index f86ef5ea9b01..67be2445941a 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h | |||
| @@ -51,6 +51,16 @@ struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, | |||
| 51 | void *filter_data); | 51 | void *filter_data); |
| 52 | struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); | 52 | struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); |
| 53 | 53 | ||
| 54 | /* | ||
| 55 | * The DAI supports packed transfers, eg 2 16-bit samples in a 32-bit word. | ||
| 56 | * If this flag is set the dmaengine driver won't put any restriction on | ||
| 57 | * the supported sample formats and set the DMA transfer size to undefined. | ||
| 58 | * The DAI driver is responsible to disable any unsupported formats in it's | ||
| 59 | * configuration and catch corner cases that are not already handled in | ||
| 60 | * the ALSA core. | ||
| 61 | */ | ||
| 62 | #define SND_DMAENGINE_PCM_DAI_FLAG_PACK BIT(0) | ||
| 63 | |||
| 54 | /** | 64 | /** |
| 55 | * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data | 65 | * struct snd_dmaengine_dai_dma_data - DAI DMA configuration data |
| 56 | * @addr: Address of the DAI data source or destination register. | 66 | * @addr: Address of the DAI data source or destination register. |
| @@ -63,6 +73,7 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) | |||
| 63 | * requesting the DMA channel. | 73 | * requesting the DMA channel. |
| 64 | * @chan_name: Custom channel name to use when requesting DMA channel. | 74 | * @chan_name: Custom channel name to use when requesting DMA channel. |
| 65 | * @fifo_size: FIFO size of the DAI controller in bytes | 75 | * @fifo_size: FIFO size of the DAI controller in bytes |
| 76 | * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now | ||
| 66 | */ | 77 | */ |
| 67 | struct snd_dmaengine_dai_dma_data { | 78 | struct snd_dmaengine_dai_dma_data { |
| 68 | dma_addr_t addr; | 79 | dma_addr_t addr; |
| @@ -72,6 +83,7 @@ struct snd_dmaengine_dai_dma_data { | |||
| 72 | void *filter_data; | 83 | void *filter_data; |
| 73 | const char *chan_name; | 84 | const char *chan_name; |
| 74 | unsigned int fifo_size; | 85 | unsigned int fifo_size; |
| 86 | unsigned int flags; | ||
| 75 | }; | 87 | }; |
| 76 | 88 | ||
| 77 | void snd_dmaengine_pcm_set_config_from_dai_data( | 89 | void snd_dmaengine_pcm_set_config_from_dai_data( |
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 697c166acf05..8eb58c709b14 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c | |||
| @@ -106,8 +106,9 @@ EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config); | |||
| 106 | * direction of the substream. If the substream is a playback stream the dst | 106 | * direction of the substream. If the substream is a playback stream the dst |
| 107 | * fields will be initialized, if it is a capture stream the src fields will be | 107 | * fields will be initialized, if it is a capture stream the src fields will be |
| 108 | * initialized. The {dst,src}_addr_width field will only be initialized if the | 108 | * initialized. The {dst,src}_addr_width field will only be initialized if the |
| 109 | * addr_width field of the DAI DMA data struct is not equal to | 109 | * SND_DMAENGINE_PCM_DAI_FLAG_PACK flag is set or if the addr_width field of |
| 110 | * DMA_SLAVE_BUSWIDTH_UNDEFINED. | 110 | * the DAI DMA data struct is not equal to DMA_SLAVE_BUSWIDTH_UNDEFINED. If |
| 111 | * both conditions are met the latter takes priority. | ||
| 111 | */ | 112 | */ |
| 112 | void snd_dmaengine_pcm_set_config_from_dai_data( | 113 | void snd_dmaengine_pcm_set_config_from_dai_data( |
| 113 | const struct snd_pcm_substream *substream, | 114 | const struct snd_pcm_substream *substream, |
| @@ -117,11 +118,17 @@ void snd_dmaengine_pcm_set_config_from_dai_data( | |||
| 117 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 118 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 118 | slave_config->dst_addr = dma_data->addr; | 119 | slave_config->dst_addr = dma_data->addr; |
| 119 | slave_config->dst_maxburst = dma_data->maxburst; | 120 | slave_config->dst_maxburst = dma_data->maxburst; |
| 121 | if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) | ||
| 122 | slave_config->dst_addr_width = | ||
| 123 | DMA_SLAVE_BUSWIDTH_UNDEFINED; | ||
| 120 | if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) | 124 | if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) |
| 121 | slave_config->dst_addr_width = dma_data->addr_width; | 125 | slave_config->dst_addr_width = dma_data->addr_width; |
| 122 | } else { | 126 | } else { |
| 123 | slave_config->src_addr = dma_data->addr; | 127 | slave_config->src_addr = dma_data->addr; |
| 124 | slave_config->src_maxburst = dma_data->maxburst; | 128 | slave_config->src_maxburst = dma_data->maxburst; |
| 129 | if (dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK) | ||
| 130 | slave_config->src_addr_width = | ||
| 131 | DMA_SLAVE_BUSWIDTH_UNDEFINED; | ||
| 125 | if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) | 132 | if (dma_data->addr_width != DMA_SLAVE_BUSWIDTH_UNDEFINED) |
| 126 | slave_config->src_addr_width = dma_data->addr_width; | 133 | slave_config->src_addr_width = dma_data->addr_width; |
| 127 | } | 134 | } |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 6fd1906af387..6cef3977507a 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
| @@ -163,31 +163,42 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea | |||
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | /* | 165 | /* |
| 166 | * Prepare formats mask for valid/allowed sample types. If the dma does | 166 | * If SND_DMAENGINE_PCM_DAI_FLAG_PACK is set keep |
| 167 | * not have support for the given physical word size, it needs to be | 167 | * hw.formats set to 0, meaning no restrictions are in place. |
| 168 | * masked out so user space can not use the format which produces | 168 | * In this case it's the responsibility of the DAI driver to |
| 169 | * corrupted audio. | 169 | * provide the supported format information. |
| 170 | * In case the dma driver does not implement the slave_caps the default | ||
| 171 | * assumption is that it supports 1, 2 and 4 bytes widths. | ||
| 172 | */ | 170 | */ |
| 173 | for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { | 171 | if (!(dma_data->flags & SND_DMAENGINE_PCM_DAI_FLAG_PACK)) |
| 174 | int bits = snd_pcm_format_physical_width(i); | 172 | /* |
| 175 | 173 | * Prepare formats mask for valid/allowed sample types. If the | |
| 176 | /* Enable only samples with DMA supported physical widths */ | 174 | * dma does not have support for the given physical word size, |
| 177 | switch (bits) { | 175 | * it needs to be masked out so user space can not use the |
| 178 | case 8: | 176 | * format which produces corrupted audio. |
| 179 | case 16: | 177 | * In case the dma driver does not implement the slave_caps the |
| 180 | case 24: | 178 | * default assumption is that it supports 1, 2 and 4 bytes |
| 181 | case 32: | 179 | * widths. |
| 182 | case 64: | 180 | */ |
| 183 | if (addr_widths & (1 << (bits / 8))) | 181 | for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) { |
| 184 | hw.formats |= (1LL << i); | 182 | int bits = snd_pcm_format_physical_width(i); |
| 185 | break; | 183 | |
| 186 | default: | 184 | /* |
| 187 | /* Unsupported types */ | 185 | * Enable only samples with DMA supported physical |
| 188 | break; | 186 | * widths |
| 187 | */ | ||
| 188 | switch (bits) { | ||
| 189 | case 8: | ||
| 190 | case 16: | ||
| 191 | case 24: | ||
| 192 | case 32: | ||
| 193 | case 64: | ||
| 194 | if (addr_widths & (1 << (bits / 8))) | ||
| 195 | hw.formats |= (1LL << i); | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | /* Unsupported types */ | ||
| 199 | break; | ||
| 200 | } | ||
| 189 | } | 201 | } |
| 190 | } | ||
| 191 | 202 | ||
| 192 | return snd_soc_set_runtime_hwparams(substream, &hw); | 203 | return snd_soc_set_runtime_hwparams(substream, &hw); |
| 193 | } | 204 | } |
