summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h6
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c190
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.c108
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.h4
4 files changed, 283 insertions, 25 deletions
diff --git a/include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h b/include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h
index a9fe10d8cd6e..7902cfbafad8 100644
--- a/include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h
+++ b/include/uapi/linux/mfd/wcd9xxx/wcd9xxx_registers.h
@@ -352,4 +352,10 @@
#define WCD9XXX_CDC_RX2_RX_VOL_MIX_CTL (0xB70)
#define WCD9XXX_CDC_RX2_RX_PATH_SEC1 (0xB72)
+/* Class-H registers for codecs from and above WCD934X */
+#define WCD9XXX_HPH_CNP_WG_CTL (0x06cc)
+#define WCD9XXX_FLYBACK_VNEG_CTRL_4 (0x06a8)
+#define WCD9XXX_HPH_NEW_INT_PA_MISC2 (0x0738)
+#define WCD9XXX_RX_BIAS_HPH_LOWPOWER (0x06bf)
+#define WCD9XXX_HPH_PA_CTL1 (0x06d1)
#endif
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 84e5c09494c6..5713014c436f 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -1384,6 +1384,27 @@ static int tavil_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
return 0;
}
+static void tavil_codec_override(struct snd_soc_codec *codec, int mode,
+ int event)
+{
+ if (mode == CLS_AB || mode == CLS_AB_HIFI) {
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (!(snd_soc_read(codec,
+ WCD934X_CDC_RX2_RX_PATH_CTL) & 0x10) &&
+ (!(snd_soc_read(codec,
+ WCD934X_CDC_RX1_RX_PATH_CTL) & 0x10)))
+ snd_soc_update_bits(codec,
+ WCD9XXX_A_ANA_RX_SUPPLIES, 0x02, 0x02);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec,
+ WCD9XXX_A_ANA_RX_SUPPLIES, 0x02, 0x00);
+ break;
+ }
+ }
+}
+
static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -1396,6 +1417,8 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
+ 0x06, (0x03 << 1));
set_bit(HPH_PA_DELAY, &tavil->status_mask);
break;
case SND_SOC_DAPM_POST_PMU:
@@ -1410,6 +1433,9 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
/* Remove mute */
snd_soc_update_bits(codec, WCD934X_CDC_RX2_RX_PATH_CTL,
0x10, 0x00);
+ /* Enable GM3 boost */
+ snd_soc_update_bits(codec, WCD934X_HPH_CNP_WG_CTL,
+ 0x80, 0x80);
/* Enable AutoChop timer at the end of power up */
snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
0x02, 0x02);
@@ -1427,6 +1453,7 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, WCD934X_CDC_DSD1_CFG2,
0x04, 0x00);
}
+ tavil_codec_override(codec, tavil->hph_mode, event);
break;
case SND_SOC_DAPM_PRE_PMD:
/* Enable DSD Mute before PA disable */
@@ -1436,6 +1463,9 @@ static int tavil_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
0x04, 0x04);
break;
case SND_SOC_DAPM_POST_PMD:
+ tavil_codec_override(codec, tavil->hph_mode, event);
+ snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
+ 0x06, 0x0);
/* 5ms sleep is required after PA disable */
usleep_range(5000, 5100);
break;
@@ -1456,6 +1486,8 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
+ 0x06, (0x03 << 1));
set_bit(HPH_PA_DELAY, &tavil->status_mask);
break;
case SND_SOC_DAPM_POST_PMU:
@@ -1470,6 +1502,12 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
/* Remove Mute on primary path */
snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CTL,
0x10, 0x00);
+ /* Enable GM3 boost */
+ snd_soc_update_bits(codec, WCD934X_HPH_CNP_WG_CTL,
+ 0x80, 0x80);
+ /* Enable AutoChop timer at the end of power up */
+ snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ 0x02, 0x02);
/* Remove mix path mute if it is enabled */
if ((snd_soc_read(codec, WCD934X_CDC_RX1_RX_PATH_MIX_CTL)) &
0x10)
@@ -1484,6 +1522,7 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec, WCD934X_CDC_DSD0_CFG2,
0x04, 0x00);
}
+ tavil_codec_override(codec, tavil->hph_mode, event);
break;
case SND_SOC_DAPM_PRE_PMD:
/* Enable DSD Mute before PA disable */
@@ -1493,6 +1532,9 @@ static int tavil_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
0x04, 0x04);
break;
case SND_SOC_DAPM_POST_PMD:
+ tavil_codec_override(codec, tavil->hph_mode, event);
+ snd_soc_update_bits(codec, WCD934X_HPH_REFBUFF_LP_CTL,
+ 0x06, 0x0);
/* 5ms sleep is required after PA disable */
usleep_range(5000, 5100);
break;
@@ -1602,9 +1644,17 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
__func__, hph_mode);
return -EINVAL;
}
+ if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
+ /* Ripple freq control enable */
+ snd_soc_update_bits(codec,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ 0x01, 0x01);
/* Disable AutoChop timer during power up */
snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
- 0x02, 0x00);
+ 0x02, 0x00);
+ /* Set RDAC gain */
+ snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
+ 0xF0, 0x40);
if (dsd_conf &&
(snd_soc_read(codec, WCD934X_CDC_DSD1_PATH_CTL) & 0x01))
@@ -1613,8 +1663,7 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
wcd_clsh_fsm(codec, &tavil->clsh_d,
WCD_CLSH_EVENT_PRE_DAC,
WCD_CLSH_STATE_HPHR,
- ((hph_mode == CLS_H_LOHIFI) ?
- CLS_H_HIFI : hph_mode));
+ hph_mode);
break;
case SND_SOC_DAPM_POST_PMD:
/* 1000us required as per HW requirement */
@@ -1622,8 +1671,15 @@ static int tavil_codec_hphr_dac_event(struct snd_soc_dapm_widget *w,
wcd_clsh_fsm(codec, &tavil->clsh_d,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_HPHR,
- ((hph_mode == CLS_H_LOHIFI) ?
- CLS_H_HIFI : hph_mode));
+ hph_mode);
+ if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
+ /* Ripple freq control disable */
+ snd_soc_update_bits(codec,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ 0x01, 0x0);
+ /* Re-set RDAC gain */
+ snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
+ 0xF0, 0x0);
break;
default:
break;
@@ -1657,6 +1713,17 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
__func__, hph_mode);
return -EINVAL;
}
+ if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
+ /* Ripple freq control enable */
+ snd_soc_update_bits(codec,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ 0x01, 0x01);
+ /* Disable AutoChop timer during power up */
+ snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_HPH_TIMER1,
+ 0x02, 0x00);
+ /* Set RDAC gain */
+ snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
+ 0xF0, 0x40);
if (dsd_conf &&
(snd_soc_read(codec, WCD934X_CDC_DSD0_PATH_CTL) & 0x01))
hph_mode = CLS_H_HIFI;
@@ -1664,8 +1731,7 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
wcd_clsh_fsm(codec, &tavil->clsh_d,
WCD_CLSH_EVENT_PRE_DAC,
WCD_CLSH_STATE_HPHL,
- ((hph_mode == CLS_H_LOHIFI) ?
- CLS_H_HIFI : hph_mode));
+ hph_mode);
break;
case SND_SOC_DAPM_POST_PMD:
/* 1000us required as per HW requirement */
@@ -1673,8 +1739,15 @@ static int tavil_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
wcd_clsh_fsm(codec, &tavil->clsh_d,
WCD_CLSH_EVENT_POST_PA,
WCD_CLSH_STATE_HPHL,
- ((hph_mode == CLS_H_LOHIFI) ?
- CLS_H_HIFI : hph_mode));
+ hph_mode);
+ if ((hph_mode != CLS_H_LP) && (hph_mode != CLS_H_ULP))
+ /* Ripple freq control disable */
+ snd_soc_update_bits(codec,
+ WCD934X_SIDO_NEW_VOUT_D_FREQ2,
+ 0x01, 0x0);
+ /* Re-set RDAC gain */
+ snd_soc_update_bits(codec, WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL,
+ 0xF0, 0x0);
break;
default:
break;
@@ -2207,6 +2280,46 @@ static int tavil_enable_native_supply(struct snd_soc_dapm_widget *w,
return 0;
}
+static void tavil_codec_hphdelay_lutbypass(struct snd_soc_codec *codec,
+ u16 interp_idx, int event)
+{
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+ u8 hph_dly_mask;
+ u16 hph_lut_bypass_reg = 0;
+ u16 hph_comp_ctrl7 = 0;
+
+
+ switch (interp_idx) {
+ case INTERP_HPHL:
+ hph_dly_mask = 1;
+ hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHL_COMP_LUT;
+ hph_comp_ctrl7 = WCD934X_CDC_COMPANDER1_CTL7;
+ break;
+ case INTERP_HPHR:
+ hph_dly_mask = 2;
+ hph_lut_bypass_reg = WCD934X_CDC_TOP_HPHR_COMP_LUT;
+ hph_comp_ctrl7 = WCD934X_CDC_COMPANDER2_CTL7;
+ break;
+ default:
+ break;
+ }
+
+ if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_ON(event)) {
+ snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
+ hph_dly_mask, 0x0);
+ snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x80);
+ if (tavil->hph_mode == CLS_H_ULP)
+ snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x20);
+ }
+
+ if (hph_lut_bypass_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_update_bits(codec, WCD934X_CDC_CLSH_TEST0,
+ hph_dly_mask, hph_dly_mask);
+ snd_soc_update_bits(codec, hph_lut_bypass_reg, 0x80, 0x00);
+ snd_soc_update_bits(codec, hph_comp_ctrl7, 0x20, 0x0);
+ }
+}
+
static void tavil_codec_hd2_control(struct snd_soc_codec *codec,
u16 interp_idx, int event)
{
@@ -2225,14 +2338,12 @@ static void tavil_codec_hd2_control(struct snd_soc_codec *codec,
}
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_scale_reg, 0x3C, 0x14);
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);
}
}
@@ -2267,7 +2378,9 @@ static int tavil_config_compander(struct snd_soc_codec *codec, int interp_n,
}
if (SND_SOC_DAPM_EVENT_OFF(event)) {
+ snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
+ snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
@@ -2306,6 +2419,8 @@ int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec,
/* Clk enable */
snd_soc_update_bits(codec, main_reg, 0x20, 0x20);
tavil_codec_hd2_control(codec, interp_idx, event);
+ tavil_codec_hphdelay_lutbypass(codec, interp_idx,
+ event);
tavil_config_compander(codec, interp_idx, event);
}
tavil->main_clk_users[interp_idx]++;
@@ -2316,6 +2431,8 @@ int tavil_codec_enable_interp_clk(struct snd_soc_codec *codec,
if (tavil->main_clk_users[interp_idx] <= 0) {
tavil->main_clk_users[interp_idx] = 0;
tavil_config_compander(codec, interp_idx, event);
+ tavil_codec_hphdelay_lutbypass(codec, interp_idx,
+ event);
tavil_codec_hd2_control(codec, interp_idx, event);
/* Clk Disable */
snd_soc_update_bits(codec, main_reg, 0x20, 0x00);
@@ -3919,6 +4036,47 @@ static int tavil_ear_pa_gain_put(struct snd_kcontrol *kcontrol,
return 0;
}
+
+static int tavil_rx_hph_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = tavil->hph_mode;
+ return 0;
+}
+
+static int tavil_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
+ u32 mode_val;
+
+ mode_val = ucontrol->value.enumerated.item[0];
+
+ dev_dbg(codec->dev, "%s: mode: %d\n", __func__, mode_val);
+
+ if (mode_val == 0) {
+ dev_warn(codec->dev, "%s:Invalid HPH Mode, default to Cls-H LOHiFi\n",
+ __func__);
+ mode_val = CLS_H_LOHIFI;
+ }
+ tavil->hph_mode = mode_val;
+ return 0;
+}
+
+
+static const char * const rx_hph_mode_mux_text[] = {
+ "CLS_H_INVALID", "CLS_H_HIFI", "CLS_H_LP", "CLS_AB", "CLS_H_LOHIFI",
+ "CLS_H_ULP", "CLS_AB_HIFI",
+};
+
+static const struct soc_enum rx_hph_mode_mux_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
+ rx_hph_mode_mux_text);
+
/* Cutoff frequency for high pass filter */
static const char * const cf_text[] = {
"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
@@ -4095,6 +4253,9 @@ static const struct snd_kcontrol_new tavil_snd_controls[] = {
SOC_ENUM("RX INT8_1 HPF cut off", cf_int8_1_enum),
SOC_ENUM("RX INT8_2 HPF cut off", cf_int8_2_enum),
+ SOC_ENUM_EXT("RX HPH Mode", rx_hph_mode_mux_enum,
+ tavil_rx_hph_mode_get, tavil_rx_hph_mode_put),
+
SOC_SINGLE_EXT("IIR0 Enable Band1", IIR0, BAND1, 1, 0,
tavil_iir_enable_audio_mixer_get,
tavil_iir_enable_audio_mixer_put),
@@ -6327,7 +6488,6 @@ static const struct tavil_reg_mask_val tavil_codec_reg_defaults[] = {
{WCD934X_BIAS_VBG_FINE_ADJ, 0xFF, 0x75},
{WCD934X_CODEC_CPR_SVS_CX_VDD, 0xFF, 0x7C}, /* value in svs mode */
{WCD934X_CODEC_CPR_SVS2_CX_VDD, 0xFF, 0x58}, /* value in svs2 mode */
- {WCD934X_SIDO_NEW_VOUT_D_FREQ2, 0x01, 0x01},
{WCD934X_CDC_RX0_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_RX1_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
{WCD934X_CDC_RX2_RX_PATH_DSMDEM_CTL, 0x01, 0x01},
@@ -6831,8 +6991,8 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
}
/* Class-H Init */
wcd_clsh_init(&tavil->clsh_d);
- /* Default HPH Mode to Class-H HiFi */
- tavil->hph_mode = CLS_H_HIFI;
+ /* Default HPH Mode to Class-H Low HiFi */
+ tavil->hph_mode = CLS_H_LOHIFI;
tavil->fw_data = devm_kzalloc(codec->dev, sizeof(*(tavil->fw_data)),
GFP_KERNEL);
diff --git a/sound/soc/codecs/wcd9xxx-common-v2.c b/sound/soc/codecs/wcd9xxx-common-v2.c
index 116c4e27c981..63872bbf540c 100644
--- a/sound/soc/codecs/wcd9xxx-common-v2.c
+++ b/sound/soc/codecs/wcd9xxx-common-v2.c
@@ -237,10 +237,16 @@ static const char *mode_to_str(int mode)
return "CLS_H_NORMAL";
case CLS_H_HIFI:
return "CLS_H_HIFI";
+ case CLS_H_LOHIFI:
+ return "CLS_H_LOHIFI";
case CLS_H_LP:
return "CLS_H_LP";
+ case CLS_H_ULP:
+ return "CLS_H_ULP";
case CLS_AB:
return "CLS_AB";
+ case CLS_AB_HIFI:
+ return "CLS_AB_HIFI";
default:
return "CLS_H_INVALID";
};
@@ -332,7 +338,8 @@ static inline void wcd_clsh_set_int_mode(struct wcd_clsh_cdc_data *clsh_d,
static inline void wcd_clsh_set_buck_mode(struct snd_soc_codec *codec,
int mode)
{
- if (mode == CLS_H_HIFI)
+ if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
+ mode == CLS_AB_HIFI || mode == CLS_AB)
snd_soc_update_bits(codec, WCD9XXX_A_ANA_RX_SUPPLIES,
0x08, 0x08); /* set to HIFI */
else
@@ -343,7 +350,8 @@ static inline void wcd_clsh_set_buck_mode(struct snd_soc_codec *codec,
static inline void wcd_clsh_set_flyback_mode(struct snd_soc_codec *codec,
int mode)
{
- if (mode == CLS_H_HIFI)
+ if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
+ mode == CLS_AB_HIFI || mode == CLS_AB)
snd_soc_update_bits(codec, WCD9XXX_A_ANA_RX_SUPPLIES,
0x04, 0x04); /* set to HIFI */
else
@@ -351,6 +359,55 @@ static inline void wcd_clsh_set_flyback_mode(struct snd_soc_codec *codec,
0x04, 0x00); /* set to Default */
}
+static inline void wcd_clsh_gm3_boost_disable(struct snd_soc_codec *codec,
+ int mode)
+{
+ struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
+
+ if (!IS_CODEC_TYPE(wcd9xxx, WCD934X))
+ return;
+
+ if (mode == CLS_H_HIFI || mode == CLS_H_LOHIFI ||
+ mode == CLS_AB_HIFI || mode == CLS_AB) {
+ snd_soc_update_bits(codec, WCD9XXX_HPH_CNP_WG_CTL,
+ 0x80, 0x0); /* disable GM3 Boost */
+ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEG_CTRL_4,
+ 0xF0, 0x80);
+ } else {
+ snd_soc_update_bits(codec, WCD9XXX_HPH_CNP_WG_CTL,
+ 0x80, 0x80); /* set to Default */
+ snd_soc_update_bits(codec, WCD9XXX_FLYBACK_VNEG_CTRL_4,
+ 0xF0, 0x70);
+ }
+}
+
+
+static inline void wcd_clsh_force_iq_ctl(struct snd_soc_codec *codec,
+ int mode)
+{
+ struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent);
+
+ if (!IS_CODEC_TYPE(wcd9xxx, WCD934X))
+ return;
+
+ if (mode == CLS_H_LOHIFI || mode == CLS_AB) {
+ snd_soc_update_bits(codec, WCD9XXX_HPH_NEW_INT_PA_MISC2,
+ 0x20, 0x20);
+ snd_soc_update_bits(codec, WCD9XXX_RX_BIAS_HPH_LOWPOWER,
+ 0xF0, 0xC0);
+ snd_soc_update_bits(codec, WCD9XXX_HPH_PA_CTL1,
+ 0x0E, 0x02);
+ } else {
+
+ snd_soc_update_bits(codec, WCD9XXX_HPH_NEW_INT_PA_MISC2,
+ 0x20, 0x0);
+ snd_soc_update_bits(codec, WCD9XXX_RX_BIAS_HPH_LOWPOWER,
+ 0xF0, 0x80);
+ snd_soc_update_bits(codec, WCD9XXX_HPH_PA_CTL1,
+ 0x0E, 0x06);
+ }
+}
+
static void wcd_clsh_buck_ctrl(struct snd_soc_codec *codec,
struct wcd_clsh_cdc_data *clsh_d,
int mode,
@@ -470,11 +527,26 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec,
gain = DAC_GAIN_0DB;
ipeak = DELTA_I_50MA;
break;
+ case CLS_AB_HIFI:
+ val = 0x08;
+ break;
case CLS_H_HIFI:
val = 0x08;
gain = DAC_GAIN_M0P2DB;
ipeak = DELTA_I_50MA;
break;
+ case CLS_H_LOHIFI:
+ val = 0x00;
+ if ((IS_CODEC_TYPE(wcd9xxx, WCD9335)) ||
+ (IS_CODEC_TYPE(wcd9xxx, WCD9326))) {
+ val = 0x08;
+ gain = DAC_GAIN_M0P2DB;
+ ipeak = DELTA_I_50MA;
+ }
+ break;
+ case CLS_H_ULP:
+ val = 0x0C;
+ break;
case CLS_H_LP:
val = 0x04;
ipeak = DELTA_I_30MA;
@@ -483,6 +555,14 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec,
return;
};
+ /*
+ * For tavil set mode to Lower_power for
+ * CLS_H_LOHIFI and CLS_AB
+ */
+ if ((IS_CODEC_TYPE(wcd9xxx, WCD934X)) &&
+ (mode == CLS_H_LOHIFI || mode == CLS_AB))
+ val = 0x04;
+
snd_soc_update_bits(codec, WCD9XXX_A_ANA_HPH, 0x0C, val);
if (TASHA_IS_2_0(wcd9xxx)) {
snd_soc_update_bits(codec, WCD9XXX_CLASSH_CTRL_VCL_2,
@@ -538,7 +618,7 @@ static void wcd_clsh_state_lo(struct snd_soc_codec *codec,
dev_dbg(codec->dev, "%s: mode: %s, %s\n", __func__, mode_to_str(mode),
is_enable ? "enable" : "disable");
- if (mode != CLS_AB) {
+ if (mode != CLS_AB && mode != CLS_AB_HIFI) {
dev_err(codec->dev, "%s: LO cannot be in this mode: %d\n",
__func__, mode);
return;
@@ -586,7 +666,8 @@ static void wcd_clsh_state_hph_ear(struct snd_soc_codec *codec,
WCD_CLSH_STATE_HPHR);
else
return;
- if (hph_mode != CLS_AB && !is_native_44_1_active(codec))
+ if (hph_mode != CLS_AB && hph_mode != CLS_AB_HIFI
+ && !is_native_44_1_active(codec))
snd_soc_update_bits(codec,
WCD9XXX_A_CDC_RX0_RX_PATH_CFG0,
0x40, 0x40);
@@ -795,6 +876,7 @@ static void wcd_clsh_state_hph_lo(struct snd_soc_codec *codec,
hph_mode);
if ((hph_mode == CLS_AB) ||
+ (hph_mode == CLS_AB_HIFI) ||
(hph_mode == CLS_NONE))
goto end;
@@ -843,7 +925,7 @@ static void wcd_clsh_state_hph_st(struct snd_soc_codec *codec,
dev_dbg(codec->dev, "%s: mode: %s, %s\n", __func__, mode_to_str(mode),
is_enable ? "enable" : "disable");
- if (mode == CLS_AB)
+ if (mode == CLS_AB || mode == CLS_AB_HIFI)
return;
if (is_enable) {
@@ -881,7 +963,7 @@ static void wcd_clsh_state_hph_r(struct snd_soc_codec *codec,
}
if (is_enable) {
- if (mode != CLS_AB) {
+ if (mode != CLS_AB && mode != CLS_AB_HIFI) {
wcd_enable_clsh_block(codec, clsh_d, true);
/*
* These K1 values depend on the Headphone Impedance
@@ -897,6 +979,8 @@ static void wcd_clsh_state_hph_r(struct snd_soc_codec *codec,
}
wcd_clsh_set_buck_regulator_mode(codec, mode);
wcd_clsh_set_flyback_mode(codec, mode);
+ wcd_clsh_gm3_boost_disable(codec, mode);
+ wcd_clsh_force_iq_ctl(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);
@@ -906,7 +990,7 @@ static void wcd_clsh_state_hph_r(struct snd_soc_codec *codec,
} else {
wcd_clsh_set_hph_mode(codec, CLS_H_NORMAL);
- if (mode != CLS_AB) {
+ if (mode != CLS_AB && mode != CLS_AB_HIFI) {
snd_soc_update_bits(codec,
WCD9XXX_A_CDC_RX2_RX_PATH_CFG0,
0x40, 0x00);
@@ -915,6 +999,8 @@ static void wcd_clsh_state_hph_r(struct snd_soc_codec *codec,
/* buck and flyback set to default mode and disable */
wcd_clsh_buck_ctrl(codec, clsh_d, CLS_H_NORMAL, false);
wcd_clsh_flyback_ctrl(codec, clsh_d, CLS_H_NORMAL, false);
+ wcd_clsh_force_iq_ctl(codec, CLS_H_NORMAL);
+ wcd_clsh_gm3_boost_disable(codec, CLS_H_NORMAL);
wcd_clsh_set_flyback_mode(codec, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(codec, CLS_H_NORMAL);
wcd_clsh_set_buck_regulator_mode(codec, CLS_H_NORMAL);
@@ -935,7 +1021,7 @@ static void wcd_clsh_state_hph_l(struct snd_soc_codec *codec,
}
if (is_enable) {
- if (mode != CLS_AB) {
+ if (mode != CLS_AB && mode != CLS_AB_HIFI) {
wcd_enable_clsh_block(codec, clsh_d, true);
/*
* These K1 values depend on the Headphone Impedance
@@ -951,6 +1037,8 @@ static void wcd_clsh_state_hph_l(struct snd_soc_codec *codec,
}
wcd_clsh_set_buck_regulator_mode(codec, mode);
wcd_clsh_set_flyback_mode(codec, mode);
+ wcd_clsh_gm3_boost_disable(codec, mode);
+ wcd_clsh_force_iq_ctl(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);
@@ -960,7 +1048,7 @@ static void wcd_clsh_state_hph_l(struct snd_soc_codec *codec,
} else {
wcd_clsh_set_hph_mode(codec, CLS_H_NORMAL);
- if (mode != CLS_AB) {
+ if (mode != CLS_AB && mode != CLS_AB_HIFI) {
snd_soc_update_bits(codec,
WCD9XXX_A_CDC_RX1_RX_PATH_CFG0,
0x40, 0x00);
@@ -969,6 +1057,8 @@ static void wcd_clsh_state_hph_l(struct snd_soc_codec *codec,
/* set buck and flyback to Default Mode */
wcd_clsh_buck_ctrl(codec, clsh_d, CLS_H_NORMAL, false);
wcd_clsh_flyback_ctrl(codec, clsh_d, CLS_H_NORMAL, false);
+ wcd_clsh_force_iq_ctl(codec, CLS_H_NORMAL);
+ wcd_clsh_gm3_boost_disable(codec, CLS_H_NORMAL);
wcd_clsh_set_flyback_mode(codec, CLS_H_NORMAL);
wcd_clsh_set_buck_mode(codec, CLS_H_NORMAL);
wcd_clsh_set_buck_regulator_mode(codec, CLS_H_NORMAL);
diff --git a/sound/soc/codecs/wcd9xxx-common-v2.h b/sound/soc/codecs/wcd9xxx-common-v2.h
index d3c52e73a7da..ee7e587b3f24 100644
--- a/sound/soc/codecs/wcd9xxx-common-v2.h
+++ b/sound/soc/codecs/wcd9xxx-common-v2.h
@@ -61,8 +61,10 @@ enum {
CLS_H_NORMAL = 0, /* Class-H Default */
CLS_H_HIFI, /* Class-H HiFi */
CLS_H_LP, /* Class-H Low Power */
- CLS_AB, /* Class-AB */
+ CLS_AB, /* Class-AB Low HIFI*/
CLS_H_LOHIFI, /* LoHIFI */
+ CLS_H_ULP, /* Ultra Low power */
+ CLS_AB_HIFI, /* Class-AB */
CLS_NONE, /* None of the above modes */
};