diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2014-04-28 06:54:52 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-05-20 18:05:03 -0400 |
commit | ee9daad4953418ecf28a6b0b920f982fe0c24814 (patch) | |
tree | 44b433d7d8efa0b352301e73ea9a568c8a10aaa6 /sound/soc/fsl | |
parent | 504894799fa122822f5c48be2968e04d3f1af8e8 (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.c | 190 |
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 | */ | ||
530 | static 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 | */ | ||
732 | static 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 |