aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@nokia.com>2010-06-03 00:39:36 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-06-03 11:12:40 -0400
commitddc29b0104d69e3742e6a9f23184fb6184614403 (patch)
tree653558a4d808b89f20fd0fcacc6c239603ef84ee /sound/soc/omap
parent3f024039e08598521a2c4c3eaedf8de2119797f4 (diff)
ASoC: omap-mcbsp: Place correct constraints for streams
OMAP McBSP FIFO is word structured: McBSP2 has 1024 + 256 = 1280 word long buffer, McBSP1,3,4,5 has 128 word long buffer This means, that the size of the FIFO depends on the McBSP word size configuration. For example on McBSP3: 16bit samples: size is 128 * 2 = 256 bytes 32bit samples: size is 128 * 4 = 512 bytes It is simpler to place constraint for buffer and period based on channels. McBSP3 as example again (16 or 32 bit samples): 1 channel (mono): size is 128 frames (128 words) 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words) 4 channels: size is 128 / 4 = 32 frames (4 * 32 words) Use the second method to place hw_rule on buffer size, and in threshold mode to period size. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Acked-by: Jarkko Nikula <jhnikula@gmail.com> Acked-by: Mark Brown <broonie@opensource.wolsfonmicro.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/omap')
-rw-r--r--sound/soc/omap/omap-mcbsp.c98
1 files changed, 77 insertions, 21 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index b06d8f1620d7..aebd3af2ab79 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -173,6 +173,50 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
173 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words); 173 omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
174} 174}
175 175
176static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
177 struct snd_pcm_hw_rule *rule)
178{
179 struct snd_interval *buffer_size = hw_param_interval(params,
180 SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
181 struct snd_interval *channels = hw_param_interval(params,
182 SNDRV_PCM_HW_PARAM_CHANNELS);
183 struct omap_mcbsp_data *mcbsp_data = rule->private;
184 struct snd_interval frames;
185 int size;
186
187 snd_interval_any(&frames);
188 size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
189
190 frames.min = size / channels->min;
191 frames.integer = 1;
192 return snd_interval_refine(buffer_size, &frames);
193}
194
195static int omap_mcbsp_hwrule_max_periodsize(struct snd_pcm_hw_params *params,
196 struct snd_pcm_hw_rule *rule)
197{
198 struct snd_interval *period_size = hw_param_interval(params,
199 SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
200 struct snd_interval *channels = hw_param_interval(params,
201 SNDRV_PCM_HW_PARAM_CHANNELS);
202 struct snd_pcm_substream *substream = rule->private;
203 struct snd_soc_pcm_runtime *rtd = substream->private_data;
204 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
205 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
206 struct snd_interval frames;
207 int size;
208
209 snd_interval_any(&frames);
210 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
211 size = omap_mcbsp_get_max_tx_threshold(mcbsp_data->bus_id);
212 else
213 size = omap_mcbsp_get_max_rx_threshold(mcbsp_data->bus_id);
214
215 frames.max = size / channels->min;
216 frames.integer = 1;
217 return snd_interval_refine(period_size, &frames);
218}
219
176static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 220static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
177 struct snd_soc_dai *dai) 221 struct snd_soc_dai *dai)
178{ 222{
@@ -185,33 +229,45 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
185 if (!cpu_dai->active) 229 if (!cpu_dai->active)
186 err = omap_mcbsp_request(bus_id); 230 err = omap_mcbsp_request(bus_id);
187 231
232 /*
233 * OMAP3 McBSP FIFO is word structured.
234 * McBSP2 has 1024 + 256 = 1280 word long buffer,
235 * McBSP1,3,4,5 has 128 word long buffer
236 * This means that the size of the FIFO depends on the sample format.
237 * For example on McBSP3:
238 * 16bit samples: size is 128 * 2 = 256 bytes
239 * 32bit samples: size is 128 * 4 = 512 bytes
240 * It is simpler to place constraint for buffer and period based on
241 * channels.
242 * McBSP3 as example again (16 or 32 bit samples):
243 * 1 channel (mono): size is 128 frames (128 words)
244 * 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
245 * 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
246 */
188 if (cpu_is_omap343x()) { 247 if (cpu_is_omap343x()) {
189 int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); 248 int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id);
190 int max_period;
191 249
192 /* 250 /*
193 * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. 251 * The first rule is for the buffer size, we should not allow
194 * Set constraint for minimum buffer size to the same than FIFO 252 * smaller buffer than the FIFO size to avoid underruns
195 * size in order to avoid underruns in playback startup because 253 */
196 * HW is keeping the DMA request active until FIFO is filled. 254 snd_pcm_hw_rule_add(substream->runtime, 0,
197 */ 255 SNDRV_PCM_HW_PARAM_CHANNELS,
198 if (bus_id == 1) 256 omap_mcbsp_hwrule_min_buffersize,
199 snd_pcm_hw_constraint_minmax(substream->runtime, 257 mcbsp_data,
200 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 258 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
201 4096, UINT_MAX);
202
203 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
204 max_period = omap_mcbsp_get_max_tx_threshold(bus_id);
205 else
206 max_period = omap_mcbsp_get_max_rx_threshold(bus_id);
207
208 max_period++;
209 max_period <<= 1;
210 259
260 /*
261 * In case of threshold mode, the rule will ensure, that the
262 * period size is not bigger than the maximum allowed threshold
263 * value.
264 */
211 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) 265 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
212 snd_pcm_hw_constraint_minmax(substream->runtime, 266 snd_pcm_hw_rule_add(substream->runtime, 0,
213 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 267 SNDRV_PCM_HW_PARAM_CHANNELS,
214 32, max_period); 268 omap_mcbsp_hwrule_max_periodsize,
269 substream,
270 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1);
215 } 271 }
216 272
217 return err; 273 return err;