summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baluta <daniel.baluta@nxp.com>2017-04-04 12:45:13 -0400
committerMark Brown <broonie@kernel.org>2017-04-05 13:23:15 -0400
commit84fdc00d519ffdf8ae6e34d7841bcc6f38928953 (patch)
tree13e325bd3f27a016c2d8dd95fbf9b92e12dbb384
parent3c01b9ee2ab9d0dffe837c12ed93740516a673d7 (diff)
ASoC: codec: wm9860: Refactor PLL out freq search
Add a separate function for deriving (sysclk, lrclk, bclk) when the clock is auto or pll. Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com> Acked-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/codecs/wm8960.c93
1 files changed, 64 insertions, 29 deletions
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index ce159f13e7a4..36c84549da23 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -672,10 +672,70 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
672 return *bclk_idx; 672 return *bclk_idx;
673} 673}
674 674
675/**
676 * wm8960_configure_pll - checks if there is a PLL out frequency available
677 * The PLL out frequency must be chosen such that:
678 * - sysclk = lrclk * dac_divs
679 * - freq_out = sysclk * sysclk_divs
680 * - 10 * sysclk = bclk * bclk_divs
681 *
682 * @codec: codec structure
683 * @freq_in: input frequency used to derive freq out via PLL
684 * @sysclk_idx: sysclk_divs index for found sysclk
685 * @dac_idx: dac_divs index for found lrclk
686 * @bclk_idx: bclk_divs index for found bclk
687 *
688 * Returns:
689 * -1, in case no PLL frequency out available was found
690 * >=0, in case we could derive bclk, lrclk, sysclk from PLL out using
691 * (@sysclk_idx, @dac_idx, @bclk_idx) dividers
692 */
693static
694int wm8960_configure_pll(struct snd_soc_codec *codec, int freq_in,
695 int *sysclk_idx, int *dac_idx, int *bclk_idx)
696{
697 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
698 int sysclk, bclk, lrclk, freq_out;
699 int diff, best_freq_out;
700 int i, j, k;
701
702 bclk = wm8960->bclk;
703 lrclk = wm8960->lrclk;
704
705 *bclk_idx = -1;
706
707 for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
708 if (sysclk_divs[i] == -1)
709 continue;
710 for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
711 sysclk = lrclk * dac_divs[j];
712 freq_out = sysclk * sysclk_divs[i];
713
714 for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {
715 if (!is_pll_freq_available(freq_in, freq_out))
716 continue;
717
718 diff = sysclk - bclk * bclk_divs[k] / 10;
719 if (diff == 0) {
720 *sysclk_idx = i;
721 *dac_idx = j;
722 *bclk_idx = k;
723 best_freq_out = freq_out;
724 break;
725 }
726 }
727 }
728 }
729
730 if (*bclk_idx != -1)
731 wm8960_set_pll(codec, freq_in, best_freq_out);
732
733 return *bclk_idx;
734}
675static int wm8960_configure_clocking(struct snd_soc_codec *codec) 735static int wm8960_configure_clocking(struct snd_soc_codec *codec)
676{ 736{
677 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); 737 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
678 int sysclk, bclk, lrclk, freq_out, freq_in; 738 int freq_out, freq_in;
679 u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); 739 u16 iface1 = snd_soc_read(codec, WM8960_IFACE1);
680 int i, j, k; 740 int i, j, k;
681 int ret; 741 int ret;
@@ -692,8 +752,6 @@ static int wm8960_configure_clocking(struct snd_soc_codec *codec)
692 } 752 }
693 753
694 freq_in = wm8960->freq_in; 754 freq_in = wm8960->freq_in;
695 bclk = wm8960->bclk;
696 lrclk = wm8960->lrclk;
697 /* 755 /*
698 * If it's sysclk auto mode, check if the MCLK can provide sysclk or 756 * If it's sysclk auto mode, check if the MCLK can provide sysclk or
699 * not. If MCLK can provide sysclk, using MCLK to provide sysclk 757 * not. If MCLK can provide sysclk, using MCLK to provide sysclk
@@ -720,33 +778,10 @@ static int wm8960_configure_clocking(struct snd_soc_codec *codec)
720 return -EINVAL; 778 return -EINVAL;
721 } 779 }
722 } 780 }
723 /* get a available pll out frequency and set pll */
724 for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
725 if (sysclk_divs[i] == -1)
726 continue;
727 for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) {
728 sysclk = lrclk * dac_divs[j];
729 freq_out = sysclk * sysclk_divs[i];
730
731 for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) {
732 if (sysclk == bclk * bclk_divs[k] / 10 &&
733 is_pll_freq_available(freq_in, freq_out)) {
734 wm8960_set_pll(codec,
735 freq_in, freq_out);
736 break;
737 } else {
738 continue;
739 }
740 }
741 if (k != ARRAY_SIZE(bclk_divs))
742 break;
743 }
744 if (j != ARRAY_SIZE(dac_divs))
745 break;
746 }
747 781
748 if (i == ARRAY_SIZE(sysclk_divs)) { 782 ret = wm8960_configure_pll(codec, freq_in, &i, &j, &k);
749 dev_err(codec->dev, "failed to configure clock\n"); 783 if (ret < 0) {
784 dev_err(codec->dev, "failed to configure clock via PLL\n");
750 return -EINVAL; 785 return -EINVAL;
751 } 786 }
752 787