diff mbox series

[2/3] ASoC: rt5682s: Reduce coupling of I2S1 setting

Message ID 20220913025658.5005-2-derek.fang@realtek.com (mailing list archive)
State Accepted
Commit 6ea304a402322ed4449156805b0a79fa1e326ca7
Headers show
Series [1/3] ASoC: rt5682s: Reduce coupling of Micbias and Vref2 settings | expand

Commit Message

Derek [方德義] Sept. 13, 2022, 2:56 a.m. UTC
From: Derek Fang <derek.fang@realtek.com>

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>
---
 sound/soc/codecs/rt5682s.c | 104 +++++++++++++++++++++++--------------
 1 file changed, 66 insertions(+), 38 deletions(-)
diff mbox series

Patch

diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c
index c5c55d146ddf..325d227a2b37 100644
--- a/sound/soc/codecs/rt5682s.c
+++ b/sound/soc/codecs/rt5682s.c
@@ -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);