diff options
| -rw-r--r-- | sound/soc/codecs/wm8960.c | 28 |
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 | */ |
| 624 | static | 629 | static |
| 625 | int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk, | 630 | int 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 | ||
| 665 | static int wm8960_configure_clocking(struct snd_soc_codec *codec) | 675 | static 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"); |
