aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorNicolin Chen <b42378@freescale.com>2013-12-02 10:29:03 -0500
committerMark Brown <broonie@linaro.org>2013-12-02 12:37:07 -0500
commit2924a9981006ad01efb46c754689fa7d03e3eb4f (patch)
treedcb22cfad1b4fae314c9e64a8a1538b970520666 /sound/soc/fsl
parent3621dbbc27ff347f2e4476013054bab18ebd906c (diff)
ASoC: fsl_ssi: Add monaural audio support for non-ac97 interface
The normal mode of SSI allows it to send/receive data to/from the first slot of each period. So we can use this normal mode to trick I2S signal by puting/getting data to/from the first slot only (the left channel) so as to support monaural audio playback and recording. Signed-off-by: Nicolin Chen <b42378@freescale.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_ssi.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 3df0318e71df..90ff1071e29c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -143,6 +143,7 @@ struct fsl_ssi_private {
143 bool ssi_on_imx; 143 bool ssi_on_imx;
144 bool imx_ac97; 144 bool imx_ac97;
145 bool use_dma; 145 bool use_dma;
146 u8 i2s_mode;
146 struct clk *clk; 147 struct clk *clk;
147 struct snd_dmaengine_dai_dma_data dma_params_tx; 148 struct snd_dmaengine_dai_dma_data dma_params_tx;
148 struct snd_dmaengine_dai_dma_data dma_params_rx; 149 struct snd_dmaengine_dai_dma_data dma_params_rx;
@@ -354,14 +355,13 @@ static void fsl_ssi_setup_ac97(struct fsl_ssi_private *ssi_private)
354static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private) 355static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
355{ 356{
356 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 357 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
357 u8 i2s_mode;
358 u8 wm; 358 u8 wm;
359 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates; 359 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
360 360
361 if (ssi_private->imx_ac97) 361 if (ssi_private->imx_ac97)
362 i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET; 362 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_NORMAL | CCSR_SSI_SCR_NET;
363 else 363 else
364 i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE; 364 ssi_private->i2s_mode = CCSR_SSI_SCR_I2S_MODE_SLAVE;
365 365
366 /* 366 /*
367 * Section 16.5 of the MPC8610 reference manual says that the SSI needs 367 * Section 16.5 of the MPC8610 reference manual says that the SSI needs
@@ -378,7 +378,7 @@ static int fsl_ssi_setup(struct fsl_ssi_private *ssi_private)
378 write_ssi_mask(&ssi->scr, 378 write_ssi_mask(&ssi->scr,
379 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN, 379 CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
380 CCSR_SSI_SCR_TFR_CLK_DIS | 380 CCSR_SSI_SCR_TFR_CLK_DIS |
381 i2s_mode | 381 ssi_private->i2s_mode |
382 (synchronous ? CCSR_SSI_SCR_SYN : 0)); 382 (synchronous ? CCSR_SSI_SCR_SYN : 0));
383 383
384 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 | 384 write_ssi(CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -508,6 +508,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
508{ 508{
509 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); 509 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
510 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 510 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
511 unsigned int channels = params_channels(hw_params);
511 unsigned int sample_size = 512 unsigned int sample_size =
512 snd_pcm_format_width(params_format(hw_params)); 513 snd_pcm_format_width(params_format(hw_params));
513 u32 wl = CCSR_SSI_SxCCR_WL(sample_size); 514 u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
@@ -537,6 +538,11 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
537 else 538 else
538 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl); 539 write_ssi_mask(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
539 540
541 if (!ssi_private->imx_ac97)
542 write_ssi_mask(&ssi->scr,
543 CCSR_SSI_SCR_NET | CCSR_SSI_SCR_I2S_MODE_MASK,
544 channels == 1 ? 0 : ssi_private->i2s_mode);
545
540 return 0; 546 return 0;
541} 547}
542 548
@@ -649,14 +655,13 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
649static struct snd_soc_dai_driver fsl_ssi_dai_template = { 655static struct snd_soc_dai_driver fsl_ssi_dai_template = {
650 .probe = fsl_ssi_dai_probe, 656 .probe = fsl_ssi_dai_probe,
651 .playback = { 657 .playback = {
652 /* The SSI does not support monaural audio. */ 658 .channels_min = 1,
653 .channels_min = 2,
654 .channels_max = 2, 659 .channels_max = 2,
655 .rates = FSLSSI_I2S_RATES, 660 .rates = FSLSSI_I2S_RATES,
656 .formats = FSLSSI_I2S_FORMATS, 661 .formats = FSLSSI_I2S_FORMATS,
657 }, 662 },
658 .capture = { 663 .capture = {
659 .channels_min = 2, 664 .channels_min = 1,
660 .channels_max = 2, 665 .channels_max = 2,
661 .rates = FSLSSI_I2S_RATES, 666 .rates = FSLSSI_I2S_RATES,
662 .formats = FSLSSI_I2S_FORMATS, 667 .formats = FSLSSI_I2S_FORMATS,