Add a separate function for finding (sysclk, lrclk, bclk) when the clock is auto or mclk. This makes code easier to read and reduces the indentation level in wm8960_configure_clocking.
Signed-off-by: Daniel Baluta daniel.baluta@nxp.com --- sound/soc/codecs/wm8960.c | 82 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 20 deletions(-)
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 3bf081a..cb2ff2d 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -604,12 +604,71 @@ static const int bclk_divs[] = { 120, 160, 220, 240, 320, 320, 320 };
+/** + * wm8960_configure_sysclk - checks if there is a sysclk frequency available + * The sysclk must be chosen such that: + * - sysclk = MCLK / sysclk_divs + * - lrclk = sysclk / dac_divs + * - 10 * bclk = sysclk / bclk_divs + * + * @wm8960_priv: wm8960 codec private data + * @mclk: MCLK used to derive sysclk + * @_i: sysclk_divs index for found sysclk + * @_j: dac_divs index for found lrclk + * @_k: bclk_divs index for found bclk + * + * Returns: + * -1, in case no sysclk frequency available found + * 0, in case an exact match is found. See @_i, @_j, @_k + * + */ +int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk, + int *_i, int *_j, int *_k) +{ + int sysclk, bclk, lrclk; + int i, j, k; + int diff; + + bclk = wm8960->bclk; + lrclk = wm8960->lrclk; + + /* check if the sysclk frequency is available. */ + for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { + if (sysclk_divs[i] == -1) + continue; + sysclk = mclk / sysclk_divs[i]; + for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { + if (sysclk != dac_divs[j] * lrclk) + continue; + for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) { + diff = sysclk - bclk * bclk_divs[k] / 10; + if (diff == 0) { + *_i = i; + *_j = j; + *_k = k; + break; + } + } + if (k != ARRAY_SIZE(bclk_divs)) + break; + } + if (j != ARRAY_SIZE(dac_divs)) + break; + } + + if (i != ARRAY_SIZE(sysclk_divs)) + return 0; + + return -1; +} + static int wm8960_configure_clocking(struct snd_soc_codec *codec) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); int sysclk, bclk, lrclk, freq_out, freq_in; u16 iface1 = snd_soc_read(codec, WM8960_IFACE1); int i, j, k; + int ret;
if (!(iface1 & (1<<6))) { dev_dbg(codec->dev, @@ -643,27 +702,10 @@ static int wm8960_configure_clocking(struct snd_soc_codec *codec) }
if (wm8960->clk_id != WM8960_SYSCLK_PLL) { - /* check if the sysclk frequency is available. */ - for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { - if (sysclk_divs[i] == -1) - continue; - sysclk = freq_out / sysclk_divs[i]; - for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { - if (sysclk != dac_divs[j] * lrclk) - continue; - for (k = 0; k < ARRAY_SIZE(bclk_divs); ++k) - if (sysclk == bclk * bclk_divs[k] / 10) - break; - if (k != ARRAY_SIZE(bclk_divs)) - break; - } - if (j != ARRAY_SIZE(dac_divs)) - break; - } - - if (i != ARRAY_SIZE(sysclk_divs)) { + ret = wm8960_configure_sysclk(wm8960, freq_out, &i, &j, &k); + if (ret == 0) goto configure_clock; - } else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) { + else if (wm8960->clk_id != WM8960_SYSCLK_AUTO) { dev_err(codec->dev, "failed to configure clock\n"); return -EINVAL; }