[alsa-devel] [PATCH 1/2] ASoC: madera: Enable clocks for input pins when used as a direct clock
When one of the MCLK pins is used to supply an internal clock directly enable the source clock for that pin.
Signed-off-by: Charles Keepax ckeepax@opensource.cirrus.com --- sound/soc/codecs/cs47l15.c | 8 ++++--- sound/soc/codecs/cs47l35.c | 6 +++-- sound/soc/codecs/cs47l85.c | 11 +++++---- sound/soc/codecs/cs47l90.c | 11 +++++---- sound/soc/codecs/cs47l92.c | 58 ++++++++++++++++++++++++++++++++++++++++++---- sound/soc/codecs/madera.c | 53 ++++++++++++++++++++++++++++++++++++++++-- sound/soc/codecs/madera.h | 2 ++ 7 files changed, 129 insertions(+), 20 deletions(-)
diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index ece1276f38eb9..513e2875e4c6e 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -438,11 +438,13 @@ static const struct snd_kcontrol_new cs47l15_aec_loopback_mux[] = { static const struct snd_soc_dapm_widget cs47l15_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index d396a8545d518..ba7aa6b31205c 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -521,11 +521,13 @@ static const struct snd_kcontrol_new cs47l35_aec_loopback_mux[] = { static const struct snd_soc_dapm_widget cs47l35_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, - 0, NULL, 0), + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 32fe7ffb75268..f85581a97bdc3 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -790,15 +790,18 @@ static const struct snd_kcontrol_new cs47l85_output_anc_src[] = { static const struct snd_soc_dapm_widget cs47l85_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, - MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + MADERA_ASYNC_CLK_ENA_SHIFT, 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 67cac60a859dd..c3b6f4d41005b 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -744,15 +744,18 @@ static const struct snd_kcontrol_new cs47l90_output_anc_src[] = { static const struct snd_soc_dapm_widget cs47l90_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, - MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + MADERA_ASYNC_CLK_ENA_SHIFT, 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index d50f75f3b3e41..663ce2b5605c2 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -163,6 +163,51 @@ static int cs47l92_adsp_power_ev(struct snd_soc_dapm_widget *w, return wm_adsp_early_event(w, kcontrol, event); }
+static int cs47l92_outclk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l92->core; + struct madera *madera = priv->madera; + unsigned int val; + int ret; + + ret = regmap_read(madera->regmap, MADERA_OUTPUT_RATE_1, &val); + if (ret) { + dev_err(madera->dev, "Failed to read OUTCLK source: %d\n", ret); + return ret; + } + + val &= MADERA_OUT_CLK_SRC_MASK; + + switch (val) { + case MADERA_OUTCLK_MCLK1: + case MADERA_OUTCLK_MCLK2: + case MADERA_OUTCLK_MCLK3: + val -= (MADERA_OUTCLK_MCLK1 - MADERA_MCLK1); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = clk_prepare_enable(madera->mclk[val].clk); + if (ret) + return ret; + break; + case SND_SOC_DAPM_POST_PMD: + clk_disable_unprepare(madera->mclk[val].clk); + break; + default: + break; + } + default: + break; + } + + return madera_domain_clk_ev(w, kcontrol, event); +} + #define CS47L92_NG_SRC(name, base) \ SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ @@ -615,15 +660,18 @@ static const struct snd_kcontrol_new cs47l92_aec_loopback_mux = static const struct snd_soc_dapm_widget cs47l92_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, - MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + MADERA_ASYNC_CLK_ENA_SHIFT, 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), @@ -666,7 +714,7 @@ SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, MADERA_DOM_GRP_OUT, 0, - madera_domain_clk_ev, + cs47l92_outclk_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, MADERA_DOM_GRP_SPD, 0, diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 52639811cc525..9b4b4c52b9e4b 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -163,6 +163,48 @@ static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = { MADERA_IRQ_DSP7_BUS_ERR, };
+int madera_clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + unsigned int val; + int clk_idx; + int ret; + + ret = regmap_read(madera->regmap, w->reg, &val); + if (ret) { + dev_err(madera->dev, "Failed to check clock source: %d\n", ret); + return ret; + } + + switch ((val & MADERA_SYSCLK_SRC_MASK) >> MADERA_SYSCLK_SRC_SHIFT) { + case MADERA_CLK_SRC_MCLK1: + clk_idx = MADERA_MCLK1; + break; + case MADERA_CLK_SRC_MCLK2: + clk_idx = MADERA_MCLK2; + break; + case MADERA_CLK_SRC_MCLK3: + clk_idx = MADERA_MCLK3; + break; + default: + return 0; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return clk_prepare_enable(madera->mclk[clk_idx].clk); + case SND_SOC_DAPM_POST_PMD: + clk_disable_unprepare(madera->mclk[clk_idx].clk); + return 0; + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(madera_clk_ev); + static void madera_spin_sysclk(struct madera_priv *priv) { struct madera *madera = priv->madera; @@ -193,9 +235,16 @@ int madera_sysclk_ev(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct madera_priv *priv = snd_soc_component_get_drvdata(component);
- madera_spin_sysclk(priv); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + case SND_SOC_DAPM_PRE_PMD: + madera_spin_sysclk(priv); + break; + default: + break; + }
- return 0; + return madera_clk_ev(w, kcontrol, event); } EXPORT_SYMBOL_GPL(madera_sysclk_ev);
diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h index 6d8938a3fb647..49a8f68ec43da 100644 --- a/sound/soc/codecs/madera.h +++ b/sound/soc/codecs/madera.h @@ -383,6 +383,8 @@ int madera_eq_coeff_put(struct snd_kcontrol *kcontrol, int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int madera_clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); int madera_sysclk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int madera_spk_ev(struct snd_soc_dapm_widget *w,
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 --- sound/soc/codecs/madera.c | 109 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 9b4b4c52b9e4b..12dc468ae6bf0 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -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,
The patch
ASoC: madera: Enable clocks for input pins when used for the FLL
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.6
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 3863857dd5ca3e60685c6b49a7873fda727ff233 Mon Sep 17 00:00:00 2001
From: Charles Keepax ckeepax@opensource.cirrus.com Date: Mon, 30 Dec 2019 14:35:17 +0000 Subject: [PATCH] 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.c... Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/madera.c | 109 ++++++++++++++++++++++++++++++++++---- 1 file changed, 100 insertions(+), 9 deletions(-)
diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 9b4b4c52b9e4..12dc468ae6bf 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -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,
The patch
ASoC: madera: Enable clocks for input pins when used as a direct clock
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.6
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From 1094af1199007976370b8f04b4d6668ad9707954 Mon Sep 17 00:00:00 2001
From: Charles Keepax ckeepax@opensource.cirrus.com Date: Mon, 30 Dec 2019 14:35:16 +0000 Subject: [PATCH] ASoC: madera: Enable clocks for input pins when used as a direct clock
When one of the MCLK pins is used to supply an internal clock directly enable the source clock for that pin.
Signed-off-by: Charles Keepax ckeepax@opensource.cirrus.com Link: https://lore.kernel.org/r/20191230143517.21005-1-ckeepax@opensource.cirrus.c... Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/cs47l15.c | 8 ++++-- sound/soc/codecs/cs47l35.c | 6 ++-- sound/soc/codecs/cs47l85.c | 11 +++++--- sound/soc/codecs/cs47l90.c | 11 +++++--- sound/soc/codecs/cs47l92.c | 58 ++++++++++++++++++++++++++++++++++---- sound/soc/codecs/madera.c | 53 ++++++++++++++++++++++++++++++++-- sound/soc/codecs/madera.h | 2 ++ 7 files changed, 129 insertions(+), 20 deletions(-)
diff --git a/sound/soc/codecs/cs47l15.c b/sound/soc/codecs/cs47l15.c index ece1276f38eb..513e2875e4c6 100644 --- a/sound/soc/codecs/cs47l15.c +++ b/sound/soc/codecs/cs47l15.c @@ -438,11 +438,13 @@ static const struct snd_kcontrol_new cs47l15_aec_loopback_mux[] = { static const struct snd_soc_dapm_widget cs47l15_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), diff --git a/sound/soc/codecs/cs47l35.c b/sound/soc/codecs/cs47l35.c index d396a8545d51..ba7aa6b31205 100644 --- a/sound/soc/codecs/cs47l35.c +++ b/sound/soc/codecs/cs47l35.c @@ -521,11 +521,13 @@ static const struct snd_kcontrol_new cs47l35_aec_loopback_mux[] = { static const struct snd_soc_dapm_widget cs47l35_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, - 0, NULL, 0), + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), diff --git a/sound/soc/codecs/cs47l85.c b/sound/soc/codecs/cs47l85.c index 32fe7ffb7526..f85581a97bdc 100644 --- a/sound/soc/codecs/cs47l85.c +++ b/sound/soc/codecs/cs47l85.c @@ -790,15 +790,18 @@ static const struct snd_kcontrol_new cs47l85_output_anc_src[] = { static const struct snd_soc_dapm_widget cs47l85_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, - MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + MADERA_ASYNC_CLK_ENA_SHIFT, 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), diff --git a/sound/soc/codecs/cs47l90.c b/sound/soc/codecs/cs47l90.c index 67cac60a859d..c3b6f4d41005 100644 --- a/sound/soc/codecs/cs47l90.c +++ b/sound/soc/codecs/cs47l90.c @@ -744,15 +744,18 @@ static const struct snd_kcontrol_new cs47l90_output_anc_src[] = { static const struct snd_soc_dapm_widget cs47l90_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, - MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + MADERA_ASYNC_CLK_ENA_SHIFT, 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), diff --git a/sound/soc/codecs/cs47l92.c b/sound/soc/codecs/cs47l92.c index 536b7d35d6b2..cbffcd84766d 100644 --- a/sound/soc/codecs/cs47l92.c +++ b/sound/soc/codecs/cs47l92.c @@ -163,6 +163,51 @@ static int cs47l92_adsp_power_ev(struct snd_soc_dapm_widget *w, return wm_adsp_early_event(w, kcontrol, event); }
+static int cs47l92_outclk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component); + struct madera_priv *priv = &cs47l92->core; + struct madera *madera = priv->madera; + unsigned int val; + int ret; + + ret = regmap_read(madera->regmap, MADERA_OUTPUT_RATE_1, &val); + if (ret) { + dev_err(madera->dev, "Failed to read OUTCLK source: %d\n", ret); + return ret; + } + + val &= MADERA_OUT_CLK_SRC_MASK; + + switch (val) { + case MADERA_OUTCLK_MCLK1: + case MADERA_OUTCLK_MCLK2: + case MADERA_OUTCLK_MCLK3: + val -= (MADERA_OUTCLK_MCLK1 - MADERA_MCLK1); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = clk_prepare_enable(madera->mclk[val].clk); + if (ret) + return ret; + break; + case SND_SOC_DAPM_POST_PMD: + clk_disable_unprepare(madera->mclk[val].clk); + break; + default: + break; + } + default: + break; + } + + return madera_domain_clk_ev(w, kcontrol, event); +} + #define CS47L92_NG_SRC(name, base) \ SOC_SINGLE(name " NG HPOUT1L Switch", base, 0, 1, 0), \ SOC_SINGLE(name " NG HPOUT1R Switch", base, 1, 1, 0), \ @@ -615,15 +660,18 @@ static const struct snd_kcontrol_new cs47l92_aec_loopback_mux = static const struct snd_soc_dapm_widget cs47l92_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("SYSCLK", MADERA_SYSTEM_CLOCK_1, MADERA_SYSCLK_ENA_SHIFT, 0, madera_sysclk_ev, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("ASYNCCLK", MADERA_ASYNC_CLOCK_1, - MADERA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), + MADERA_ASYNC_CLK_ENA_SHIFT, 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OPCLK", MADERA_OUTPUT_SYSTEM_CLOCK, MADERA_OPCLK_ENA_SHIFT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", MADERA_OUTPUT_ASYNC_CLOCK, MADERA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, - MADERA_DSP_CLK_ENA_SHIFT, 0, NULL, 0), +SND_SOC_DAPM_SUPPLY("DSPCLK", MADERA_DSP_CLOCK_1, MADERA_DSP_CLK_ENA_SHIFT, + 0, madera_clk_ev, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD1", 20, 0), SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD2", 20, 0), @@ -666,7 +714,7 @@ SND_SOC_DAPM_SUPPLY("ISRC2CLK", SND_SOC_NOPM, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("OUTCLK", SND_SOC_NOPM, MADERA_DOM_GRP_OUT, 0, - madera_domain_clk_ev, + cs47l92_outclk_ev, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("SPDCLK", SND_SOC_NOPM, MADERA_DOM_GRP_SPD, 0, diff --git a/sound/soc/codecs/madera.c b/sound/soc/codecs/madera.c index 52639811cc52..9b4b4c52b9e4 100644 --- a/sound/soc/codecs/madera.c +++ b/sound/soc/codecs/madera.c @@ -163,6 +163,48 @@ static const int madera_dsp_bus_error_irqs[MADERA_MAX_ADSP] = { MADERA_IRQ_DSP7_BUS_ERR, };
+int madera_clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct madera_priv *priv = snd_soc_component_get_drvdata(component); + struct madera *madera = priv->madera; + unsigned int val; + int clk_idx; + int ret; + + ret = regmap_read(madera->regmap, w->reg, &val); + if (ret) { + dev_err(madera->dev, "Failed to check clock source: %d\n", ret); + return ret; + } + + switch ((val & MADERA_SYSCLK_SRC_MASK) >> MADERA_SYSCLK_SRC_SHIFT) { + case MADERA_CLK_SRC_MCLK1: + clk_idx = MADERA_MCLK1; + break; + case MADERA_CLK_SRC_MCLK2: + clk_idx = MADERA_MCLK2; + break; + case MADERA_CLK_SRC_MCLK3: + clk_idx = MADERA_MCLK3; + break; + default: + return 0; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + return clk_prepare_enable(madera->mclk[clk_idx].clk); + case SND_SOC_DAPM_POST_PMD: + clk_disable_unprepare(madera->mclk[clk_idx].clk); + return 0; + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(madera_clk_ev); + static void madera_spin_sysclk(struct madera_priv *priv) { struct madera *madera = priv->madera; @@ -193,9 +235,16 @@ int madera_sysclk_ev(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct madera_priv *priv = snd_soc_component_get_drvdata(component);
- madera_spin_sysclk(priv); + switch (event) { + case SND_SOC_DAPM_POST_PMU: + case SND_SOC_DAPM_PRE_PMD: + madera_spin_sysclk(priv); + break; + default: + break; + }
- return 0; + return madera_clk_ev(w, kcontrol, event); } EXPORT_SYMBOL_GPL(madera_sysclk_ev);
diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h index 6d8938a3fb64..49a8f68ec43d 100644 --- a/sound/soc/codecs/madera.h +++ b/sound/soc/codecs/madera.h @@ -383,6 +383,8 @@ int madera_eq_coeff_put(struct snd_kcontrol *kcontrol, int madera_lhpf_coeff_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol);
+int madera_clk_ev(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event); int madera_sysclk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int madera_spk_ev(struct snd_soc_dapm_widget *w,
participants (2)
-
Charles Keepax
-
Mark Brown