Unverified Commit 6ea304a4 authored by Derek Fang's avatar Derek Fang Committed by Mark Brown
Browse files

ASoC: rt5682s: Reduce coupling of I2S1 setting



Some parts of rt5682s CCF function are implemented
by 'I2S1' dapm widget.
The coupling risk exists, so this patch fixes it.

Signed-off-by: default avatarDerek Fang <derek.fang@realtek.com>
Link: https://lore.kernel.org/r/20220913025658.5005-2-derek.fang@realtek.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent bfc5e8b8
Loading
Loading
Loading
Loading
+66 −38
Original line number Diff line number Diff line
@@ -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 -EINVAL;
			return;
		}

		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, c_reg, c_mask, pre_div << c_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:
		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_PWR_LDO, 0);
		if (!rt5682s->wclk_enabled)
			regmap_update_bits(rt5682s->regmap, RT5682S_PWR_DIG_1,
			RT5682S_DIG_GATE_CTRL | RT5682S_PWR_LDO, 0);
				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);