aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-04-27 12:35:42 -0400
committerMark Brown <broonie@kernel.org>2016-04-27 12:35:42 -0400
commitcc70666c252ce43fface105a44b6e178831660cd (patch)
tree90da8b997c0225c7f93e1500cf1684a628c8041f
parent60507fe191f524e82986fa737e5b27b4d3ad9289 (diff)
parent73fe01cfb3babff01748a9fbc95cc3ea2079cc7f (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.h12
-rw-r--r--sound/core/pcm_dmaengine.c11
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c57
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);
52struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream); 52struct 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 */
67struct snd_dmaengine_dai_dma_data { 78struct 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
77void snd_dmaengine_pcm_set_config_from_dai_data( 89void 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 */
112void snd_dmaengine_pcm_set_config_from_dai_data( 113void 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}