aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm8960.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index d899623fb101..9ed455700954 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -679,6 +679,10 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
679 * - freq_out = sysclk * sysclk_divs 679 * - freq_out = sysclk * sysclk_divs
680 * - 10 * sysclk = bclk * bclk_divs 680 * - 10 * sysclk = bclk * bclk_divs
681 * 681 *
682 * If we cannot find an exact match for (sysclk, lrclk, bclk)
683 * triplet, we relax the bclk such that bclk is chosen as the
684 * closest available frequency greater than expected bclk.
685 *
682 * @codec: codec structure 686 * @codec: codec structure
683 * @freq_in: input frequency used to derive freq out via PLL 687 * @freq_in: input frequency used to derive freq out via PLL
684 * @sysclk_idx: sysclk_divs index for found sysclk 688 * @sysclk_idx: sysclk_divs index for found sysclk
@@ -696,12 +700,14 @@ int wm8960_configure_pll(struct snd_soc_codec *codec, int freq_in,
696{ 700{
697 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); 701 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
698 int sysclk, bclk, lrclk, freq_out; 702 int sysclk, bclk, lrclk, freq_out;
699 int diff; 703 int diff, closest, best_freq_out;
700 int i, j, k; 704 int i, j, k;
701 705
702 bclk = wm8960->bclk; 706 bclk = wm8960->bclk;
703 lrclk = wm8960->lrclk; 707 lrclk = wm8960->lrclk;
708 closest = freq_in;
704 709
710 best_freq_out = -EINVAL;
705 *sysclk_idx = *dac_idx = *bclk_idx = -1; 711 *sysclk_idx = *dac_idx = *bclk_idx = -1;
706 712
707 for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { 713 for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) {
@@ -722,10 +728,18 @@ int wm8960_configure_pll(struct snd_soc_codec *codec, int freq_in,
722 *bclk_idx = k; 728 *bclk_idx = k;
723 return freq_out; 729 return freq_out;
724 } 730 }
731 if (diff > 0 && closest > diff) {
732 *sysclk_idx = i;
733 *dac_idx = j;
734 *bclk_idx = k;
735 closest = diff;
736 best_freq_out = freq_out;
737 }
725 } 738 }
726 } 739 }
727 } 740 }
728 return -EINVAL; 741
742 return best_freq_out;
729} 743}
730static int wm8960_configure_clocking(struct snd_soc_codec *codec) 744static int wm8960_configure_clocking(struct snd_soc_codec *codec)
731{ 745{