Skip to content

Commit

Permalink
ASoC: madera: Enable clocks for input pins when used for the FLL
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Charles Keepax authored and Mark Brown committed Dec 31, 2019
1 parent 1094af1 commit 3863857
Showing 1 changed file with 100 additions and 9 deletions.
109 changes: 100 additions & 9 deletions sound/soc/codecs/madera.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down

0 comments on commit 3863857

Please sign in to comment.