diff options
author | Mark Brown <broonie@kernel.org> | 2016-04-27 12:35:42 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-04-27 12:35:42 -0400 |
commit | cc70666c252ce43fface105a44b6e178831660cd (patch) | |
tree | 90da8b997c0225c7f93e1500cf1684a628c8041f | |
parent | 60507fe191f524e82986fa737e5b27b4d3ad9289 (diff) | |
parent | 73fe01cfb3babff01748a9fbc95cc3ea2079cc7f (diff) |
Merge branch 'topic/dmaengine' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-bcm2835
-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 | } |