ASoC: rt5682s: Reduce coupling of I2S1 setting
authorDerek Fang <derek.fang@realtek.com>
Tue, 13 Sep 2022 02:56:57 +0000 (10:56 +0800)
committerMark Brown <broonie@kernel.org>
Mon, 19 Sep 2022 16:52:49 +0000 (17:52 +0100)
Some parts of rt5682s CCF function are implemented
by 'I2S1' dapm widget.
The coupling risk exists, so this patch fixes it.

Signed-off-by: Derek Fang <derek.fang@realtek.com>
Link: https://lore.kernel.org/r/20220913025658.5005-2-derek.fang@realtek.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/rt5682s.c

index c5c55d146ddf3fc66fc4bef0faf17e6260bc7011..325d227a2b37a55effcfaa3878ee1f4f11cc5c7f 100644 (file)
@@ -1229,41 +1229,58 @@ static int set_dmic_power(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
-static int set_i2s_clk(struct snd_soc_dapm_widget *w,
-               struct snd_kcontrol *kcontrol, int event)
+static void rt5682s_set_i2s(struct rt5682s_priv *rt5682s, int id, int on)
 {
-       struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
-       struct rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component);
-       int pre_div, id;
-       unsigned int reg, mask, sft;
-
-       if (event != SND_SOC_DAPM_PRE_PMU)
-               return 0;
-
-       if (w->shift == RT5682S_PWR_I2S2_BIT) {
-               id = RT5682S_AIF2;
-               reg = RT5682S_I2S2_M_CLK_CTRL_1;
-               mask = RT5682S_I2S2_M_D_MASK;
-               sft = RT5682S_I2S2_M_D_SFT;
+       struct snd_soc_component *component = rt5682s->component;
+       int pre_div;
+       unsigned int p_reg, p_mask, p_sft;
+       unsigned int c_reg, c_mask, c_sft;
+
+       if (id == RT5682S_AIF1) {
+               c_reg = RT5682S_ADDA_CLK_1;
+               c_mask = RT5682S_I2S_M_D_MASK;
+               c_sft = RT5682S_I2S_M_D_SFT;
+               p_reg = RT5682S_PWR_DIG_1;
+               p_mask = RT5682S_PWR_I2S1;
+               p_sft = RT5682S_PWR_I2S1_BIT;
        } else {
-               id = RT5682S_AIF1;
-               reg = RT5682S_ADDA_CLK_1;
-               mask = RT5682S_I2S_M_D_MASK;
-               sft = RT5682S_I2S_M_D_SFT;
+               c_reg = RT5682S_I2S2_M_CLK_CTRL_1;
+               c_mask = RT5682S_I2S2_M_D_MASK;
+               c_sft = RT5682S_I2S2_M_D_SFT;
+               p_reg = RT5682S_PWR_DIG_1;
+               p_mask = RT5682S_PWR_I2S2;
+               p_sft = RT5682S_PWR_I2S2_BIT;
        }
 
-       if (!rt5682s->master[id])
-               return 0;
+       if (on && rt5682s->master[id]) {
+               pre_div = get_clk_info(rt5682s->sysclk, rt5682s->lrck[id]);
+               if (pre_div < 0) {
+                       dev_err(component->dev, "get pre_div failed\n");
+                       return;
+               }
 
-       pre_div = get_clk_info(rt5682s->sysclk, rt5682s->lrck[id]);
-       if (pre_div < 0) {
-               dev_err(component->dev, "get pre_div failed\n");
-               return -EINVAL;
+               dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d master\n",
+                       rt5682s->lrck[id], pre_div, id);
+               snd_soc_component_update_bits(component, c_reg, c_mask, pre_div << c_sft);
        }
 
-       dev_dbg(component->dev, "lrck is %dHz and pre_div is %d for iis %d master\n",
-               rt5682s->lrck[id], pre_div, id);
-       snd_soc_component_update_bits(component, reg, mask, pre_div << sft);
+       snd_soc_component_update_bits(component, p_reg, p_mask, on << p_sft);
+}
+
+static int set_i2s_event(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 rt5682s_priv *rt5682s = snd_soc_component_get_drvdata(component);
+       int on = 0;
+
+       if (SND_SOC_DAPM_EVENT_ON(event))
+               on = 1;
+
+       if (!strcmp(w->name, "I2S1") && !rt5682s->wclk_enabled)
+               rt5682s_set_i2s(rt5682s, RT5682S_AIF1, on);
+       else if (!strcmp(w->name, "I2S2"))
+               rt5682s_set_i2s(rt5682s, RT5682S_AIF2, on);
 
        return 0;
 }
@@ -1715,10 +1732,10 @@ static const struct snd_soc_dapm_widget rt5682s_dapm_widgets[] = {
        SND_SOC_DAPM_PGA("Stereo1 ADC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),
 
        /* Digital Interface */
-       SND_SOC_DAPM_SUPPLY("I2S1", RT5682S_PWR_DIG_1, RT5682S_PWR_I2S1_BIT,
-               0, set_i2s_clk, SND_SOC_DAPM_PRE_PMU),
-       SND_SOC_DAPM_SUPPLY("I2S2", RT5682S_PWR_DIG_1, RT5682S_PWR_I2S2_BIT,
-               0, set_i2s_clk, SND_SOC_DAPM_PRE_PMU),
+       SND_SOC_DAPM_SUPPLY("I2S1", SND_SOC_NOPM, 0, 0,
+               set_i2s_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+       SND_SOC_DAPM_SUPPLY("I2S2", SND_SOC_NOPM, 0, 0,
+               set_i2s_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
        SND_SOC_DAPM_PGA("IF1 DAC1 L", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("IF1 DAC1 R", SND_SOC_NOPM, 0, 0, NULL, 0),
 
@@ -2426,12 +2443,15 @@ static int rt5682s_set_bias_level(struct snd_soc_component *component,
                        RT5682S_PWR_LDO, RT5682S_PWR_LDO);
                break;
        case SND_SOC_BIAS_STANDBY:
-               regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1,
-                       RT5682S_DIG_GATE_CTRL, RT5682S_DIG_GATE_CTRL);
+               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+                       regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1,
+                               RT5682S_DIG_GATE_CTRL, RT5682S_DIG_GATE_CTRL);
                break;
        case SND_SOC_BIAS_OFF:
-               regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1,
-                       RT5682S_DIG_GATE_CTRL | RT5682S_PWR_LDO, 0);
+               regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1, RT5682S_PWR_LDO, 0);
+               if (!rt5682s->wclk_enabled)
+                       regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1,
+                               RT5682S_DIG_GATE_CTRL, 0);
                break;
        case SND_SOC_BIAS_ON:
                break;
@@ -2473,13 +2493,17 @@ static int rt5682s_wclk_prepare(struct clk_hw *hw)
        snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1,
                RT5682S_PWR_FV2, RT5682S_PWR_FV2);
 
+       /* Set and power on I2S1 */
+       snd_soc_component_update_bits(component, RT5682S_PWR_DIG_1,
+               RT5682S_DIG_GATE_CTRL, RT5682S_DIG_GATE_CTRL);
+       rt5682s_set_i2s(rt5682s, RT5682S_AIF1, 1);
+
        rt5682s->wclk_enabled = 1;
 
        mutex_unlock(&rt5682s->wclk_mutex);
 
        snd_soc_dapm_mutex_lock(dapm);
 
-       snd_soc_dapm_force_enable_pin_unlocked(dapm, "I2S1");
        /* Only need to power PLLB due to the rate set restriction */
        snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLLB");
        snd_soc_dapm_sync_unlocked(dapm);
@@ -2505,13 +2529,17 @@ static void rt5682s_wclk_unprepare(struct clk_hw *hw)
                snd_soc_component_update_bits(component, RT5682S_PWR_ANLG_1,
                        RT5682S_PWR_VREF2 | RT5682S_PWR_FV2 | RT5682S_PWR_MB, 0);
 
+       /* Power down I2S1 */
+       rt5682s_set_i2s(rt5682s, RT5682S_AIF1, 0);
+       snd_soc_component_update_bits(component, RT5682S_PWR_DIG_1,
+               RT5682S_DIG_GATE_CTRL, 0);
+
        rt5682s->wclk_enabled = 0;
 
        mutex_unlock(&rt5682s->wclk_mutex);
 
        snd_soc_dapm_mutex_lock(dapm);
 
-       snd_soc_dapm_disable_pin_unlocked(dapm, "I2S1");
        snd_soc_dapm_disable_pin_unlocked(dapm, "PLLB");
        snd_soc_dapm_sync_unlocked(dapm);