aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2014-04-28 06:54:52 -0400
committerMark Brown <broonie@linaro.org>2014-05-20 18:05:03 -0400
commitee9daad4953418ecf28a6b0b920f982fe0c24814 (patch)
tree44b433d7d8efa0b352301e73ea9a568c8a10aaa6 /sound/soc/fsl
parent504894799fa122822f5c48be2968e04d3f1af8e8 (diff)
ASoC: fsl-ssi: Move fsl_ssi_set_dai_sysclk above fsl_ssi_hw_params
fsl_ssi_set_dai_sysclk will be called from fsl_ssi_hw_params in the next patch. Move up to avoid forward declaration and to keep the next patch more readable. No functional change. 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/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_ssi.c190
1 files changed, 96 insertions, 94 deletions
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c6dcdb88b2b9..e5d8819cf19f 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -519,6 +519,102 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
519} 519}
520 520
521/** 521/**
522 * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
523 *
524 * Note: This function can be only called when using SSI as DAI master
525 *
526 * Quick instruction for parameters:
527 * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
528 * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
529 */
530static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
531 int clk_id, unsigned int freq, int dir)
532{
533 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
534 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
535 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
536 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
537 unsigned long flags, clkrate, baudrate, tmprate;
538 u64 sub, savesub = 100000;
539
540 /* Don't apply it to any non-baudclk circumstance */
541 if (IS_ERR(ssi_private->baudclk))
542 return -EINVAL;
543
544 /* It should be already enough to divide clock by setting pm alone */
545 psr = 0;
546 div2 = 0;
547
548 factor = (div2 + 1) * (7 * psr + 1) * 2;
549
550 for (i = 0; i < 255; i++) {
551 /* The bclk rate must be smaller than 1/5 sysclk rate */
552 if (factor * (i + 1) < 5)
553 continue;
554
555 tmprate = freq * factor * (i + 2);
556 clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
557
558 do_div(clkrate, factor);
559 afreq = (u32)clkrate / (i + 1);
560
561 if (freq == afreq)
562 sub = 0;
563 else if (freq / afreq == 1)
564 sub = freq - afreq;
565 else if (afreq / freq == 1)
566 sub = afreq - freq;
567 else
568 continue;
569
570 /* Calculate the fraction */
571 sub *= 100000;
572 do_div(sub, freq);
573
574 if (sub < savesub) {
575 baudrate = tmprate;
576 savesub = sub;
577 pm = i;
578 }
579
580 /* We are lucky */
581 if (savesub == 0)
582 break;
583 }
584
585 /* No proper pm found if it is still remaining the initial value */
586 if (pm == 999) {
587 dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
588 return -EINVAL;
589 }
590
591 stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
592 (psr ? CCSR_SSI_SxCCR_PSR : 0);
593 mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 |
594 CCSR_SSI_SxCCR_PSR;
595
596 if (dir == SND_SOC_CLOCK_OUT || synchronous)
597 write_ssi_mask(&ssi->stccr, mask, stccr);
598 else
599 write_ssi_mask(&ssi->srccr, mask, stccr);
600
601 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
602 if (!ssi_private->baudclk_locked) {
603 ret = clk_set_rate(ssi_private->baudclk, baudrate);
604 if (ret) {
605 spin_unlock_irqrestore(&ssi_private->baudclk_lock,
606 flags);
607 dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
608 return -EINVAL;
609 }
610 ssi_private->baudclk_locked = true;
611 }
612 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
613
614 return 0;
615}
616
617/**
522 * fsl_ssi_hw_params - program the sample size 618 * fsl_ssi_hw_params - program the sample size
523 * 619 *
524 * Most of the SSI registers have been programmed in the startup function, 620 * Most of the SSI registers have been programmed in the startup function,
@@ -721,100 +817,6 @@ static int fsl_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
721} 817}
722 818
723/** 819/**
724 * fsl_ssi_set_dai_sysclk - configure Digital Audio Interface bit clock
725 *
726 * Note: This function can be only called when using SSI as DAI master
727 *
728 * Quick instruction for parameters:
729 * freq: Output BCLK frequency = samplerate * 32 (fixed) * channels
730 * dir: SND_SOC_CLOCK_OUT -> TxBCLK, SND_SOC_CLOCK_IN -> RxBCLK.
731 */
732static int fsl_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
733 int clk_id, unsigned int freq, int dir)
734{
735 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
736 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
737 int synchronous = ssi_private->cpu_dai_drv.symmetric_rates, ret;
738 u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
739 unsigned long flags, clkrate, baudrate, tmprate;
740 u64 sub, savesub = 100000;
741
742 /* Don't apply it to any non-baudclk circumstance */
743 if (IS_ERR(ssi_private->baudclk))
744 return -EINVAL;
745
746 /* It should be already enough to divide clock by setting pm alone */
747 psr = 0;
748 div2 = 0;
749
750 factor = (div2 + 1) * (7 * psr + 1) * 2;
751
752 for (i = 0; i < 255; i++) {
753 /* The bclk rate must be smaller than 1/5 sysclk rate */
754 if (factor * (i + 1) < 5)
755 continue;
756
757 tmprate = freq * factor * (i + 2);
758 clkrate = clk_round_rate(ssi_private->baudclk, tmprate);
759
760 do_div(clkrate, factor);
761 afreq = (u32)clkrate / (i + 1);
762
763 if (freq == afreq)
764 sub = 0;
765 else if (freq / afreq == 1)
766 sub = freq - afreq;
767 else if (afreq / freq == 1)
768 sub = afreq - freq;
769 else
770 continue;
771
772 /* Calculate the fraction */
773 sub *= 100000;
774 do_div(sub, freq);
775
776 if (sub < savesub) {
777 baudrate = tmprate;
778 savesub = sub;
779 pm = i;
780 }
781
782 /* We are lucky */
783 if (savesub == 0)
784 break;
785 }
786
787 /* No proper pm found if it is still remaining the initial value */
788 if (pm == 999) {
789 dev_err(cpu_dai->dev, "failed to handle the required sysclk\n");
790 return -EINVAL;
791 }
792
793 stccr = CCSR_SSI_SxCCR_PM(pm + 1) | (div2 ? CCSR_SSI_SxCCR_DIV2 : 0) |
794 (psr ? CCSR_SSI_SxCCR_PSR : 0);
795 mask = CCSR_SSI_SxCCR_PM_MASK | CCSR_SSI_SxCCR_DIV2 | CCSR_SSI_SxCCR_PSR;
796
797 if (dir == SND_SOC_CLOCK_OUT || synchronous)
798 write_ssi_mask(&ssi->stccr, mask, stccr);
799 else
800 write_ssi_mask(&ssi->srccr, mask, stccr);
801
802 spin_lock_irqsave(&ssi_private->baudclk_lock, flags);
803 if (!ssi_private->baudclk_locked) {
804 ret = clk_set_rate(ssi_private->baudclk, baudrate);
805 if (ret) {
806 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
807 dev_err(cpu_dai->dev, "failed to set baudclk rate\n");
808 return -EINVAL;
809 }
810 ssi_private->baudclk_locked = true;
811 }
812 spin_unlock_irqrestore(&ssi_private->baudclk_lock, flags);
813
814 return 0;
815}
816
817/**
818 * fsl_ssi_set_dai_tdm_slot - set TDM slot number 820 * fsl_ssi_set_dai_tdm_slot - set TDM slot number
819 * 821 *
820 * Note: This function can be only called when using SSI as DAI master 822 * Note: This function can be only called when using SSI as DAI master