aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm8960.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 25a4a11929fe..ce159f13e7a4 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -611,6 +611,10 @@ static const int bclk_divs[] = {
611 * - lrclk = sysclk / dac_divs 611 * - lrclk = sysclk / dac_divs
612 * - 10 * bclk = sysclk / bclk_divs 612 * - 10 * bclk = sysclk / bclk_divs
613 * 613 *
614 * If we cannot find an exact match for (sysclk, lrclk, bclk)
615 * triplet, we relax the bclk such that bclk is chosen as the
616 * closest available frequency greater than expected bclk.
617 *
614 * @wm8960_priv: wm8960 codec private data 618 * @wm8960_priv: wm8960 codec private data
615 * @mclk: MCLK used to derive sysclk 619 * @mclk: MCLK used to derive sysclk
616 * @sysclk_idx: sysclk_divs index for found sysclk 620 * @sysclk_idx: sysclk_divs index for found sysclk
@@ -618,8 +622,9 @@ static const int bclk_divs[] = {
618 * @bclk_idx: bclk_divs index for found bclk 622 * @bclk_idx: bclk_divs index for found bclk
619 * 623 *
620 * Returns: 624 * Returns:
621 * -1, in case no sysclk frequency available found 625 * -1, in case no sysclk frequency available found
622 * 0, in case an exact (@sysclk_idx, @dac_idx, @bclk_idx) match is found 626 * >=0, in case we could derive bclk and lrclk from sysclk using
627 * (@sysclk_idx, @dac_idx, @bclk_idx) dividers
623 */ 628 */
624static 629static
625int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk, 630int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
@@ -627,7 +632,10 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
627{ 632{
628 int sysclk, bclk, lrclk; 633 int sysclk, bclk, lrclk;
629 int i, j, k; 634 int i, j, k;
630 int diff; 635 int diff, closest = mclk;
636
637 /* marker for no match */
638 *bclk_idx = -1;
631 639
632 bclk = wm8960->bclk; 640 bclk = wm8960->bclk;
633 lrclk = wm8960->lrclk; 641 lrclk = wm8960->lrclk;
@@ -648,6 +656,12 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
648 *bclk_idx = k; 656 *bclk_idx = k;
649 break; 657 break;
650 } 658 }
659 if (diff > 0 && closest > diff) {
660 *sysclk_idx = i;
661 *dac_idx = j;
662 *bclk_idx = k;
663 closest = diff;
664 }
651 } 665 }
652 if (k != ARRAY_SIZE(bclk_divs)) 666 if (k != ARRAY_SIZE(bclk_divs))
653 break; 667 break;
@@ -655,11 +669,7 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk,
655 if (j != ARRAY_SIZE(dac_divs)) 669 if (j != ARRAY_SIZE(dac_divs))
656 break; 670 break;
657 } 671 }
658 672 return *bclk_idx;
659 if (i != ARRAY_SIZE(sysclk_divs))
660 return 0;
661
662 return -1;
663} 673}
664 674
665static int wm8960_configure_clocking(struct snd_soc_codec *codec) 675static int wm8960_configure_clocking(struct snd_soc_codec *codec)
@@ -703,7 +713,7 @@ static int wm8960_configure_clocking(struct snd_soc_codec *codec)
703 713
704 if (wm8960->clk_id != WM8960_SYSCLK_PLL) { 714 if (wm8960->clk_id != WM8960_SYSCLK_PLL) {
705 ret = wm8960_configure_sysclk(wm8960, freq_out, &i, &j, &k); 715 ret = wm8960_configure_sysclk(wm8960, freq_out, &i, &j, &k);
706 if (ret == 0) { 716 if (ret >= 0) {
707 goto configure_clock; 717 goto configure_clock;
708 } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) { 718 } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) {
709 dev_err(codec->dev, "failed to configure clock\n"); 719 dev_err(codec->dev, "failed to configure clock\n");