Loading asoc/codecs/wcd-mbhc-v2.c +50 −1 Original line number Diff line number Diff line Loading @@ -850,6 +850,36 @@ void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc, } 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; Loading Loading @@ -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); Loading Loading @@ -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) Loading @@ -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__); Loading Loading @@ -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); /* Loading asoc/codecs/wcd-mbhc-v2.h +4 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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 { Loading asoc/codecs/wcd937x/wcd937x-mbhc.c +60 −0 Original line number Diff line number Diff line Loading @@ -721,6 +721,63 @@ static void wcd937x_mbhc_moisture_config(struct wcd_mbhc *mbhc) 0x0C, mbhc->moist_rref << 2); } static void wcd937x_mbhc_moisture_detect_en(struct wcd_mbhc *mbhc, bool enable) { struct snd_soc_codec *codec = mbhc->codec; if (enable) snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, mbhc->moist_rref << 2); else snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, R_OFF << 2); } static bool wcd937x_mbhc_get_moisture_status(struct wcd_mbhc *mbhc) { struct snd_soc_codec *codec = mbhc->codec; bool ret = false; if ((mbhc->moist_rref == R_OFF) || (mbhc->mbhc_cfg->enable_usbc_analog)) { snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, R_OFF << 2); goto done; } /* Do not enable moisture detection if jack type is NC */ if (!mbhc->hphl_swh) { dev_dbg(codec->dev, "%s: disable moisture detection for NC\n", __func__); snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, R_OFF << 2); goto done; } /* If moisture_en is already enabled, then skip to plug type * detection. */ if ((snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2) & 0x0C)) goto done; wcd937x_mbhc_moisture_detect_en(mbhc, true); /* Read moisture comparator status */ ret = ((snd_soc_read(codec, WCD937X_MBHC_NEW_FSM_STATUS) & 0x20) ? 0 : 1); done: return ret; } static void wcd937x_mbhc_moisture_polling_ctrl(struct wcd_mbhc *mbhc, bool enable) { snd_soc_update_bits(codec, WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 0x04, (enable << 2)); } static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = wcd937x_mbhc_request_irq, .irq_control = wcd937x_mbhc_irq_control, Loading @@ -742,6 +799,9 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_gnd_det_ctrl = wcd937x_mbhc_gnd_det_ctrl, .hph_pull_down_ctrl = wcd937x_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = wcd937x_mbhc_moisture_config, .mbhc_get_moisture_status = wcd937x_mbhc_get_moisture_status, .mbhc_moisture_polling_ctrl = wcd937x_mbhc_moisture_polling_ctrl, .mbhc_moisture_detect_en = wcd937x_mbhc_moisture_detect_en, }; static int wcd937x_get_hph_type(struct snd_kcontrol *kcontrol, Loading Loading
asoc/codecs/wcd-mbhc-v2.c +50 −1 Original line number Diff line number Diff line Loading @@ -850,6 +850,36 @@ void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc, } 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; Loading Loading @@ -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); Loading Loading @@ -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) Loading @@ -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__); Loading Loading @@ -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); /* Loading
asoc/codecs/wcd-mbhc-v2.h +4 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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 { Loading
asoc/codecs/wcd937x/wcd937x-mbhc.c +60 −0 Original line number Diff line number Diff line Loading @@ -721,6 +721,63 @@ static void wcd937x_mbhc_moisture_config(struct wcd_mbhc *mbhc) 0x0C, mbhc->moist_rref << 2); } static void wcd937x_mbhc_moisture_detect_en(struct wcd_mbhc *mbhc, bool enable) { struct snd_soc_codec *codec = mbhc->codec; if (enable) snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, mbhc->moist_rref << 2); else snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, R_OFF << 2); } static bool wcd937x_mbhc_get_moisture_status(struct wcd_mbhc *mbhc) { struct snd_soc_codec *codec = mbhc->codec; bool ret = false; if ((mbhc->moist_rref == R_OFF) || (mbhc->mbhc_cfg->enable_usbc_analog)) { snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, R_OFF << 2); goto done; } /* Do not enable moisture detection if jack type is NC */ if (!mbhc->hphl_swh) { dev_dbg(codec->dev, "%s: disable moisture detection for NC\n", __func__); snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2, 0x0C, R_OFF << 2); goto done; } /* If moisture_en is already enabled, then skip to plug type * detection. */ if ((snd_soc_update_bits(codec, WCD937X_MBHC_NEW_CTL_2) & 0x0C)) goto done; wcd937x_mbhc_moisture_detect_en(mbhc, true); /* Read moisture comparator status */ ret = ((snd_soc_read(codec, WCD937X_MBHC_NEW_FSM_STATUS) & 0x20) ? 0 : 1); done: return ret; } static void wcd937x_mbhc_moisture_polling_ctrl(struct wcd_mbhc *mbhc, bool enable) { snd_soc_update_bits(codec, WCD937X_MBHC_NEW_INT_MOISTURE_DET_POLLING_CTRL, 0x04, (enable << 2)); } static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = wcd937x_mbhc_request_irq, .irq_control = wcd937x_mbhc_irq_control, Loading @@ -742,6 +799,9 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_gnd_det_ctrl = wcd937x_mbhc_gnd_det_ctrl, .hph_pull_down_ctrl = wcd937x_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = wcd937x_mbhc_moisture_config, .mbhc_get_moisture_status = wcd937x_mbhc_get_moisture_status, .mbhc_moisture_polling_ctrl = wcd937x_mbhc_moisture_polling_ctrl, .mbhc_moisture_detect_en = wcd937x_mbhc_moisture_detect_en, }; static int wcd937x_get_hph_type(struct snd_kcontrol *kcontrol, Loading