From a45a56e82401695b4110b08985ab94dc88eb5eee Mon Sep 17 00:00:00 2001 From: Sudheer Papothi Date: Fri, 3 Aug 2018 05:30:24 +0530 Subject: [PATCH] ASoC: wcd-mbhc: Avoid headset jack corrosion due to moisture Detect moisture in the headset jack and avoid headset jack corrosion due to presence of moisture over prolonged duration. Change-Id: I0227e516feb58c96ddf6a8fbc32423bfe7733ca6 Signed-off-by: Sudheer Papothi --- asoc/codecs/wcd-mbhc-v2.c | 51 ++++++++++++++++++++++++++++++++++++++- asoc/codecs/wcd-mbhc-v2.h | 4 +++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 6f3b19ba6c..363b90b1d5 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -850,6 +850,36 @@ exit: } EXPORT_SYMBOL(wcd_mbhc_find_plug_and_report); +static bool wcd_mbhc_moisture_detect(struct wcd_mbhc *mbhc, bool detection_type) +{ + bool ret = false; + + if (!mbhc->mbhc_cfg->moisture_en || + !mbhc->mbhc_cfg->moisture_duty_cycle_en) + return ret; + + if (!mbhc->mbhc_cb->mbhc_get_moisture_status || + !mbhc->mbhc_cb->mbhc_moisture_polling_ctrl || + !mbhc->mbhc_cb->mbhc_moisture_detect_en) + return ret; + + if (mbhc->mbhc_cb->mbhc_get_moisture_status(mbhc)) { + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 0); + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_DET_EN, 0); + mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc, true); + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE, + detection_type); + ret = true; + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1); + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_DET_EN, 1); + } else { + mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc, false); + mbhc->mbhc_cb->mbhc_moisture_detect_en(mbhc, false); + } + + return ret; +} + static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) { bool detection_type = 0; @@ -885,6 +915,13 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) if ((mbhc->current_plug == MBHC_PLUG_TYPE_NONE) && detection_type) { + + /* If moisture is present, then enable polling, disable + * moisture detection and wait for interrupt + */ + if (wcd_mbhc_moisture_detect(mbhc, detection_type)) + goto done; + /* Make sure MASTER_BIAS_CTL is enabled */ mbhc->mbhc_cb->mbhc_bias(codec, true); @@ -970,6 +1007,16 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) mbhc->mbhc_cb->clk_setup(mbhc->codec, false); } + if (mbhc->mbhc_cfg->moisture_en && + mbhc->mbhc_cfg->moisture_duty_cycle_en) { + if (mbhc->mbhc_cb->mbhc_moisture_polling_ctrl) + mbhc->mbhc_cb->mbhc_moisture_polling_ctrl(mbhc, + false); + if (mbhc->mbhc_cb->mbhc_moisture_detect_en) + mbhc->mbhc_cb->mbhc_moisture_detect_en(mbhc, + false); + } + } else if (!detection_type) { /* Disable external voltage source to micbias if present */ if (mbhc->mbhc_cb->enable_mb_source) @@ -980,6 +1027,7 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) mbhc->extn_cable_hph_rem = false; } +done: mbhc->in_swch_irq_handler = false; WCD_MBHC_RSC_UNLOCK(mbhc); pr_debug("%s: leave\n", __func__); @@ -1294,7 +1342,8 @@ static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc) else WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3); - if (mbhc->mbhc_cfg->moisture_en && mbhc->mbhc_cb->mbhc_moisture_config) + if (mbhc->mbhc_cfg->moisture_en && mbhc->mbhc_cb->mbhc_moisture_config + && !mbhc->mbhc_cfg->moisture_duty_cycle_en) mbhc->mbhc_cb->mbhc_moisture_config(mbhc); /* diff --git a/asoc/codecs/wcd-mbhc-v2.h b/asoc/codecs/wcd-mbhc-v2.h index 0473574104..4d00c2bb98 100644 --- a/asoc/codecs/wcd-mbhc-v2.h +++ b/asoc/codecs/wcd-mbhc-v2.h @@ -437,6 +437,7 @@ struct wcd_mbhc_config { int anc_micbias; bool enable_anc_mic_detect; u32 enable_usbc_analog; + bool moisture_duty_cycle_en; }; struct wcd_mbhc_intr { @@ -502,6 +503,9 @@ struct wcd_mbhc_cb { bool enable, int anc_num); bool (*is_anc_on)(struct wcd_mbhc *mbhc); void (*hph_pull_up_control_v2)(struct snd_soc_codec *, int); + bool (*mbhc_get_moisture_status)(struct wcd_mbhc *); + void (*mbhc_moisture_polling_ctrl)(struct wcd_mbhc *, bool); + void (*mbhc_moisture_detect_en)(struct wcd_mbhc *, bool); }; struct wcd_mbhc_fn {