Loading include/linux/mfd/wcd9xxx/wcd9xxx_registers.h +1 −0 Original line number Diff line number Diff line Loading @@ -340,4 +340,5 @@ #define WCD9XXX_CDC_RX1_RX_PATH_CTL (0xB55) #define WCD9XXX_CDC_RX2_RX_PATH_CTL (0xB69) #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL (0xD41) #define WCD9XXX_CLASSH_CTRL_CCL_1 (0x69C) #endif sound/soc/codecs/wcd9335.c +183 −18 Original line number Diff line number Diff line Loading @@ -335,6 +335,7 @@ enum { AIF4_SWITCH_VALUE, AUDIO_NOMINAL, CPE_NOMINAL, HPH_PA_DELAY, }; enum { Loading Loading @@ -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, Loading Loading @@ -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 */ Loading @@ -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 Loading Loading @@ -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 */ Loading @@ -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 Loading Loading @@ -3726,32 +3799,70 @@ 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)) { snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x02); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x08); snd_soc_update_bits(codec, WCD9335_RX_BIAS_HPH_PA, 0x0F, 0x06); snd_soc_update_bits(codec, WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2, 0xF0, 0x40); 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); snd_soc_write(codec, WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2, 0x8A); snd_soc_update_bits(codec, WCD9335_RX_BIAS_HPH_PA, 0x0F, 0x0A); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x06); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x00); } } 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)) { snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x0C); tasha_codec_hph_mode_gain_opt(codec, 0x10); 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_CTL2, 0x04, 0x04); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x20, 0x20); Loading @@ -3766,14 +3877,30 @@ static void tasha_codec_hph_lp_config(struct snd_soc_codec *codec, } if (SND_SOC_DAPM_EVENT_OFF(event)) { snd_soc_update_bits(codec, WCD9335_HPH_R_EN, 0xC0, 0x80); snd_soc_update_bits(codec, WCD9335_HPH_L_EN, 0xC0, 0x80); snd_soc_write(codec, WCD9335_RX_BIAS_HPH_RDAC_LDO, 0x88); snd_soc_write(codec, WCD9335_HPH_RDAC_LDO_CTL, 0x33); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x20, 0x00); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x04, 0x00); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x00); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x06); snd_soc_update_bits(codec, WCD9335_HPH_CNP_WG_CTL, 0x07, 0x02); snd_soc_update_bits(codec, WCD9335_HPH_R_EN, 0xC0, 0x80); snd_soc_update_bits(codec, WCD9335_HPH_L_EN, 0xC0, 0x80); } } 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); } } Loading @@ -3787,10 +3914,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; } } Loading Loading @@ -4127,6 +4257,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) Loading @@ -4143,6 +4305,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); } Loading @@ -4159,6 +4322,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; }; Loading Loading @@ -9749,11 +9913,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, Loading Loading @@ -10805,7 +10969,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}, Loading @@ -10814,6 +10977,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[] = { Loading sound/soc/codecs/wcd9xxx-common-v2.c +23 −7 Original line number Diff line number Diff line Loading @@ -40,6 +40,15 @@ enum { VREF_FILT_R_100KOHM, }; enum { DELTA_I_0MA, DELTA_I_10MA, DELTA_I_20MA, DELTA_I_30MA, DELTA_I_40MA, DELTA_I_50MA, }; static void (*clsh_state_fp[NUM_CLSH_STATES_V2])(struct snd_soc_codec *, struct wcd_clsh_cdc_data *, u8 req_state, bool en, int mode); Loading Loading @@ -284,6 +293,7 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec, u8 val; u8 gain; u8 res_val = VREF_FILT_R_0OHM; u8 ipeak = DELTA_I_50MA; struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent); Loading @@ -292,18 +302,21 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec, res_val = VREF_FILT_R_50KOHM; val = 0x00; gain = DAC_GAIN_0DB; ipeak = DELTA_I_50MA; break; case CLS_AB: val = 0x00; gain = DAC_GAIN_0DB; ipeak = DELTA_I_50MA; break; case CLS_H_HIFI: val = 0x08; gain = DAC_GAIN_M0P2DB; ipeak = DELTA_I_50MA; break; case CLS_H_LP: val = 0x04; gain = DAC_GAIN_0P2DB; ipeak = DELTA_I_30MA; break; }; Loading @@ -311,8 +324,11 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec, if (TASHA_IS_2_0(wcd9xxx->version)) { snd_soc_update_bits(codec, WCD9XXX_CLASSH_CTRL_VCL_2, 0x30, (res_val << 4)); if (mode != CLS_H_LP) snd_soc_update_bits(codec, WCD9XXX_HPH_REFBUFF_UHQA_CTL, 0x07, gain); snd_soc_update_bits(codec, WCD9XXX_CLASSH_CTRL_CCL_1, 0xF0, (ipeak << 4)); } } Loading Loading @@ -660,13 +676,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); Loading Loading @@ -714,13 +730,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); Loading Loading
include/linux/mfd/wcd9xxx/wcd9xxx_registers.h +1 −0 Original line number Diff line number Diff line Loading @@ -340,4 +340,5 @@ #define WCD9XXX_CDC_RX1_RX_PATH_CTL (0xB55) #define WCD9XXX_CDC_RX2_RX_PATH_CTL (0xB69) #define WCD9XXX_CDC_CLK_RST_CTRL_MCLK_CONTROL (0xD41) #define WCD9XXX_CLASSH_CTRL_CCL_1 (0x69C) #endif
sound/soc/codecs/wcd9335.c +183 −18 Original line number Diff line number Diff line Loading @@ -335,6 +335,7 @@ enum { AIF4_SWITCH_VALUE, AUDIO_NOMINAL, CPE_NOMINAL, HPH_PA_DELAY, }; enum { Loading Loading @@ -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, Loading Loading @@ -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 */ Loading @@ -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 Loading Loading @@ -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 */ Loading @@ -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 Loading Loading @@ -3726,32 +3799,70 @@ 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)) { snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x02); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x08); snd_soc_update_bits(codec, WCD9335_RX_BIAS_HPH_PA, 0x0F, 0x06); snd_soc_update_bits(codec, WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2, 0xF0, 0x40); 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); snd_soc_write(codec, WCD9335_RX_BIAS_HPH_RDACBUFF_CNP2, 0x8A); snd_soc_update_bits(codec, WCD9335_RX_BIAS_HPH_PA, 0x0F, 0x0A); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x06); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x00); } } 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)) { snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x0C); tasha_codec_hph_mode_gain_opt(codec, 0x10); 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_CTL2, 0x04, 0x04); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x20, 0x20); Loading @@ -3766,14 +3877,30 @@ static void tasha_codec_hph_lp_config(struct snd_soc_codec *codec, } if (SND_SOC_DAPM_EVENT_OFF(event)) { snd_soc_update_bits(codec, WCD9335_HPH_R_EN, 0xC0, 0x80); snd_soc_update_bits(codec, WCD9335_HPH_L_EN, 0xC0, 0x80); snd_soc_write(codec, WCD9335_RX_BIAS_HPH_RDAC_LDO, 0x88); snd_soc_write(codec, WCD9335_HPH_RDAC_LDO_CTL, 0x33); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x20, 0x00); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x04, 0x00); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL2, 0x08, 0x00); snd_soc_update_bits(codec, WCD9335_HPH_PA_CTL1, 0x0E, 0x06); snd_soc_update_bits(codec, WCD9335_HPH_CNP_WG_CTL, 0x07, 0x02); snd_soc_update_bits(codec, WCD9335_HPH_R_EN, 0xC0, 0x80); snd_soc_update_bits(codec, WCD9335_HPH_L_EN, 0xC0, 0x80); } } 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); } } Loading @@ -3787,10 +3914,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; } } Loading Loading @@ -4127,6 +4257,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) Loading @@ -4143,6 +4305,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); } Loading @@ -4159,6 +4322,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; }; Loading Loading @@ -9749,11 +9913,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, Loading Loading @@ -10805,7 +10969,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}, Loading @@ -10814,6 +10977,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[] = { Loading
sound/soc/codecs/wcd9xxx-common-v2.c +23 −7 Original line number Diff line number Diff line Loading @@ -40,6 +40,15 @@ enum { VREF_FILT_R_100KOHM, }; enum { DELTA_I_0MA, DELTA_I_10MA, DELTA_I_20MA, DELTA_I_30MA, DELTA_I_40MA, DELTA_I_50MA, }; static void (*clsh_state_fp[NUM_CLSH_STATES_V2])(struct snd_soc_codec *, struct wcd_clsh_cdc_data *, u8 req_state, bool en, int mode); Loading Loading @@ -284,6 +293,7 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec, u8 val; u8 gain; u8 res_val = VREF_FILT_R_0OHM; u8 ipeak = DELTA_I_50MA; struct wcd9xxx *wcd9xxx = dev_get_drvdata(codec->dev->parent); Loading @@ -292,18 +302,21 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec, res_val = VREF_FILT_R_50KOHM; val = 0x00; gain = DAC_GAIN_0DB; ipeak = DELTA_I_50MA; break; case CLS_AB: val = 0x00; gain = DAC_GAIN_0DB; ipeak = DELTA_I_50MA; break; case CLS_H_HIFI: val = 0x08; gain = DAC_GAIN_M0P2DB; ipeak = DELTA_I_50MA; break; case CLS_H_LP: val = 0x04; gain = DAC_GAIN_0P2DB; ipeak = DELTA_I_30MA; break; }; Loading @@ -311,8 +324,11 @@ static void wcd_clsh_set_hph_mode(struct snd_soc_codec *codec, if (TASHA_IS_2_0(wcd9xxx->version)) { snd_soc_update_bits(codec, WCD9XXX_CLASSH_CTRL_VCL_2, 0x30, (res_val << 4)); if (mode != CLS_H_LP) snd_soc_update_bits(codec, WCD9XXX_HPH_REFBUFF_UHQA_CTL, 0x07, gain); snd_soc_update_bits(codec, WCD9XXX_CLASSH_CTRL_CCL_1, 0xF0, (ipeak << 4)); } } Loading Loading @@ -660,13 +676,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); Loading Loading @@ -714,13 +730,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); Loading