]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ASoC: madera: Enable clocks for input pins when used for the FLL
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Mon, 30 Dec 2019 14:35:17 +0000 (14:35 +0000)
committerMark Brown <broonie@kernel.org>
Tue, 31 Dec 2019 00:21:54 +0000 (00:21 +0000)
When one of the MCLK pins is used to supply the FLL enable that clock
source.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20191230143517.21005-2-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/madera.c

index 9b4b4c52b9e4b1efa0d22979ca0dc84e94556a5f..12dc468ae6bf07f4a3c5406202aae243e031c9e1 100644 (file)
@@ -3858,11 +3858,75 @@ static bool madera_set_fll_phase_integrator(struct madera_fll *fll,
        return reg_change;
 }
 
+static int madera_set_fll_clks_reg(struct madera_fll *fll, bool ena,
+                                  unsigned int reg, unsigned int mask,
+                                  unsigned int shift)
+{
+       struct madera *madera = fll->madera;
+       unsigned int src;
+       struct clk *clk;
+       int ret;
+
+       ret = regmap_read(madera->regmap, reg, &src);
+       if (ret != 0) {
+               madera_fll_err(fll, "Failed to read current source: %d\n",
+                              ret);
+               return ret;
+       }
+
+       src = (src & mask) >> shift;
+
+       switch (src) {
+       case MADERA_FLL_SRC_MCLK1:
+               clk = madera->mclk[MADERA_MCLK1].clk;
+               break;
+       case MADERA_FLL_SRC_MCLK2:
+               clk = madera->mclk[MADERA_MCLK2].clk;
+               break;
+       case MADERA_FLL_SRC_MCLK3:
+               clk = madera->mclk[MADERA_MCLK3].clk;
+               break;
+       default:
+               return 0;
+       }
+
+       if (ena) {
+               return clk_prepare_enable(clk);
+       } else {
+               clk_disable_unprepare(clk);
+               return 0;
+       }
+}
+
+static inline int madera_set_fll_clks(struct madera_fll *fll, int base, bool ena)
+{
+       return madera_set_fll_clks_reg(fll, ena,
+                                      base + MADERA_FLL_CONTROL_6_OFFS,
+                                      MADERA_FLL1_REFCLK_SRC_MASK,
+                                      MADERA_FLL1_REFCLK_DIV_SHIFT);
+}
+
+static inline int madera_set_fllao_clks(struct madera_fll *fll, int base, bool ena)
+{
+       return madera_set_fll_clks_reg(fll, ena,
+                                      base + MADERA_FLLAO_CONTROL_6_OFFS,
+                                      MADERA_FLL_AO_REFCLK_SRC_MASK,
+                                      MADERA_FLL_AO_REFCLK_SRC_SHIFT);
+}
+
+static inline int madera_set_fllhj_clks(struct madera_fll *fll, int base, bool ena)
+{
+       return madera_set_fll_clks_reg(fll, ena,
+                                      base + MADERA_FLL_CONTROL_1_OFFS,
+                                      CS47L92_FLL1_REFCLK_SRC_MASK,
+                                      CS47L92_FLL1_REFCLK_SRC_SHIFT);
+}
+
 static void madera_disable_fll(struct madera_fll *fll)
 {
        struct madera *madera = fll->madera;
        unsigned int sync_base;
-       bool change;
+       bool ref_change, sync_change;
 
        switch (madera->type) {
        case CS47L35:
@@ -3880,18 +3944,23 @@ static void madera_disable_fll(struct madera_fll *fll)
                           MADERA_FLL1_FREERUN, MADERA_FLL1_FREERUN);
        regmap_update_bits_check(madera->regmap,
                                 fll->base + MADERA_FLL_CONTROL_1_OFFS,
-                                MADERA_FLL1_ENA, 0, &change);
-       regmap_update_bits(madera->regmap,
-                          sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
-                          MADERA_FLL1_SYNC_ENA, 0);
+                                MADERA_FLL1_ENA, 0, &ref_change);
+       regmap_update_bits_check(madera->regmap,
+                                sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
+                                MADERA_FLL1_SYNC_ENA, 0, &sync_change);
        regmap_update_bits(madera->regmap,
                           fll->base + MADERA_FLL_CONTROL_1_OFFS,
                           MADERA_FLL1_FREERUN, 0);
 
        madera_wait_for_fll(fll, false);
 
-       if (change)
+       if (sync_change)
+               madera_set_fll_clks(fll, sync_base, false);
+
+       if (ref_change) {
+               madera_set_fll_clks(fll, fll->base, false);
                pm_runtime_put_autosuspend(madera->dev);
+       }
 }
 
 static int madera_enable_fll(struct madera_fll *fll)
@@ -3947,6 +4016,10 @@ static int madera_enable_fll(struct madera_fll *fll)
                regmap_update_bits(fll->madera->regmap,
                                   fll->base + MADERA_FLL_CONTROL_7_OFFS,
                                   MADERA_FLL1_GAIN_MASK, 0);
+
+               if (sync_enabled > 0)
+                       madera_set_fll_clks(fll, sync_base, false);
+               madera_set_fll_clks(fll, fll->base, false);
        }
 
        /* Apply SYNCCLK setting */
@@ -4025,11 +4098,15 @@ static int madera_enable_fll(struct madera_fll *fll)
        if (!already_enabled)
                pm_runtime_get_sync(madera->dev);
 
-       if (have_sync)
+       if (have_sync) {
+               madera_set_fll_clks(fll, sync_base, true);
                regmap_update_bits(madera->regmap,
                                   sync_base + MADERA_FLL_SYNCHRONISER_1_OFFS,
                                   MADERA_FLL1_SYNC_ENA,
                                   MADERA_FLL1_SYNC_ENA);
+       }
+
+       madera_set_fll_clks(fll, fll->base, true);
        regmap_update_bits(madera->regmap,
                           fll->base + MADERA_FLL_CONTROL_1_OFFS,
                           MADERA_FLL1_ENA, MADERA_FLL1_ENA);
@@ -4201,6 +4278,9 @@ static int madera_enable_fll_ao(struct madera_fll *fll,
                           fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
                           MADERA_FLL_AO_HOLD, MADERA_FLL_AO_HOLD);
 
+       if (already_enabled)
+               madera_set_fllao_clks(fll, fll->base, false);
+
        for (i = 0; i < patch_size; i++) {
                val = patch[i].def;
 
@@ -4214,6 +4294,8 @@ static int madera_enable_fll_ao(struct madera_fll *fll,
                regmap_write(madera->regmap, patch[i].reg, val);
        }
 
+       madera_set_fllao_clks(fll, fll->base, true);
+
        regmap_update_bits(madera->regmap,
                           fll->base + MADERA_FLLAO_CONTROL_1_OFFS,
                           MADERA_FLL_AO_ENA, MADERA_FLL_AO_ENA);
@@ -4257,8 +4339,10 @@ static int madera_disable_fll_ao(struct madera_fll *fll)
                           fll->base + MADERA_FLLAO_CONTROL_2_OFFS,
                           MADERA_FLL_AO_CTRL_UPD_MASK, 0);
 
-       if (change)
+       if (change) {
+               madera_set_fllao_clks(fll, fll->base, false);
                pm_runtime_put_autosuspend(madera->dev);
+       }
 
        return 0;
 }
@@ -4344,8 +4428,10 @@ static int madera_fllhj_disable(struct madera_fll *fll)
                           fll->base + MADERA_FLL_CONTROL_2_OFFS,
                           MADERA_FLL1_CTRL_UPD_MASK, 0);
 
-       if (change)
+       if (change) {
+               madera_set_fllhj_clks(fll, fll->base, false);
                pm_runtime_put_autosuspend(madera->dev);
+       }
 
        return 0;
 }
@@ -4517,6 +4603,9 @@ static int madera_fllhj_enable(struct madera_fll *fll)
                           MADERA_FLL1_HOLD_MASK,
                           MADERA_FLL1_HOLD_MASK);
 
+       if (already_enabled)
+               madera_set_fllhj_clks(fll, fll->base, false);
+
        /* Apply refclk */
        ret = madera_fllhj_apply(fll, fll->ref_freq);
        if (ret) {
@@ -4528,6 +4617,8 @@ static int madera_fllhj_enable(struct madera_fll *fll)
                           CS47L92_FLL1_REFCLK_SRC_MASK,
                           fll->ref_src << CS47L92_FLL1_REFCLK_SRC_SHIFT);
 
+       madera_set_fllhj_clks(fll, fll->base, true);
+
        regmap_update_bits(madera->regmap,
                           fll->base + MADERA_FLL_CONTROL_1_OFFS,
                           MADERA_FLL1_ENA_MASK,