diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index 78bef6a8ed09..2f8e954b5a23 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -37,6 +37,10 @@ #define ROULEUR_MBHC_ZDET_CONST (86 * 16384) #define ROULEUR_MBHC_MOISTURE_RREF R_24_KOHM +/* Cross connection thresholds in mV */ +#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200 +#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 200 + static struct wcd_mbhc_register wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = { WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN", @@ -320,11 +324,11 @@ static void rouleur_mbhc_micb_ramp_control(struct snd_soc_component *component, 0x1C, 0x0C); snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MICB2_RAMP, - 0xA0, 0x80); + 0x80, 0x80); } else { snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MICB2_RAMP, - 0xA0, 0x00); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_MICB2_RAMP, 0x1C, 0x00); @@ -820,15 +824,6 @@ static void rouleur_mbhc_bcs_enable(struct wcd_mbhc *mbhc, rouleur_disable_bcs_before_slow_insert(mbhc->component, true); } -static void rouleur_mbhc_hs_vref_max_update(struct wcd_mbhc *mbhc) -{ - struct snd_soc_component *component = mbhc->component; - - /* Update the HS Vref max voltage to 1.7V */ - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_2, - 0x03, 0x03); -} - static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb) { u8 vout_ctl = 0; @@ -843,19 +838,40 @@ static void rouleur_mbhc_get_micbias_val(struct wcd_mbhc *mbhc, int *mb) pr_debug("%s: vout_ctl: %d, micbias: %d\n", __func__, vout_ctl, *mb); } -static void rouleur_mbhc_micb_pullup_control( - struct snd_soc_component *component, - bool pullup_enable) +static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc, + bool az_enable) { - if (pullup_enable) - rouleur_micbias_control(component, MIC_BIAS_2, - MICB_PULLUP_ENABLE, false); + if (az_enable) + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_MBHC_MCLK, 0x08, 0x08); else - rouleur_micbias_control(component, MIC_BIAS_2, - MICB_PULLUP_DISABLE, false); + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_MBHC_MCLK, 0x08, 0x00); } +static void rouleur_mbhc_surge_control(struct wcd_mbhc *mbhc, + bool surge_enable) +{ + if (surge_enable) + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0); + else + snd_soc_component_update_bits(mbhc->component, + ROULEUR_ANA_SURGE_EN, 0xC0, 0x00); + +} + +static void rouleur_mbhc_update_cross_conn_thr(struct wcd_mbhc *mbhc) +{ + mbhc->hphl_cross_conn_thr = ROULEUR_HPHL_CROSS_CONN_THRESHOLD; + mbhc->hphr_cross_conn_thr = ROULEUR_HPHR_CROSS_CONN_THRESHOLD; + + pr_debug("%s: Cross connection threshold for hphl: %d, hphr: %d\n", + __func__, mbhc->hphl_cross_conn_thr, + mbhc->hphr_cross_conn_thr); +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = rouleur_mbhc_request_irq, .irq_control = rouleur_mbhc_irq_control, @@ -880,9 +896,10 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_get_moisture_status = rouleur_mbhc_get_moisture_status, .mbhc_moisture_detect_en = rouleur_mbhc_moisture_detect_en, .bcs_enable = rouleur_mbhc_bcs_enable, - .hs_vref_max_update = rouleur_mbhc_hs_vref_max_update, .get_micbias_val = rouleur_mbhc_get_micbias_val, - .mbhc_micb_pullup_control = rouleur_mbhc_micb_pullup_control, + .mbhc_comp_autozero_control = rouleur_mbhc_comp_autozero_control, + .mbhc_surge_ctl = rouleur_mbhc_surge_control, + .update_cross_conn_thr = rouleur_mbhc_update_cross_conn_thr, }; static int rouleur_get_hph_type(struct snd_kcontrol *kcontrol, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index cdb1de2c6996..e1ecdba83f3b 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -107,6 +107,9 @@ static int rouleur_handle_post_irq(void *data) static int rouleur_init_reg(struct snd_soc_component *component) { + /* Disable HPH OCP */ + snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, + 0x03, 0x00); /* Enable surge protection */ snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0); @@ -354,7 +357,7 @@ static int rouleur_rx_clk_enable(struct snd_soc_component *component) usleep_range(5000, 5100); rouleur_global_mbias_enable(component); snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x11); + ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11); snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80); snd_soc_component_update_bits(component, @@ -382,14 +385,14 @@ static int rouleur_rx_clk_disable(struct snd_soc_component *component) snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x00); snd_soc_component_update_bits(component, - ROULEUR_ANA_HPHPA_FSM_CLK, 0x11, 0x00); + ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x00); snd_soc_component_update_bits(component, ROULEUR_ANA_NCP_EN, 0x01, 0x00); - rouleur_global_mbias_disable(component); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x20, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x10, 0x00); + rouleur_global_mbias_disable(component); } mutex_unlock(&rouleur->rx_clk_lock); @@ -478,8 +481,15 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, - 0x01, 0x00); + ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, + 0x01, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, + 0x04, 0x00); + if (rouleur->comp1_enable) + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_COMP_CTL_0, + 0x02, 0x00); break; } @@ -544,6 +554,13 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x02, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, + 0x08, 0x00); + if (rouleur->comp2_enable) + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_COMP_CTL_0, + 0x01, 0x00); break; } @@ -567,18 +584,21 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX0_CTL, 0x7C, 0x7C); - snd_soc_component_update_bits(component, - ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, - 0x01, 0x01); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, + 0x01, 0x01); break; case SND_SOC_DAPM_POST_PMD: snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_CLK_CTL, 0x01, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, + 0x04, 0x00); break; }; diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c index 47c7ebf62fd8..89f0f7ed19ae 100644 --- a/asoc/codecs/wcd-mbhc-adc.c +++ b/asoc/codecs/wcd-mbhc-adc.c @@ -80,8 +80,22 @@ static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc) WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0); /* Set the MUX selection to IN2P */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P); + + /* + * Current source mode requires Auto zeroing to be enabled + * automatically. If HW doesn't do it, SW has to take care of this + * for button interrupts to work fine and to avoid + * fake electrical removal interrupts by enabling autozero before FSM + * enable and disable it after FSM enable + */ + if (mbhc->mbhc_cb->mbhc_comp_autozero_control) + mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc, + true); /* Enable MBHC FSM */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1); + if (mbhc->mbhc_cb->mbhc_comp_autozero_control) + mbhc->mbhc_cb->mbhc_comp_autozero_control(mbhc, + false); /* Enable ADC_ENABLE bit */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1); @@ -294,6 +308,10 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00); + /* Disable surge detection before ADC measurement */ + if (mbhc->mbhc_cb->mbhc_surge_ctl) + mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, false); + /* Read and set ADC to single measurement */ WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode); /* Read ADC Enable bit to restore after adc measurement */ @@ -317,7 +335,12 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) goto done; } - if (hphl_adc_res > 100 || hphr_adc_res > 100) { + /* Update cross connection threshold voltages if needed */ + if (mbhc->mbhc_cb->update_cross_conn_thr) + mbhc->mbhc_cb->update_cross_conn_thr(mbhc); + + if (hphl_adc_res > mbhc->hphl_cross_conn_thr || + hphr_adc_res > mbhc->hphr_cross_conn_thr) { plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP; pr_debug("%s: Cross connection identified\n", __func__); } else { @@ -339,6 +362,10 @@ done: /* Restore FSM state */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en); + /* Restore surge detection */ + if (mbhc->mbhc_cb->mbhc_surge_ctl) + mbhc->mbhc_cb->mbhc_surge_ctl(mbhc, true); + /* Restore electrical detection */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 5b07fcca233f..17ce0ef7903e 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -80,17 +80,13 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc) struct snd_soc_component *component = mbhc->component; u32 reg_val; - if (mbhc->mbhc_cb->hs_vref_max_update) { - mbhc->mbhc_cb->hs_vref_max_update(mbhc); - } else { - plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR( - mbhc->mbhc_cfg->calibration); - reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); + plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR( + mbhc->mbhc_cfg->calibration); + reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); - dev_dbg(component->dev, "%s: reg_val = %x\n", - __func__, reg_val); - WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); - } + dev_dbg(component->dev, "%s: reg_val = %x\n", + __func__, reg_val); + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val); } static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias) @@ -999,14 +995,6 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) mbhc->mbhc_cb->enable_mb_source(mbhc, true); mbhc->btn_press_intr = false; mbhc->is_btn_press = false; - /* - * When current source mode doesn't work properly - * use mic bias pull up mode for button interrupts - * to function properly - */ - if (mbhc->mbhc_cb->mbhc_micb_pullup_control) - mbhc->mbhc_cb->mbhc_micb_pullup_control(component, - true); if (mbhc->mbhc_fn) mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc); } else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE) @@ -1084,10 +1072,6 @@ static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc) false); } - if (mbhc->mbhc_cb->mbhc_micb_pullup_control) - mbhc->mbhc_cb->mbhc_micb_pullup_control(component, - false); - } else if (!detection_type) { /* Disable external voltage source to micbias if present */ if (mbhc->mbhc_cb->enable_mb_source) @@ -1856,6 +1840,8 @@ int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_component *component, mbhc->hph_type = WCD_MBHC_HPH_NONE; mbhc->wcd_mbhc_regs = wcd_mbhc_regs; mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD; + mbhc->hphl_cross_conn_thr = HPHL_CROSS_CONN_THRESHOLD; + mbhc->hphr_cross_conn_thr = HPHR_CROSS_CONN_THRESHOLD; if (mbhc->intr_ids == NULL) { pr_err("%s: Interrupt mapping not provided\n", __func__); diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index 392e59418d68..1c351f8012e6 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -145,6 +145,8 @@ do { \ #define FW_READ_ATTEMPTS 15 #define FW_READ_TIMEOUT 4000000 #define FAKE_REM_RETRY_ATTEMPTS 3 +#define HPHL_CROSS_CONN_THRESHOLD 100 +#define HPHR_CROSS_CONN_THRESHOLD 100 #define WCD_MBHC_BTN_PRESS_COMPL_TIMEOUT_MS 50 #define ANC_DETECT_RETRY_CNT 7 @@ -456,12 +458,14 @@ struct wcd_mbhc_register { }; struct wcd_mbhc_cb { - void (*mbhc_micb_pullup_control) - (struct snd_soc_component *component, bool enable); + void (*update_cross_conn_thr) + (struct wcd_mbhc *mbhc); + void (*mbhc_surge_ctl) + (struct wcd_mbhc *mbhc, bool surge_en); + void (*mbhc_comp_autozero_control) + (struct wcd_mbhc *mbhc, bool az_enable); void (*get_micbias_val) (struct wcd_mbhc *mbhc, int *mb); - void (*hs_vref_max_update) - (struct wcd_mbhc *mbhc); void (*bcs_enable) (struct wcd_mbhc *mbhc, bool bcs_enable); int (*enable_mb_source)(struct wcd_mbhc *mbhc, bool turn_on); @@ -557,6 +561,8 @@ struct wcd_mbhc { u32 moist_vref; u32 moist_iref; u32 moist_rref; + u32 hphl_cross_conn_thr; + u32 hphr_cross_conn_thr; u8 micbias1_cap_mode; /* track ext cap setting */ u8 micbias2_cap_mode; /* track ext cap setting */ bool hs_detect_work_stop;