summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Oglesby <soglesby@codeaurora.org>2016-03-23 14:03:47 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-07-12 12:53:51 -0700
commitacffc8ef067f26323b33bf30e53edbed6ad97615 (patch)
tree4b88db7a66d49bfa85a3455b64ae6407d4036b4a
parent400520a6e2f06cc7c45e386e769a85d4aded565b (diff)
ASoC: wcd9335: Remove pop on bring-up of noise cancelling headset
In order to reduce an audible pop on bring-up of ANC headset path, keep AMICs supplying ANC noise data muted and ANC block in reset until after headset amps are enabled. Also synchronize the PA enables. CRs-fixed: 990915 Change-Id: Ifb6b7849ec60fa1b5e3fd56c1d45631af1c18fd8 Signed-off-by: Stephen Oglesby <soglesby@codeaurora.org>
-rwxr-xr-xsound/soc/codecs/wcd9335.c121
1 files changed, 112 insertions, 9 deletions
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index f496559f0632..d8787ed249db 100755
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -349,6 +349,12 @@ enum {
CPE_NOMINAL,
HPH_PA_DELAY,
SB_CLK_GEAR,
+ ANC_MIC_AMIC1,
+ ANC_MIC_AMIC2,
+ ANC_MIC_AMIC3,
+ ANC_MIC_AMIC4,
+ ANC_MIC_AMIC5,
+ ANC_MIC_AMIC6,
};
enum {
@@ -576,6 +582,7 @@ static struct snd_soc_dai_driver tasha_dai[];
static int wcd9335_get_micb_vout_ctl_val(u32 micb_mv);
static int tasha_config_compander(struct snd_soc_codec *, int, int);
+static void tasha_codec_set_tx_hold(struct snd_soc_codec *, u16, bool);
/* Hold instance to soundwire platform device */
struct tasha_swr_ctrl_data {
@@ -3775,7 +3782,7 @@ static int tasha_codec_enable_anc(struct snd_soc_dapm_widget *w,
WCD9335_CDC_ANC0_IIR_COEFF_2_CTL);
anc_writes_size = anc_cal_size / 2;
snd_soc_update_bits(codec,
- WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x38, 0x38);
+ WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x39, 0x39);
} else if (!strcmp(w->name, "RX INT2 DAC") ||
!strcmp(w->name, "RX INT4 DAC")) {
tasha_realign_anc_coeff(codec,
@@ -3783,7 +3790,7 @@ static int tasha_codec_enable_anc(struct snd_soc_dapm_widget *w,
WCD9335_CDC_ANC1_IIR_COEFF_2_CTL);
i = anc_cal_size / 2;
snd_soc_update_bits(codec,
- WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x38, 0x38);
+ WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x39, 0x39);
}
for (; i < anc_writes_size; i++) {
@@ -3793,16 +3800,23 @@ static int tasha_codec_enable_anc(struct snd_soc_dapm_widget *w,
if (!strcmp(w->name, "RX INT1 DAC") ||
!strcmp(w->name, "RX INT3 DAC")) {
snd_soc_update_bits(codec,
- WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x38, 0x00);
+ WCD9335_CDC_ANC0_CLK_RESET_CTL, 0x08, 0x08);
} else if (!strcmp(w->name, "RX INT2 DAC") ||
!strcmp(w->name, "RX INT4 DAC")) {
snd_soc_update_bits(codec,
- WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x38, 0x00);
+ WCD9335_CDC_ANC1_CLK_RESET_CTL, 0x08, 0x08);
}
if (!hwdep_cal)
release_firmware(fw);
break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* Remove ANC Rx from reset */
+ snd_soc_update_bits(codec, WCD9335_CDC_ANC0_CLK_RESET_CTL,
+ 0x08, 0x00);
+ snd_soc_update_bits(codec, WCD9335_CDC_ANC1_CLK_RESET_CTL,
+ 0x08, 0x00);
+ break;
case SND_SOC_DAPM_POST_PMD:
if (!strcmp(w->name, "ANC HPHL PA") ||
!strcmp(w->name, "ANC EAR PA") ||
@@ -3842,6 +3856,22 @@ err:
return ret;
}
+static void tasha_codec_clear_anc_tx_hold(struct tasha_priv *tasha)
+{
+ if (test_and_clear_bit(ANC_MIC_AMIC1, &tasha->status_mask))
+ tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC1, false);
+ if (test_and_clear_bit(ANC_MIC_AMIC2, &tasha->status_mask))
+ tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC2, false);
+ if (test_and_clear_bit(ANC_MIC_AMIC3, &tasha->status_mask))
+ tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC3, false);
+ if (test_and_clear_bit(ANC_MIC_AMIC4, &tasha->status_mask))
+ tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC4, false);
+ if (test_and_clear_bit(ANC_MIC_AMIC5, &tasha->status_mask))
+ tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC5, false);
+ if (test_and_clear_bit(ANC_MIC_AMIC6, &tasha->status_mask))
+ tasha_codec_set_tx_hold(tasha->codec, WCD9335_ANA_AMIC6, false);
+}
+
static void tasha_codec_hph_post_pa_config(struct tasha_priv *tasha,
int mode, int event)
{
@@ -3860,6 +3890,13 @@ static void tasha_codec_hph_post_pa_config(struct tasha_priv *tasha,
scale_val = 0x1;
break;
}
+ if (tasha->anc_func) {
+ /* Clear Tx FE HOLD if both PAs are enabled */
+ if ((snd_soc_read(tasha->codec, WCD9335_ANA_HPH) &
+ 0xC0) == 0xC0) {
+ tasha_codec_clear_anc_tx_hold(tasha);
+ }
+ }
break;
case SND_SOC_DAPM_PRE_PMD:
scale_val = 0x6;
@@ -3926,9 +3963,20 @@ static int tasha_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ if ((!(strcmp(w->name, "ANC HPHR PA"))) &&
+ (test_bit(HPH_PA_DELAY, &tasha->status_mask))) {
+ snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0xC0, 0xC0);
+ }
set_bit(HPH_PA_DELAY, &tasha->status_mask);
break;
case SND_SOC_DAPM_POST_PMU:
+ if ((snd_soc_read(codec, WCD9335_ANA_HPH) & 0xC0) != 0xC0)
+ /*
+ * If PA_EN is not set (potentially in ANC case) then
+ * do nothing for POST_PMU and let left channel handle
+ * everything.
+ */
+ break;
/*
* 7ms sleep is required after PA is enabled as per
* HW requirement
@@ -3946,13 +3994,31 @@ static int tasha_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec,
WCD9335_CDC_RX2_RX_PATH_MIX_CTL,
0x10, 0x00);
+
+ if (!(strcmp(w->name, "ANC HPHR PA"))) {
+ /* Do everything needed for left channel */
+ snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CTL,
+ 0x10, 0x00);
+ /* Remove mix path mute if it is enabled */
+ if ((snd_soc_read(codec,
+ WCD9335_CDC_RX1_RX_PATH_MIX_CTL)) &
+ 0x10)
+ snd_soc_update_bits(codec,
+ WCD9335_CDC_RX1_RX_PATH_MIX_CTL,
+ 0x10, 0x00);
+ /* Remove ANC Rx from reset */
+ ret = tasha_codec_enable_anc(w, kcontrol, event);
+ }
tasha_codec_override(codec, hph_mode, event);
break;
+
case SND_SOC_DAPM_PRE_PMD:
blocking_notifier_call_chain(&tasha->notifier,
WCD_EVENT_PRE_HPHR_PA_OFF,
&tasha->mbhc);
tasha_codec_hph_post_pa_config(tasha, hph_mode, event);
+ if (!(strcmp(w->name, "ANC HPHR PA")))
+ snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0x40, 0x00);
break;
case SND_SOC_DAPM_POST_PMD:
/* 5ms sleep is required after PA is disabled as per
@@ -3988,9 +4054,20 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ if ((!(strcmp(w->name, "ANC HPHL PA"))) &&
+ (test_bit(HPH_PA_DELAY, &tasha->status_mask))) {
+ snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0xC0, 0xC0);
+ }
set_bit(HPH_PA_DELAY, &tasha->status_mask);
break;
case SND_SOC_DAPM_POST_PMU:
+ if ((snd_soc_read(codec, WCD9335_ANA_HPH) & 0xC0) != 0xC0)
+ /*
+ * If PA_EN is not set (potentially in ANC case) then
+ * do nothing for POST_PMU and let right channel handle
+ * everything.
+ */
+ break;
/*
* 7ms sleep is required after PA is enabled as per
* HW requirement
@@ -4009,6 +4086,22 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec,
WCD9335_CDC_RX1_RX_PATH_MIX_CTL,
0x10, 0x00);
+
+ if (!(strcmp(w->name, "ANC HPHL PA"))) {
+ /* Do everything needed for right channel */
+ snd_soc_update_bits(codec, WCD9335_CDC_RX2_RX_PATH_CTL,
+ 0x10, 0x00);
+ /* Remove mix path mute if it is enabled */
+ if ((snd_soc_read(codec,
+ WCD9335_CDC_RX2_RX_PATH_MIX_CTL)) &
+ 0x10)
+ snd_soc_update_bits(codec,
+ WCD9335_CDC_RX2_RX_PATH_MIX_CTL,
+ 0x10, 0x00);
+
+ /* Remove ANC Rx from reset */
+ ret = tasha_codec_enable_anc(w, kcontrol, event);
+ }
tasha_codec_override(codec, hph_mode, event);
break;
case SND_SOC_DAPM_PRE_PMD:
@@ -4016,6 +4109,8 @@ static int tasha_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
WCD_EVENT_PRE_HPHL_PA_OFF,
&tasha->mbhc);
tasha_codec_hph_post_pa_config(tasha, hph_mode, event);
+ if (!(strcmp(w->name, "ANC HPHL PA")))
+ snd_soc_update_bits(codec, WCD9335_ANA_HPH, 0x80, 0x00);
break;
case SND_SOC_DAPM_POST_PMD:
/* 5ms sleep is required after PA is disabled as per
@@ -4083,6 +4178,9 @@ static int tasha_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
snd_soc_update_bits(codec,
lineout_mix_vol_reg,
0x10, 0x00);
+ if (!(strcmp(w->name, "ANC LINEOUT1 PA")) ||
+ !(strcmp(w->name, "ANC LINEOUT2 PA")))
+ ret = tasha_codec_enable_anc(w, kcontrol, event);
tasha_codec_override(codec, CLS_AB, event);
break;
case SND_SOC_DAPM_POST_PMD:
@@ -5394,8 +5492,8 @@ static int tasha_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w,
{
int adc_mux_n = w->shift;
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
int amic_n;
- u16 amic_reg;
dev_dbg(codec->dev, "%s: event: %d\n", __func__, event);
@@ -5403,8 +5501,13 @@ static int tasha_codec_tx_adc_cfg(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMU:
amic_n = tasha_codec_find_amic_input(codec, adc_mux_n);
if (amic_n) {
- amic_reg = WCD9335_ANA_AMIC1 + amic_n - 1;
- tasha_codec_set_tx_hold(codec, amic_reg, false);
+ /*
+ * Prevent ANC Rx pop by leaving Tx FE in HOLD
+ * state until PA is up. Track AMIC being used
+ * so we can release the HOLD later.
+ */
+ set_bit(ANC_MIC_AMIC1 + amic_n - 1,
+ &tasha->status_mask);
}
break;
default:
@@ -10512,11 +10615,11 @@ static const struct snd_soc_dapm_widget tasha_dapm_widgets[] = {
tasha_codec_enable_ear_pa,
SND_SOC_DAPM_POST_PMU |
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,
+ SND_SOC_DAPM_PGA_E("ANC HPHL PA", SND_SOC_NOPM, 0, 0, NULL, 0,
tasha_codec_enable_hphl_pa,
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,
+ SND_SOC_DAPM_PGA_E("ANC HPHR PA", SND_SOC_NOPM, 0, 0, NULL, 0,
tasha_codec_enable_hphr_pa,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),