aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap/omap-mcbsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap/omap-mcbsp.c')
-rw-r--r--sound/soc/omap/omap-mcbsp.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 8ad9dc901007..6f44cb4d30b8 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -256,6 +256,31 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
256 return err; 256 return err;
257} 257}
258 258
259static snd_pcm_sframes_t omap_mcbsp_dai_delay(
260 struct snd_pcm_substream *substream,
261 struct snd_soc_dai *dai)
262{
263 struct snd_soc_pcm_runtime *rtd = substream->private_data;
264 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
265 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
266 u16 fifo_use;
267 snd_pcm_sframes_t delay;
268
269 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
270 fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
271 else
272 fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
273
274 /*
275 * Divide the used locations with the channel count to get the
276 * FIFO usage in samples (don't care about partial samples in the
277 * buffer).
278 */
279 delay = fifo_use / substream->runtime->channels;
280
281 return delay;
282}
283
259static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, 284static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
260 struct snd_pcm_hw_params *params, 285 struct snd_pcm_hw_params *params,
261 struct snd_soc_dai *dai) 286 struct snd_soc_dai *dai)
@@ -295,8 +320,18 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
295 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 320 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
296 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 321 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
297 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; 322 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
298 omap_mcbsp_dai_dma_params[id][substream->stream].data_type = 323 switch (params_format(params)) {
299 OMAP_DMA_DATA_TYPE_S16; 324 case SNDRV_PCM_FORMAT_S16_LE:
325 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
326 OMAP_DMA_DATA_TYPE_S16;
327 break;
328 case SNDRV_PCM_FORMAT_S32_LE:
329 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
330 OMAP_DMA_DATA_TYPE_S32;
331 break;
332 default:
333 return -EINVAL;
334 }
300 335
301 snd_soc_dai_set_dma_data(cpu_dai, substream, 336 snd_soc_dai_set_dma_data(cpu_dai, substream,
302 &omap_mcbsp_dai_dma_params[id][substream->stream]); 337 &omap_mcbsp_dai_dma_params[id][substream->stream]);
@@ -308,7 +343,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
308 343
309 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; 344 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
310 wpf = channels = params_channels(params); 345 wpf = channels = params_channels(params);
311 if (channels == 2 && format == SND_SOC_DAIFMT_I2S) { 346 if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
347 format == SND_SOC_DAIFMT_LEFT_J)) {
312 /* Use dual-phase frames */ 348 /* Use dual-phase frames */
313 regs->rcr2 |= RPHASE; 349 regs->rcr2 |= RPHASE;
314 regs->xcr2 |= XPHASE; 350 regs->xcr2 |= XPHASE;
@@ -330,6 +366,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
330 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); 366 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
331 regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); 367 regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16);
332 break; 368 break;
369 case SNDRV_PCM_FORMAT_S32_LE:
370 /* Set word lengths */
371 wlen = 32;
372 regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32);
373 regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32);
374 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32);
375 regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32);
376 break;
333 default: 377 default:
334 /* Unsupported PCM format */ 378 /* Unsupported PCM format */
335 return -EINVAL; 379 return -EINVAL;
@@ -353,6 +397,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
353 /* Set FS period and length in terms of bit clock periods */ 397 /* Set FS period and length in terms of bit clock periods */
354 switch (format) { 398 switch (format) {
355 case SND_SOC_DAIFMT_I2S: 399 case SND_SOC_DAIFMT_I2S:
400 case SND_SOC_DAIFMT_LEFT_J:
356 regs->srgr2 |= FPER(framesize - 1); 401 regs->srgr2 |= FPER(framesize - 1);
357 regs->srgr1 |= FWID((framesize >> 1) - 1); 402 regs->srgr1 |= FWID((framesize >> 1) - 1);
358 break; 403 break;
@@ -404,6 +449,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
404 regs->rcr2 |= RDATDLY(1); 449 regs->rcr2 |= RDATDLY(1);
405 regs->xcr2 |= XDATDLY(1); 450 regs->xcr2 |= XDATDLY(1);
406 break; 451 break;
452 case SND_SOC_DAIFMT_LEFT_J:
453 /* 0-bit data delay */
454 regs->rcr2 |= RDATDLY(0);
455 regs->xcr2 |= XDATDLY(0);
456 regs->spcr1 |= RJUST(2);
457 /* Invert FS polarity configuration */
458 temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
459 break;
407 case SND_SOC_DAIFMT_DSP_A: 460 case SND_SOC_DAIFMT_DSP_A:
408 /* 1-bit data delay */ 461 /* 1-bit data delay */
409 regs->rcr2 |= RDATDLY(1); 462 regs->rcr2 |= RDATDLY(1);
@@ -609,6 +662,7 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
609 .startup = omap_mcbsp_dai_startup, 662 .startup = omap_mcbsp_dai_startup,
610 .shutdown = omap_mcbsp_dai_shutdown, 663 .shutdown = omap_mcbsp_dai_shutdown,
611 .trigger = omap_mcbsp_dai_trigger, 664 .trigger = omap_mcbsp_dai_trigger,
665 .delay = omap_mcbsp_dai_delay,
612 .hw_params = omap_mcbsp_dai_hw_params, 666 .hw_params = omap_mcbsp_dai_hw_params,
613 .set_fmt = omap_mcbsp_dai_set_dai_fmt, 667 .set_fmt = omap_mcbsp_dai_set_dai_fmt,
614 .set_clkdiv = omap_mcbsp_dai_set_clkdiv, 668 .set_clkdiv = omap_mcbsp_dai_set_clkdiv,
@@ -623,13 +677,15 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
623 .channels_min = 1, \ 677 .channels_min = 1, \
624 .channels_max = 16, \ 678 .channels_max = 16, \
625 .rates = OMAP_MCBSP_RATES, \ 679 .rates = OMAP_MCBSP_RATES, \
626 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 680 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
681 SNDRV_PCM_FMTBIT_S32_LE, \
627 }, \ 682 }, \
628 .capture = { \ 683 .capture = { \
629 .channels_min = 1, \ 684 .channels_min = 1, \
630 .channels_max = 16, \ 685 .channels_max = 16, \
631 .rates = OMAP_MCBSP_RATES, \ 686 .rates = OMAP_MCBSP_RATES, \
632 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 687 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
688 SNDRV_PCM_FMTBIT_S32_LE, \
633 }, \ 689 }, \
634 .ops = &omap_mcbsp_dai_ops, \ 690 .ops = &omap_mcbsp_dai_ops, \
635 .private_data = &mcbsp_data[(link_id)].bus_id, \ 691 .private_data = &mcbsp_data[(link_id)].bus_id, \