diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-05-27 04:24:20 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-06-01 06:55:07 -0400 |
commit | 8dd51e23a1ef3b5f22eeff4827260b75bafba620 (patch) | |
tree | 62754178efdd7c78ddb93aa5dc9f9ceb748e97cb /sound | |
parent | 85e59af24056ca7ffaf617cf6201c519e31dc668 (diff) |
ASoC: fsl-ssi: set bitclock in master mode from hw_params
The fsl_ssi driver uses the .set_sysclk callback to configure the
bitclock for master mode. This is unnecessary since the bitclock
is known in hw_params. This patch configures the bitclock from .hw_params.
.set_dai_sysclk now sets a bitclock frequency which is preferred over
the default calculated bitclock frequency.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Tested-By: Michael Grzeschik <mgr@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/fsl/fsl_ssi.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 18eacf5e399d..930095b1b72a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -166,6 +166,7 @@ struct fsl_ssi_private { | |||
166 | spinlock_t baudclk_lock; | 166 | spinlock_t baudclk_lock; |
167 | struct clk *baudclk; | 167 | struct clk *baudclk; |
168 | struct clk *clk; | 168 | struct clk *clk; |
169 | unsigned int bitclk_freq; | ||
169 | struct snd_dmaengine_dai_dma_data dma_params_tx; | 170 | struct snd_dmaengine_dai_dma_data dma_params_tx; |
170 | struct snd_dmaengine_dai_dma_data dma_params_rx; | 171 | struct snd_dmaengine_dai_dma_data dma_params_rx; |
171 | struct imx_pcm_fiq_params fiq_params; | 172 | struct imx_pcm_fiq_params fiq_params; |
@@ -236,6 +237,12 @@ static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private) | |||
236 | return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97); | 237 | return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97); |
237 | } | 238 | } |
238 | 239 | ||
240 | static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private) | ||
241 | { | ||
242 | return (ssi_private->dai_fmt & SND_SOC_DAIFMT_MASTER_MASK) == | ||
243 | SND_SOC_DAIFMT_CBS_CFS; | ||
244 | } | ||
245 | |||
239 | /** | 246 | /** |
240 | * fsl_ssi_isr: SSI interrupt handler | 247 | * fsl_ssi_isr: SSI interrupt handler |
241 | * | 248 | * |
@@ -509,7 +516,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
509 | } | 516 | } |
510 | 517 | ||
511 | /** | 518 | /** |
512 | * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock | 519 | * fsl_ssi_set_bclk - configure Digital Audio Interface bit clock |
513 | * | 520 | * |
514 | * Note: This function can be only called when using SSI as DAI master | 521 | * Note: This function can be only called when using SSI as DAI master |
515 | * | 522 | * |
@@ -517,8 +524,9 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream, | |||
517 | * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels | 524 | * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels |
518 | * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK. | 525 | * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK. |
519 | */ | 526 | */ |
520 | static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | 527 | static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, |
521 | int clk_id, unsigned int freq, int dir) | 528 | struct snd_soc_dai *cpu_dai, |
529 | struct snd_pcm_hw_params *hw_params) | ||
522 | { | 530 | { |
523 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | 531 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); |
524 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; | 532 | struct ccsr_ssi __iomem *ssi = ssi_private->ssi; |
@@ -526,6 +534,13 @@ static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
526 | u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; | 534 | u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i; |
527 | unsigned long flags, clkrate, baudrate, tmprate; | 535 | unsigned long flags, clkrate, baudrate, tmprate; |
528 | u64 sub, savesub = 100000; | 536 | u64 sub, savesub = 100000; |
537 | unsigned int freq; | ||
538 | |||
539 | /* Prefer the explicitly set bitclock frequency */ | ||
540 | if (ssi_private->bitclk_freq) | ||
541 | freq = ssi_private->bitclk_freq; | ||
542 | else | ||
543 | freq = params_channels(hw_params) * 32 * params_rate(hw_params); | ||
529 | 544 | ||
530 | /* Don't apply it to any non-baudclk circumstance */ | 545 | /* Don't apply it to any non-baudclk circumstance */ |
531 | if (IS_ERR(ssi_private->baudclk)) | 546 | if (IS_ERR(ssi_private->baudclk)) |
@@ -583,7 +598,7 @@ static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
583 | mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | | 598 | mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | |
584 | CCSR_SSI_SxCCR_PSR; | 599 | CCSR_SSI_SxCCR_PSR; |
585 | 600 | ||
586 | if (dir == SND_SOC_CLOCK_OUT || synchronous) | 601 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || synchronous) |
587 | write_ssi_mask(&ssi->stccr, mask, stccr); | 602 | write_ssi_mask(&ssi->stccr, mask, stccr); |
588 | else | 603 | else |
589 | write_ssi_mask(&ssi->srccr, mask, stccr); | 604 | write_ssi_mask(&ssi->srccr, mask, stccr); |
@@ -604,6 +619,16 @@ static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
604 | return 0; | 619 | return 0; |
605 | } | 620 | } |
606 | 621 | ||
622 | static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
623 | int clk_id, unsigned int freq, int dir) | ||
624 | { | ||
625 | struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai); | ||
626 | |||
627 | ssi_private->bitclk_freq = freq; | ||
628 | |||
629 | return 0; | ||
630 | } | ||
631 | |||
607 | /** | 632 | /** |
608 | * fsl_ssi_hw_params - program the sample size | 633 | * fsl_ssi_hw_params - program the sample size |
609 | * | 634 | * |
@@ -627,6 +652,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
627 | snd_pcm_format_width(params_format(hw_params)); | 652 | snd_pcm_format_width(params_format(hw_params)); |
628 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); | 653 | u32 wl = CCSR_SSI_SxCCR_WL(sample_size); |
629 | int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; | 654 | int enabled = read_ssi(&ssi->scr) & CCSR_SSI_SCR_SSIEN; |
655 | int ret; | ||
630 | 656 | ||
631 | /* | 657 | /* |
632 | * If we're in synchronous mode, and the SSI is already enabled, | 658 | * If we're in synchronous mode, and the SSI is already enabled, |
@@ -635,6 +661,12 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, | |||
635 | if (enabled && ssi_private->cpu_dai_drv.symmetric_rates) | 661 | if (enabled && ssi_private->cpu_dai_drv.symmetric_rates) |
636 | return 0; | 662 | return 0; |
637 | 663 | ||
664 | if (fsl_ssi_is_i2s_master(ssi_private)) { | ||
665 | ret = fsl_ssi_set_bclk(substream, cpu_dai, hw_params); | ||
666 | if (ret) | ||
667 | return ret; | ||
668 | } | ||
669 | |||
638 | /* | 670 | /* |
639 | * FIXME: The documentation says that SxCCR[WL] should not be | 671 | * FIXME: The documentation says that SxCCR[WL] should not be |
640 | * modified while the SSI is enabled. The only time this can | 672 | * modified while the SSI is enabled. The only time this can |