Rework FLL handling to use common code introduced earlier.

Signed-off-by: Michał Mirosław <[email protected]>
---
 sound/soc/atmel/atmel_wm8904.c |  11 +-
 sound/soc/codecs/Kconfig       |   1 +
 sound/soc/codecs/wm8904.c      | 476 ++++++++++-----------------------
 sound/soc/codecs/wm8904.h      |   5 -
 4 files changed, 140 insertions(+), 353 deletions(-)

diff --git a/sound/soc/atmel/atmel_wm8904.c b/sound/soc/atmel/atmel_wm8904.c
index 776b27d3686e..b77ea2495efe 100644
--- a/sound/soc/atmel/atmel_wm8904.c
+++ b/sound/soc/atmel/atmel_wm8904.c
@@ -30,20 +30,11 @@ static int atmel_asoc_wm8904_hw_params(struct 
snd_pcm_substream *substream,
        struct snd_soc_dai *codec_dai = rtd->codec_dai;
        int ret;
 
-       ret = snd_soc_dai_set_pll(codec_dai, WM8904_FLL_MCLK, WM8904_FLL_MCLK,
-               32768, params_rate(params) * 256);
-       if (ret < 0) {
-               pr_err("%s - failed to set wm8904 codec PLL.", __func__);
-               return ret;
-       }
-
        /*
         * As here wm8904 use FLL output as its system clock
-        * so calling set_sysclk won't care freq parameter
-        * then we pass 0
         */
        ret = snd_soc_dai_set_sysclk(codec_dai, WM8904_CLK_FLL,
-                       0, SND_SOC_CLOCK_IN);
+                       params_rate(params) * 256, SND_SOC_CLOCK_IN);
        if (ret < 0) {
                pr_err("%s -failed to set wm8904 SYSCLK\n", __func__);
                return ret;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 04086acf6d93..1a680023af7d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1331,6 +1331,7 @@ config SND_SOC_WM8903
 config SND_SOC_WM8904
        tristate "Wolfson Microelectronics WM8904 CODEC"
        depends on I2C
+       select SND_SOC_WM_FLL
 
 config SND_SOC_WM8940
         tristate
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index bcb3c9d5abf0..c9318fe34f91 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -24,6 +24,7 @@
 #include <sound/tlv.h>
 #include <sound/wm8904.h>
 
+#include "wm_fll.h"
 #include "wm8904.h"
 
 enum wm8904_type {
@@ -66,12 +67,8 @@ struct wm8904_priv {
        int retune_mobile_cfg;
        struct soc_enum retune_mobile_enum;
 
-       /* FLL setup */
-       int fll_src;
-       int fll_fref;
-       int fll_fout;
-
        /* Clocking configuration */
+       struct wm_fll_data fll;
        unsigned int mclk_rate;
        int sysclk_src;
        unsigned int sysclk_rate;
@@ -311,35 +308,111 @@ static bool wm8904_readable_register(struct device *dev, 
unsigned int reg)
        }
 }
 
-static int wm8904_configure_clocking(struct snd_soc_component *component)
+static void wm8904_unprepare_sysclk(struct wm8904_priv *priv)
 {
+       switch (priv->sysclk_src) {
+       case WM8904_CLK_MCLK:
+               clk_disable_unprepare(priv->mclk);
+               break;
+
+       case WM8904_CLK_FLL:
+               wm_fll_disable(&priv->fll);
+               break;
+       }
+}
+
+static int wm8904_prepare_sysclk(struct wm8904_priv *priv)
+{
+       int err;
+
+       switch (priv->sysclk_src) {
+       case WM8904_CLK_MCLK:
+               err = clk_set_rate(priv->mclk, priv->mclk_rate);
+               if (!err)
+                       err = clk_prepare_enable(priv->mclk);
+               break;
+
+       case WM8904_CLK_FLL:
+               err = wm_fll_enable(&priv->fll);
+               break;
+
+       default:
+               err = -EINVAL;
+               break;
+       }
+
+       return err;
+}
+
+static void wm8904_disable_sysclk(struct wm8904_priv *priv)
+{
+       regmap_update_bits(priv->regmap, WM8904_CLOCK_RATES_2,
+                          WM8904_CLK_SYS_ENA, 0);
+       wm8904_unprepare_sysclk(priv);
+}
+
+static int wm8904_enable_sysclk(struct wm8904_priv *priv)
+{
+       int err;
+
+       err = wm8904_prepare_sysclk(priv);
+       if (err < 0)
+               return err;
+
+       err = regmap_update_bits(priv->regmap, WM8904_CLOCK_RATES_2,
+                                WM8904_CLK_SYS_ENA_MASK, WM8904_CLK_SYS_ENA);
+       if (err < 0)
+               wm8904_unprepare_sysclk(priv);
+
+       return err;
+}
+
+static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                            unsigned int rate, int dir)
+{
+       struct snd_soc_component *component = dai->component;
        struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component);
-       unsigned int clock0, clock2, rate;
+       unsigned int clock0, clock2;
+       int err;
+
+       switch (clk_id) {
+       case WM8904_CLK_MCLK:
+       case WM8904_CLK_FLL:
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (clk_id == wm8904->sysclk_src && rate == wm8904->mclk_rate)
+               return 0;
+
+       dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, rate);
 
        /* Gate the clock while we're updating to avoid misclocking */
        clock2 = snd_soc_component_read32(component, WM8904_CLOCK_RATES_2);
-       snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2,
-                           WM8904_SYSCLK_SRC, 0);
+       wm8904_disable_sysclk(wm8904);
+
+       wm8904->sysclk_src = clk_id;
+       wm8904->mclk_rate = rate;
 
-       /* This should be done on init() for bypass paths */
        switch (wm8904->sysclk_src) {
        case WM8904_CLK_MCLK:
-               dev_dbg(component->dev, "Using %dHz MCLK\n", wm8904->mclk_rate);
+               dev_dbg(component->dev, "Using %dHz MCLK\n", rate);
 
                clock2 &= ~WM8904_SYSCLK_SRC;
-               rate = wm8904->mclk_rate;
-
-               /* Ensure the FLL is stopped */
-               snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                                   WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0);
                break;
 
        case WM8904_CLK_FLL:
-               dev_dbg(component->dev, "Using %dHz FLL clock\n",
-                       wm8904->fll_fout);
+               err = wm_fll_set_rate(&wm8904->fll, rate);
+               if (err < 0) {
+                       dev_err(component->dev, "Failed to set FLL rate: %d\n", 
err);
+                       return err;
+               }
+
+               dev_dbg(component->dev, "Using %dHz FLL clock\n", rate);
 
                clock2 |= WM8904_SYSCLK_SRC;
-               rate = wm8904->fll_fout;
                break;
 
        default:
@@ -356,11 +429,18 @@ static int wm8904_configure_clocking(struct 
snd_soc_component *component)
                wm8904->sysclk_rate = rate;
        }
 
-       snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_0, 
WM8904_MCLK_DIV,
-                           clock0);
-
+       snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_0,
+                                     WM8904_MCLK_DIV, clock0);
        snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2,
-                           WM8904_CLK_SYS_ENA | WM8904_SYSCLK_SRC, clock2);
+                                     WM8904_SYSCLK_SRC, clock2);
+
+       if (clock2 & WM8904_CLK_SYS_ENA) {
+               err = wm8904_enable_sysclk(wm8904);
+               if (err < 0) {
+                       dev_err(component->dev, "Failed to reenable CLK_SYS: 
%d\n", err);
+                       return err;
+               }
+       }
 
        dev_dbg(component->dev, "CLK_SYS is %dHz\n", wm8904->sysclk_rate);
 
@@ -655,33 +735,21 @@ static int sysclk_event(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_component *component = 
snd_soc_dapm_to_component(w->dapm);
        struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component);
+       int ret = 0;
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
-               /* If we're using the FLL then we only start it when
-                * required; we assume that the configuration has been
-                * done previously and all we need to do is kick it
-                * off.
-                */
-               switch (wm8904->sysclk_src) {
-               case WM8904_CLK_FLL:
-                       snd_soc_component_update_bits(component, 
WM8904_FLL_CONTROL_1,
-                                           WM8904_FLL_OSC_ENA,
-                                           WM8904_FLL_OSC_ENA);
-
-                       snd_soc_component_update_bits(component, 
WM8904_FLL_CONTROL_1,
-                                           WM8904_FLL_ENA,
-                                           WM8904_FLL_ENA);
-                       break;
-
-               default:
-                       break;
-               }
+               ret = wm8904_prepare_sysclk(wm8904);
+               if (ret)
+                       dev_err(component->dev,
+                               "Failed to prepare SYSCLK: %d\n", ret);
+               else
+                       dev_dbg(component->dev, "SYSCLK on\n");
                break;
 
        case SND_SOC_DAPM_POST_PMD:
-               snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                                   WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0);
+               wm8904_unprepare_sysclk(wm8904);
+               dev_dbg(component->dev, "SYSCLK off\n");
                break;
        }
 
@@ -1289,7 +1357,7 @@ static int wm8904_hw_params(struct snd_pcm_substream 
*substream,
 {
        struct snd_soc_component *component = dai->component;
        struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component);
-       int ret, i, best, best_val, cur_val;
+       int i, best, best_val, cur_val;
        unsigned int aif1 = 0;
        unsigned int aif2 = 0;
        unsigned int aif3 = 0;
@@ -1324,13 +1392,8 @@ static int wm8904_hw_params(struct snd_pcm_substream 
*substream,
                return -EINVAL;
        }
 
-
        dev_dbg(component->dev, "Target BCLK is %dHz\n", wm8904->bclk);
 
-       ret = wm8904_configure_clocking(component);
-       if (ret != 0)
-               return ret;
-
        /* Select nearest CLK_SYS_RATE */
        best = 0;
        best_val = abs((wm8904->sysclk_rate / clk_sys_rates[0].ratio)
@@ -1382,8 +1445,8 @@ static int wm8904_hw_params(struct snd_pcm_substream 
*substream,
                }
        }
        wm8904->bclk = (wm8904->sysclk_rate * 10) / bclk_divs[best].div;
-       dev_dbg(component->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
-               bclk_divs[best].div, wm8904->bclk);
+       dev_dbg(component->dev, "Selected BCLK_DIV of %d.%d for %dHz BCLK\n",
+               bclk_divs[best].div / 10, bclk_divs[best].div % 10,  
wm8904->bclk);
        aif2 |= bclk_divs[best].bclk_div;
 
        /* LRCLK is a simple fraction of BCLK */
@@ -1410,34 +1473,6 @@ static int wm8904_hw_params(struct snd_pcm_substream 
*substream,
        return 0;
 }
 
-
-static int wm8904_set_sysclk(struct snd_soc_dai *dai, int clk_id,
-                            unsigned int freq, int dir)
-{
-       struct snd_soc_component *component = dai->component;
-       struct wm8904_priv *priv = snd_soc_component_get_drvdata(component);
-
-       switch (clk_id) {
-       case WM8904_CLK_MCLK:
-               priv->sysclk_src = clk_id;
-               priv->mclk_rate = freq;
-               break;
-
-       case WM8904_CLK_FLL:
-               priv->sysclk_src = clk_id;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq);
-
-       wm8904_configure_clocking(component);
-
-       return 0;
-}
-
 static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct snd_soc_component *component = dai->component;
@@ -1577,253 +1612,6 @@ static int wm8904_set_tdm_slot(struct snd_soc_dai *dai, 
unsigned int tx_mask,
        return 0;
 }
 
-struct _fll_div {
-       u16 fll_fratio;
-       u16 fll_outdiv;
-       u16 fll_clk_ref_div;
-       u16 n;
-       u16 k;
-};
-
-/* The size in bits of the FLL divide multiplied by 10
- * to allow rounding later */
-#define FIXED_FLL_SIZE ((1 << 16) * 10)
-
-static struct {
-       unsigned int min;
-       unsigned int max;
-       u16 fll_fratio;
-       int ratio;
-} fll_fratios[] = {
-       {       0,    64000, 4, 16 },
-       {   64000,   128000, 3,  8 },
-       {  128000,   256000, 2,  4 },
-       {  256000,  1000000, 1,  2 },
-       { 1000000, 13500000, 0,  1 },
-};
-
-static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
-                      unsigned int Fout)
-{
-       u64 Kpart;
-       unsigned int K, Ndiv, Nmod, target;
-       unsigned int div;
-       int i;
-
-       /* Fref must be <=13.5MHz */
-       div = 1;
-       fll_div->fll_clk_ref_div = 0;
-       while ((Fref / div) > 13500000) {
-               div *= 2;
-               fll_div->fll_clk_ref_div++;
-
-               if (div > 8) {
-                       pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
-                              Fref);
-                       return -EINVAL;
-               }
-       }
-
-       pr_debug("Fref=%u Fout=%u\n", Fref, Fout);
-
-       /* Apply the division for our remaining calculations */
-       Fref /= div;
-
-       /* Fvco should be 90-100MHz; don't check the upper bound */
-       div = 4;
-       while (Fout * div < 90000000) {
-               div++;
-               if (div > 64) {
-                       pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
-                              Fout);
-                       return -EINVAL;
-               }
-       }
-       target = Fout * div;
-       fll_div->fll_outdiv = div - 1;
-
-       pr_debug("Fvco=%dHz\n", target);
-
-       /* Find an appropriate FLL_FRATIO and factor it out of the target */
-       for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
-               if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
-                       fll_div->fll_fratio = fll_fratios[i].fll_fratio;
-                       target /= fll_fratios[i].ratio;
-                       break;
-               }
-       }
-       if (i == ARRAY_SIZE(fll_fratios)) {
-               pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
-               return -EINVAL;
-       }
-
-       /* Now, calculate N.K */
-       Ndiv = target / Fref;
-
-       fll_div->n = Ndiv;
-       Nmod = target % Fref;
-       pr_debug("Nmod=%d\n", Nmod);
-
-       /* Calculate fractional part - scale up so we can round. */
-       Kpart = FIXED_FLL_SIZE * (long long)Nmod;
-
-       do_div(Kpart, Fref);
-
-       K = Kpart & 0xFFFFFFFF;
-
-       if ((K % 10) >= 5)
-               K += 5;
-
-       /* Move down to proper range now rounding is done */
-       fll_div->k = K / 10;
-
-       pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n",
-                fll_div->n, fll_div->k,
-                fll_div->fll_fratio, fll_div->fll_outdiv,
-                fll_div->fll_clk_ref_div);
-
-       return 0;
-}
-
-static int wm8904_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
-                         unsigned int Fref, unsigned int Fout)
-{
-       struct snd_soc_component *component = dai->component;
-       struct wm8904_priv *wm8904 = snd_soc_component_get_drvdata(component);
-       struct _fll_div fll_div;
-       int ret, val;
-       int clock2, fll1;
-
-       /* Any change? */
-       if (source == wm8904->fll_src && Fref == wm8904->fll_fref &&
-           Fout == wm8904->fll_fout)
-               return 0;
-
-       clock2 = snd_soc_component_read32(component, WM8904_CLOCK_RATES_2);
-
-       if (Fout == 0) {
-               dev_dbg(component->dev, "FLL disabled\n");
-
-               wm8904->fll_fref = 0;
-               wm8904->fll_fout = 0;
-
-               /* Gate SYSCLK to avoid glitches */
-               snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2,
-                                   WM8904_CLK_SYS_ENA, 0);
-
-               snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                                   WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0);
-
-               goto out;
-       }
-
-       /* Validate the FLL ID */
-       switch (source) {
-       case WM8904_FLL_MCLK:
-       case WM8904_FLL_LRCLK:
-       case WM8904_FLL_BCLK:
-               ret = fll_factors(&fll_div, Fref, Fout);
-               if (ret != 0)
-                       return ret;
-               break;
-
-       case WM8904_FLL_FREE_RUNNING:
-               dev_dbg(component->dev, "Using free running FLL\n");
-               /* Force 12MHz and output/4 for now */
-               Fout = 12000000;
-               Fref = 12000000;
-
-               memset(&fll_div, 0, sizeof(fll_div));
-               fll_div.fll_outdiv = 3;
-               break;
-
-       default:
-               dev_err(component->dev, "Unknown FLL ID %d\n", fll_id);
-               return -EINVAL;
-       }
-
-       /* Save current state then disable the FLL and SYSCLK to avoid
-        * misclocking */
-       fll1 = snd_soc_component_read32(component, WM8904_FLL_CONTROL_1);
-       snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2,
-                           WM8904_CLK_SYS_ENA, 0);
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                           WM8904_FLL_OSC_ENA | WM8904_FLL_ENA, 0);
-
-       /* Unlock forced oscilator control to switch it on/off */
-       snd_soc_component_update_bits(component, 
WM8904_CONTROL_INTERFACE_TEST_1,
-                           WM8904_USER_KEY, WM8904_USER_KEY);
-
-       if (fll_id == WM8904_FLL_FREE_RUNNING) {
-               val = WM8904_FLL_FRC_NCO;
-       } else {
-               val = 0;
-       }
-
-       snd_soc_component_update_bits(component, WM8904_FLL_NCO_TEST_1, 
WM8904_FLL_FRC_NCO,
-                           val);
-       snd_soc_component_update_bits(component, 
WM8904_CONTROL_INTERFACE_TEST_1,
-                           WM8904_USER_KEY, 0);
-
-       switch (fll_id) {
-       case WM8904_FLL_MCLK:
-               snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_5,
-                                   WM8904_FLL_CLK_REF_SRC_MASK, 0);
-               break;
-
-       case WM8904_FLL_LRCLK:
-               snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_5,
-                                   WM8904_FLL_CLK_REF_SRC_MASK, 1);
-               break;
-
-       case WM8904_FLL_BCLK:
-               snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_5,
-                                   WM8904_FLL_CLK_REF_SRC_MASK, 2);
-               break;
-       }
-
-       if (fll_div.k)
-               val = WM8904_FLL_FRACN_ENA;
-       else
-               val = 0;
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                           WM8904_FLL_FRACN_ENA, val);
-
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_2,
-                           WM8904_FLL_OUTDIV_MASK | WM8904_FLL_FRATIO_MASK,
-                           (fll_div.fll_outdiv << WM8904_FLL_OUTDIV_SHIFT) |
-                           (fll_div.fll_fratio << WM8904_FLL_FRATIO_SHIFT));
-
-       snd_soc_component_write(component, WM8904_FLL_CONTROL_3, fll_div.k);
-
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_4, 
WM8904_FLL_N_MASK,
-                           fll_div.n << WM8904_FLL_N_SHIFT);
-
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_5,
-                           WM8904_FLL_CLK_REF_DIV_MASK,
-                           fll_div.fll_clk_ref_div 
-                           << WM8904_FLL_CLK_REF_DIV_SHIFT);
-
-       dev_dbg(component->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
-
-       wm8904->fll_fref = Fref;
-       wm8904->fll_fout = Fout;
-       wm8904->fll_src = source;
-
-       /* Enable the FLL if it was previously active */
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                           WM8904_FLL_OSC_ENA, fll1);
-       snd_soc_component_update_bits(component, WM8904_FLL_CONTROL_1,
-                           WM8904_FLL_ENA, fll1);
-
-out:
-       /* Reenable SYSCLK if it was previously active */
-       snd_soc_component_update_bits(component, WM8904_CLOCK_RATES_2,
-                           WM8904_CLK_SYS_ENA, clock2);
-
-       return 0;
-}
-
 static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 {
        struct snd_soc_component *component = codec_dai->component;
@@ -1871,15 +1659,6 @@ static int wm8904_set_bias_level(struct 
snd_soc_component *component,
                                return ret;
                        }
 
-                       ret = clk_prepare_enable(wm8904->mclk);
-                       if (ret) {
-                               dev_err(component->dev,
-                                       "Failed to enable MCLK: %d\n", ret);
-                               
regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies),
-                                                      wm8904->supplies);
-                               return ret;
-                       }
-
                        regcache_cache_only(wm8904->regmap, false);
                        regcache_sync(wm8904->regmap);
 
@@ -1922,7 +1701,6 @@ static int wm8904_set_bias_level(struct snd_soc_component 
*component,
 
                regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies),
                                       wm8904->supplies);
-               clk_disable_unprepare(wm8904->mclk);
                break;
        }
        return 0;
@@ -1937,7 +1715,6 @@ static const struct snd_soc_dai_ops wm8904_dai_ops = {
        .set_sysclk = wm8904_set_sysclk,
        .set_fmt = wm8904_set_fmt,
        .set_tdm_slot = wm8904_set_tdm_slot,
-       .set_pll = wm8904_set_fll,
        .hw_params = wm8904_hw_params,
        .digital_mute = wm8904_digital_mute,
 };
@@ -2123,6 +1900,15 @@ static const struct regmap_config wm8904_regmap = {
        .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
 };
 
+static const struct wm_fll_desc wm8904_fll_desc = {
+       .ctl_offset = WM8904_FLL_CONTROL_1,
+       .int_offset = WM8904_INTERRUPT_STATUS,
+       .int_mask = WM8904_FLL_LOCK_EINT_MASK,
+       .nco_reg0 = WM8904_FLL_NCO_TEST_0,
+       .nco_reg1 = WM8904_FLL_NCO_TEST_1,
+       .clk_ref_map = { FLL_REF_MCLK, FLL_REF_BCLK, FLL_REF_FSCLK, /* reserved 
*/ 0 },
+};
+
 #ifdef CONFIG_OF
 static const struct of_device_id wm8904_of_match[] = {
        {
@@ -2165,6 +1951,19 @@ static int wm8904_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
+       wm8904->fll.regmap = wm8904->regmap;
+       wm8904->fll.desc = &wm8904_fll_desc;
+       ret = wm_fll_init_with_clk(&wm8904->fll);
+       if (ret)
+               return ret;
+
+       ret = wm_fll_set_parent(&wm8904->fll, FLL_REF_MCLK);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to select MCLK as FLL input: %d\n",
+                       ret);
+               return ret;
+       }
+
        if (i2c->dev.of_node) {
                const struct of_device_id *match;
 
@@ -2276,6 +2075,7 @@ static int wm8904_i2c_probe(struct i2c_client *i2c,
                            WM8904_POBCTRL, 0);
 
        /* Can leave the device powered off until we need it */
+       wm8904_disable_sysclk(wm8904);
        regcache_cache_only(wm8904->regmap, true);
        regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
 
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index c1bca52f9927..60af09e0bb15 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -13,11 +13,6 @@
 #define WM8904_CLK_MCLK 1
 #define WM8904_CLK_FLL  2
 
-#define WM8904_FLL_MCLK          1
-#define WM8904_FLL_BCLK          2
-#define WM8904_FLL_LRCLK         3
-#define WM8904_FLL_FREE_RUNNING  4
-
 /*
  * Register values.
  */
-- 
2.20.1

Reply via email to