diff options
author | Linux Build Service Account <lnxbuild@quicinc.com> | 2017-07-04 01:21:02 -0700 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-07-04 01:21:02 -0700 |
commit | 48b492e8e181c1ab4d915889ad6def337b77f78c (patch) | |
tree | 398cc96461433df95c2f867f67924a099871c318 | |
parent | 8775c10a30afd1d84b5665831699dbf6bb0ad08a (diff) | |
parent | e0085c2429cfabc3db0de2d23e783c45d9d2aa14 (diff) |
Merge "ASoC: wcd-mbhc: Disconnect ANC from RX chain during plug removal"
-rw-r--r-- | sound/soc/codecs/wcd-mbhc-v2.c | 35 | ||||
-rw-r--r-- | sound/soc/codecs/wcd-mbhc-v2.h | 9 | ||||
-rw-r--r-- | sound/soc/codecs/wcd9335.c | 28 | ||||
-rw-r--r-- | sound/soc/codecs/wcd934x/wcd934x-mbhc.c | 28 |
4 files changed, 100 insertions, 0 deletions
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 44141ae5668e..3d131ed463c9 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -361,6 +361,7 @@ out_micb_en: /* Disable micbias, pullup & enable cs */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); mutex_unlock(&mbhc->hphl_pa_lock); + clear_bit(WCD_MBHC_ANC0_OFF_ACK, &mbhc->hph_anc_state); break; case WCD_EVENT_PRE_HPHR_PA_OFF: mutex_lock(&mbhc->hphr_pa_lock); @@ -378,6 +379,7 @@ out_micb_en: /* Disable micbias, pullup & enable cs */ wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS); mutex_unlock(&mbhc->hphr_pa_lock); + clear_bit(WCD_MBHC_ANC1_OFF_ACK, &mbhc->hph_anc_state); break; case WCD_EVENT_PRE_HPHL_PA_ON: set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); @@ -495,6 +497,25 @@ static void wcd_mbhc_clr_and_turnon_hph_padac(struct wcd_mbhc *mbhc) __func__); usleep_range(wg_time * 1000, wg_time * 1000 + 50); } + + if (test_and_clear_bit(WCD_MBHC_ANC0_OFF_ACK, + &mbhc->hph_anc_state)) { + usleep_range(20000, 20100); + pr_debug("%s: HPHL ANC clear flag and enable ANC_EN\n", + __func__); + if (mbhc->mbhc_cb->update_anc_state) + mbhc->mbhc_cb->update_anc_state(mbhc->codec, true, 0); + } + + if (test_and_clear_bit(WCD_MBHC_ANC1_OFF_ACK, + &mbhc->hph_anc_state)) { + usleep_range(20000, 20100); + pr_debug("%s: HPHR ANC clear flag and enable ANC_EN\n", + __func__); + if (mbhc->mbhc_cb->update_anc_state) + mbhc->mbhc_cb->update_anc_state(mbhc->codec, true, 1); + } + } static bool wcd_mbhc_is_hph_pa_on(struct wcd_mbhc *mbhc) @@ -526,6 +547,20 @@ static void wcd_mbhc_set_and_turnoff_hph_padac(struct wcd_mbhc *mbhc) } WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 0); usleep_range(wg_time * 1000, wg_time * 1000 + 50); + + + if (mbhc->mbhc_cb->is_anc_on && mbhc->mbhc_cb->is_anc_on(mbhc)) { + usleep_range(20000, 20100); + pr_debug("%s ANC is on, setting ANC_OFF_ACK\n", __func__); + set_bit(WCD_MBHC_ANC0_OFF_ACK, &mbhc->hph_anc_state); + set_bit(WCD_MBHC_ANC1_OFF_ACK, &mbhc->hph_anc_state); + if (mbhc->mbhc_cb->update_anc_state) { + mbhc->mbhc_cb->update_anc_state(mbhc->codec, false, 0); + mbhc->mbhc_cb->update_anc_state(mbhc->codec, false, 1); + } else { + pr_debug("%s ANC is off\n", __func__); + } + } } int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, diff --git a/sound/soc/codecs/wcd-mbhc-v2.h b/sound/soc/codecs/wcd-mbhc-v2.h index 32d9801468f9..09b9307ad61d 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.h +++ b/sound/soc/codecs/wcd-mbhc-v2.h @@ -89,6 +89,11 @@ enum pa_dac_ack_flags { WCD_MBHC_HPHR_PA_OFF_ACK, }; +enum anc_ack_flags { + WCD_MBHC_ANC0_OFF_ACK = 0, + WCD_MBHC_ANC1_OFF_ACK, +}; + enum wcd_mbhc_btn_det_mem { WCD_MBHC_BTN_DET_V_BTN_LOW, WCD_MBHC_BTN_DET_V_BTN_HIGH @@ -386,6 +391,9 @@ struct wcd_mbhc_cb { void (*hph_pull_down_ctrl)(struct snd_soc_codec *, bool); void (*mbhc_moisture_config)(struct wcd_mbhc *); bool (*hph_register_recovery)(struct wcd_mbhc *); + void (*update_anc_state)(struct snd_soc_codec *codec, + bool enable, int anc_num); + bool (*is_anc_on)(struct wcd_mbhc *mbhc); }; struct wcd_mbhc { @@ -426,6 +434,7 @@ struct wcd_mbhc { /* track PA/DAC state to sync with userspace */ unsigned long hph_pa_dac_state; + unsigned long hph_anc_state; unsigned long event_state; unsigned long jiffies_atreport; diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index c4f9e84a1f68..2ab787f57b31 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -2219,6 +2219,32 @@ static void tasha_mbhc_moisture_config(struct wcd_mbhc *mbhc) tasha_mbhc_hph_l_pull_up_control(codec, mbhc->moist_iref); } +static void tasha_update_anc_state(struct snd_soc_codec *codec, bool enable, + int anc_num) +{ + if (enable) + snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CFG0 + + (20 * anc_num), 0x10, 0x10); + else + snd_soc_update_bits(codec, WCD9335_CDC_RX1_RX_PATH_CFG0 + + (20 * anc_num), 0x10, 0x00); +} + +static bool tasha_is_anc_on(struct wcd_mbhc *mbhc) +{ + bool anc_on = false; + u16 ancl, ancr; + + ancl = + (snd_soc_read(mbhc->codec, WCD9335_CDC_RX1_RX_PATH_CFG0)) & 0x10; + ancr = + (snd_soc_read(mbhc->codec, WCD9335_CDC_RX2_RX_PATH_CFG0)) & 0x10; + + anc_on = !!(ancl | ancr); + + return anc_on; +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = tasha_mbhc_request_irq, .irq_control = tasha_mbhc_irq_control, @@ -2241,6 +2267,8 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_gnd_det_ctrl = tasha_mbhc_gnd_det_ctrl, .hph_pull_down_ctrl = tasha_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = tasha_mbhc_moisture_config, + .update_anc_state = tasha_update_anc_state, + .is_anc_on = tasha_is_anc_on, }; static int tasha_get_anc_slot(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/codecs/wcd934x/wcd934x-mbhc.c b/sound/soc/codecs/wcd934x/wcd934x-mbhc.c index 3d032f0a7115..075ab7b2ff2b 100644 --- a/sound/soc/codecs/wcd934x/wcd934x-mbhc.c +++ b/sound/soc/codecs/wcd934x/wcd934x-mbhc.c @@ -812,6 +812,32 @@ static bool tavil_hph_register_recovery(struct wcd_mbhc *mbhc) return wcd934x_mbhc->is_hph_recover; } +static void tavil_update_anc_state(struct snd_soc_codec *codec, bool enable, + int anc_num) +{ + if (enable) + snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CFG0 + + (20 * anc_num), 0x10, 0x10); + else + snd_soc_update_bits(codec, WCD934X_CDC_RX1_RX_PATH_CFG0 + + (20 * anc_num), 0x10, 0x00); +} + +static bool tavil_is_anc_on(struct wcd_mbhc *mbhc) +{ + bool anc_on = false; + u16 ancl, ancr; + + ancl = + (snd_soc_read(mbhc->codec, WCD934X_CDC_RX1_RX_PATH_CFG0)) & 0x10; + ancr = + (snd_soc_read(mbhc->codec, WCD934X_CDC_RX2_RX_PATH_CFG0)) & 0x10; + + anc_on = !!(ancl | ancr); + + return anc_on; +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = tavil_mbhc_request_irq, .irq_control = tavil_mbhc_irq_control, @@ -835,6 +861,8 @@ static const struct wcd_mbhc_cb mbhc_cb = { .hph_pull_down_ctrl = tavil_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = tavil_mbhc_moisture_config, .hph_register_recovery = tavil_hph_register_recovery, + .update_anc_state = tavil_update_anc_state, + .is_anc_on = tavil_is_anc_on, }; static struct regulator *tavil_codec_find_ondemand_regulator( |