Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70586523 authored by Phani Kumar Uppalapati's avatar Phani Kumar Uppalapati
Browse files

ASoC: wcd9335: Update HIFI mode sequence for headphones



Update HIFI mode register sequence for headphones on
wcd9335 codec for better performance.

Change-Id: I277a38847d02c4500cc3d2c77b00fbe4a63e2f83
Signed-off-by: default avatarPhani Kumar Uppalapati <phaniu@codeaurora.org>
parent ac6766f8
Loading
Loading
Loading
Loading
+172 −11
Original line number Diff line number Diff line
@@ -335,6 +335,7 @@ enum {
	AIF4_SWITCH_VALUE,
	AUDIO_NOMINAL,
	CPE_NOMINAL,
	HPH_PA_DELAY,
};

enum {
@@ -757,6 +758,8 @@ struct tasha_priv {
	int spkr_mode;
	struct hpf_work tx_hpf_work[TASHA_NUM_DECIMATORS];
	struct tx_mute_work tx_mute_dwork[TASHA_NUM_DECIMATORS];
	int hph_l_gain;
	int hph_r_gain;
};

static int tasha_codec_vote_max_bw(struct snd_soc_codec *codec,
@@ -3518,22 +3521,80 @@ err:
	return ret;
}

static void tasha_codec_hph_post_pa_config(struct tasha_priv *tasha,
					   int mode, int event)
{
	u8 scale_val = 0;

	if (!TASHA_IS_2_0(tasha->wcd9xxx->version))
		return;

	switch (event) {
	case SND_SOC_DAPM_POST_PMU:
		switch (mode) {
		case CLS_H_HIFI:
			scale_val = 0x3;
			break;
		case CLS_H_LOHIFI:
			scale_val = 0x1;
			break;
		}
		break;
	case SND_SOC_DAPM_PRE_PMD:
		scale_val = 0x6;
		break;
	}

	if (scale_val)
		snd_soc_update_bits(tasha->codec, WCD9335_HPH_PA_CTL1, 0x0E,
				    scale_val << 1);
	if (SND_SOC_DAPM_EVENT_ON(event)) {
		if (tasha->comp_enabled[COMPANDER_1] ||
		    tasha->comp_enabled[COMPANDER_2]) {
			snd_soc_update_bits(tasha->codec, WCD9335_HPH_L_EN,
					    0x20, 0x00);
			snd_soc_update_bits(tasha->codec, WCD9335_HPH_R_EN,
					    0x20, 0x00);
			snd_soc_update_bits(tasha->codec, WCD9335_HPH_AUTO_CHOP,
					    0x20, 0x20);
		}
		snd_soc_update_bits(tasha->codec, WCD9335_HPH_L_EN, 0x1F,
				    tasha->hph_l_gain);
		snd_soc_update_bits(tasha->codec, WCD9335_HPH_R_EN, 0x1F,
				    tasha->hph_r_gain);
	}

	if (SND_SOC_DAPM_EVENT_OFF(event)) {
		snd_soc_update_bits(tasha->codec, WCD9335_HPH_AUTO_CHOP, 0x20,
				    0x00);
	}
}

static int tasha_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
				      struct snd_kcontrol *kcontrol,
				      int event)
{
	struct snd_soc_codec *codec = w->codec;
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	int hph_mode = tasha->hph_mode;
	int ret = 0;

	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		set_bit(HPH_PA_DELAY, &tasha->status_mask);
		break;
	case SND_SOC_DAPM_POST_PMU:
		/* 5ms sleep is required after PA is enabled as per
		/*
		 * 7ms sleep is required after PA is enabled as per
		 * HW requirement
		 */
		usleep_range(5000, 5500);
		if (test_bit(HPH_PA_DELAY, &tasha->status_mask)) {
			usleep_range(7000, 7100);
			clear_bit(HPH_PA_DELAY, &tasha->status_mask);
		}
		tasha_codec_hph_post_pa_config(tasha, hph_mode, event);
		snd_soc_update_bits(codec, WCD9335_CDC_RX2_RX_PATH_CTL,
				    0x10, 0x00);
		/* Remove mix path mute if it is enabled */
@@ -3547,6 +3608,7 @@ static int tasha_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
		blocking_notifier_call_chain(&tasha->notifier,
					WCD_EVENT_PRE_HPHR_PA_OFF,
					&tasha->mbhc);
		tasha_codec_hph_post_pa_config(tasha, hph_mode, event);
		break;
	case SND_SOC_DAPM_POST_PMD:
		/* 5ms sleep is required after PA is disabled as per
@@ -3574,16 +3636,26 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
{
	struct snd_soc_codec *codec = w->codec;
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	int hph_mode = tasha->hph_mode;
	int ret = 0;

	dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);

	switch (event) {
	case SND_SOC_DAPM_PRE_PMU:
		set_bit(HPH_PA_DELAY, &tasha->status_mask);
		break;
	case SND_SOC_DAPM_POST_PMU:
		/* 5ms sleep is required after PA is enabled as per
		/*
		 * 7ms sleep is required after PA is enabled as per
		 * HW requirement
		 */
		usleep_range(5000, 5500);
		if (test_bit(HPH_PA_DELAY, &tasha->status_mask)) {
			usleep_range(7000, 7100);
			clear_bit(HPH_PA_DELAY, &tasha->status_mask);
		}

		tasha_codec_hph_post_pa_config(tasha, hph_mode, event);
		snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CTL,
				    0x10, 0x00);
		/* Remove mix path mute if it is enabled */
@@ -3597,6 +3669,7 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
		blocking_notifier_call_chain(&tasha->notifier,
					WCD_EVENT_PRE_HPHL_PA_OFF,
					&tasha->mbhc);
		tasha_codec_hph_post_pa_config(tasha, hph_mode, event);
		break;
	case SND_SOC_DAPM_POST_PMD:
		/* 5ms sleep is required after PA is disabled as per
@@ -3726,8 +3799,43 @@ static int tasha_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
	return ret;
}

static void tasha_codec_hph_mode_gain_opt(struct snd_soc_codec *codec,
					  u8 gain)
{
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	u8 hph_l_en, hph_r_en;
	u8 l_val, r_val;
	u8 hph_pa_status;
	bool is_hphl_pa, is_hphr_pa;

	hph_pa_status = snd_soc_read(codec, WCD9335_ANA_HPH);
	is_hphl_pa = hph_pa_status >> 7;
	is_hphr_pa = (hph_pa_status & 0x40) >> 6;

	hph_l_en = snd_soc_read(codec, WCD9335_HPH_L_EN);
	hph_r_en = snd_soc_read(codec, WCD9335_HPH_R_EN);

	l_val = (hph_l_en & 0xC0) | 0x20 | gain;
	r_val = (hph_r_en & 0xC0) | 0x20 | gain;

	/*
	 * Set HPH_L & HPH_R gain source selection to REGISTER
	 * for better click and pop only if corresponding PAs are
	 * not enabled. Also cache the values of the HPHL/R
	 * PA gains to be applied after PAs are enabled
	 */
	if ((l_val != hph_l_en) && !is_hphl_pa) {
		snd_soc_write(codec, WCD9335_HPH_L_EN, l_val);
		tasha->hph_l_gain = hph_l_en & 0x1F;
	}

	if ((r_val != hph_r_en) && !is_hphr_pa) {
		snd_soc_write(codec, WCD9335_HPH_R_EN, r_val);
		tasha->hph_r_gain = hph_r_en & 0x1F;
	}
}

static void tasha_codec_hph_lohifi_config(struct snd_soc_codec *codec,
					  struct tasha_priv *tasha,
					  int event)
{
	if (SND_SOC_DAPM_EVENT_ON(event)) {
@@ -3747,7 +3855,6 @@ static void tasha_codec_hph_lohifi_config(struct snd_soc_codec *codec,
}

static void tasha_codec_hph_lp_config(struct snd_soc_codec *codec,
				      struct tasha_priv *tasha,
				      int event)
{
	if (SND_SOC_DAPM_EVENT_ON(event)) {
@@ -3777,6 +3884,22 @@ static void tasha_codec_hph_lp_config(struct snd_soc_codec *codec,
	}
}

static void tasha_codec_hph_hifi_config(struct snd_soc_codec *codec,
					int event)
{
	if (SND_SOC_DAPM_EVENT_ON(event)) {
		snd_soc_update_bits(codec, WCD9335_HPH_CNP_WG_CTL, 0x07, 0x03);
		snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x08);
		snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x0C);
		tasha_codec_hph_mode_gain_opt(codec, 0x11);
	}

	if (SND_SOC_DAPM_EVENT_OFF(event)) {
		snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x00);
		snd_soc_update_bits(codec, WCD9335_HPH_CNP_WG_CTL, 0x07, 0x02);
	}
}

static void tasha_codec_hph_mode_config(struct snd_soc_codec *codec,
					int event, int mode)
{
@@ -3787,10 +3910,13 @@ static void tasha_codec_hph_mode_config(struct snd_soc_codec *codec,

	switch (mode) {
	case CLS_H_LP:
		tasha_codec_hph_lp_config(codec, tasha, event);
		tasha_codec_hph_lp_config(codec, event);
		break;
	case CLS_H_LOHIFI:
		tasha_codec_hph_lohifi_config(codec, tasha, event);
		tasha_codec_hph_lohifi_config(codec, event);
		break;
	case CLS_H_HIFI:
		tasha_codec_hph_hifi_config(codec, event);
		break;
	}
}
@@ -4127,6 +4253,38 @@ static u16 tasha_interp_get_primary_reg(u16 reg, u16 *ind)
	return prim_int_reg;
}

static void tasha_codec_hd2_control(struct snd_soc_codec *codec,
				    u16 prim_int_reg, int event)
{
	struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
	u16 hd2_scale_reg;
	u16 hd2_enable_reg = 0;

	if (!TASHA_IS_2_0(tasha->wcd9xxx->version))
		return;

	if (prim_int_reg == WCD9335_CDC_RX1_RX_PATH_CTL) {
		hd2_scale_reg = WCD9335_CDC_RX1_RX_PATH_SEC3;
		hd2_enable_reg = WCD9335_CDC_RX1_RX_PATH_CFG0;
	}
	if (prim_int_reg == WCD9335_CDC_RX2_RX_PATH_CTL) {
		hd2_scale_reg = WCD9335_CDC_RX2_RX_PATH_SEC3;
		hd2_enable_reg = WCD9335_CDC_RX2_RX_PATH_CFG0;
	}

	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
		snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x10);
		snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x01);
		snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
	}

	if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
		snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
		snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x00);
		snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
	}
}

static int tasha_codec_enable_prim_interpolator(
				struct snd_soc_codec *codec,
				u16 reg, int event)
@@ -4143,6 +4301,7 @@ static int tasha_codec_enable_prim_interpolator(
		if (tasha->prim_int_users[ind] == 1) {
			snd_soc_update_bits(codec, prim_int_reg,
					    0x10, 0x10);
			tasha_codec_hd2_control(codec, prim_int_reg, event);
			snd_soc_update_bits(codec, prim_int_reg,
					    1 << 0x5, 1 << 0x5);
		}
@@ -4159,6 +4318,7 @@ static int tasha_codec_enable_prim_interpolator(
					0x40, 0x40);
			snd_soc_update_bits(codec, prim_int_reg,
					0x40, 0x00);
			tasha_codec_hd2_control(codec, prim_int_reg, event);
		}
		break;
	};
@@ -9749,11 +9909,11 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = {
			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_PGA_E("ANC HPHL PA", WCD9335_ANA_HPH, 7, 0, NULL, 0,
			   tasha_codec_enable_hphl_pa,
			   SND_SOC_DAPM_POST_PMU |
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_PGA_E("ANC HPHR PA", WCD9335_ANA_HPH, 6, 0, NULL, 0,
			   tasha_codec_enable_hphr_pa,
			   SND_SOC_DAPM_POST_PMU |
			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
			   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
	SND_SOC_DAPM_PGA_E("ANC LINEOUT1 PA", WCD9335_ANA_LO_1_2,
				7, 0, NULL, 0,
@@ -10805,7 +10965,6 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_val_2_0[] = {
	{WCD9335_HPH_OCP_CTL, 0xFF, 0x5A},
	{WCD9335_HPH_L_TEST, 0x01, 0x01},
	{WCD9335_HPH_R_TEST, 0x01, 0x01},
	{WCD9335_FLYBACK_VNEG_DAC_CTRL_2, 0xE0, 0x20},
	{WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
	{WCD9335_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08},
	{WCD9335_CDC_COMPANDER7_CTL7, 0x1E, 0x18},
@@ -10814,6 +10973,8 @@ static const struct tasha_reg_mask_val tasha_codec_reg_init_val_2_0[] = {
	{WCD9335_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
	{WCD9335_CDC_TX0_TX_PATH_SEC7, 0xFF, 0x45},
	{WCD9335_CDC_RX0_RX_PATH_SEC0, 0xFC, 0xF4},
	{WCD9335_HPH_REFBUFF_LP_CTL, 0x08, 0x08},
	{WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02},
};

static const struct tasha_reg_mask_val tasha_codec_reg_defaults[] = {
+4 −4
Original line number Diff line number Diff line
@@ -660,13 +660,13 @@ static void wcd_clsh_state_hph_r(struct snd_soc_codec *codec,
					    0x40, 0x40);
		}
		wcd_clsh_set_buck_regulator_mode(codec, mode);
		wcd_clsh_set_buck_mode(codec, mode);
		wcd_clsh_set_flyback_mode(codec, mode);
		wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
		wcd_clsh_set_flyback_current(codec, mode);
		wcd_clsh_set_buck_mode(codec, mode);
		wcd_clsh_buck_ctrl(codec, clsh_d, mode, true);
		wcd_clsh_set_gain_path(codec, mode);
		wcd_clsh_set_hph_mode(codec, mode);
		wcd_clsh_set_gain_path(codec, mode);
	} else {
		wcd_clsh_set_hph_mode(codec, CLS_H_NORMAL);

@@ -714,13 +714,13 @@ static void wcd_clsh_state_hph_l(struct snd_soc_codec *codec,
					    0x40, 0x40);
		}
		wcd_clsh_set_buck_regulator_mode(codec, mode);
		wcd_clsh_set_buck_mode(codec, mode);
		wcd_clsh_set_flyback_mode(codec, mode);
		wcd_clsh_flyback_ctrl(codec, clsh_d, mode, true);
		wcd_clsh_set_flyback_current(codec, mode);
		wcd_clsh_set_buck_mode(codec, mode);
		wcd_clsh_buck_ctrl(codec, clsh_d, mode, true);
		wcd_clsh_set_gain_path(codec, mode);
		wcd_clsh_set_hph_mode(codec, mode);
		wcd_clsh_set_gain_path(codec, mode);
	} else {
		wcd_clsh_set_hph_mode(codec, CLS_H_NORMAL);