ASoC: wcd934x: add support for HPH modes
Headphones support classH and classAB. Add support for hifi, lowhifi, low power and ultra low power modes for classH. Support hifi and lowhifi power modes for classAB. CRs-Fixed: 1066331 Change-Id: I846f9704a5bf800583682f8dc2ec385a0ec64c61 Signed-off-by: Yeleswarapu Nagaradhesh <nagaradh@codeaurora.org>
This commit is contained in:
parent
971aeb6add
commit
ea965ee6e8
4 changed files with 283 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue