ASoC: madera: Enable clocks for input pins when used for the FLL

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>
This commit is contained in:
Charles Keepax 2019-12-30 14:35:17 +00:00 committed by Mark Brown
parent 1094af1199
commit 3863857dd5
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 100 additions and 9 deletions

View 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,