summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhani Kumar Uppalapati <phaniu@codeaurora.org>2015-10-26 16:39:07 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:12:24 -0700
commitb7f18741022d8d0459b18c8ea990cb8d1a427642 (patch)
treef6cf6668c92ed66b5ea503a313d21905224e4c51
parent0307f3529b16d4e04fae49876755358df5d34663 (diff)
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: Phani Kumar Uppalapati <phaniu@codeaurora.org>
-rwxr-xr-xsound/soc/codecs/wcd9335.c183
-rw-r--r--sound/soc/codecs/wcd9xxx-common-v2.c8
2 files changed, 176 insertions, 15 deletions
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index a2a0105a28e7..c3ed33f00d6b 100755
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -335,6 +335,7 @@ enum {
AIF4_SWITCH_VALUE,
AUDIO_NOMINAL,
CPE_NOMINAL,
+ HPH_PA_DELAY,
};
enum {
@@ -764,6 +765,8 @@ struct tasha_priv {
struct hpf_work tx_hpf_work[TASHA_NUM_DECIMATORS];
struct tx_mute_work tx_mute_dwork[TASHA_NUM_DECIMATORS];
struct mutex codec_mutex;
+ int hph_l_gain;
+ int hph_r_gain;
};
static int tasha_codec_vote_max_bw(struct snd_soc_codec *codec,
@@ -3526,22 +3529,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 = snd_soc_dapm_to_codec(w->dapm);
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 */
@@ -3555,6 +3616,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
@@ -3582,16 +3644,26 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
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 */
@@ -3605,6 +3677,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
@@ -3734,8 +3807,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)) {
@@ -3755,7 +3863,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)) {
@@ -3785,6 +3892,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)
{
@@ -3795,10 +3918,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;
}
}
@@ -4146,6 +4272,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)
@@ -4162,6 +4320,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);
}
@@ -4178,6 +4337,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;
};
@@ -9782,11 +9942,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,
@@ -10995,7 +11155,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},
@@ -11004,6 +11163,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[] = {
diff --git a/sound/soc/codecs/wcd9xxx-common-v2.c b/sound/soc/codecs/wcd9xxx-common-v2.c
index 301cf5cf42c4..2661fab3b67f 100644
--- a/sound/soc/codecs/wcd9xxx-common-v2.c
+++ b/sound/soc/codecs/wcd9xxx-common-v2.c
@@ -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);