From c3fd6cc3055ad98bc030ac936cfba4c24397c715 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Thu, 23 Apr 2020 18:57:27 +0530 Subject: [PATCH 1/5] asoc: codecs: Fix button interrupts issue in rouleur Current source mode in rouleur does not work properly leading to issues in button interrupts and fake electrical removal interrupts. Enable pull up mode instead of current source mode to fix these issues. Modify the headset max vref voltage to 1.7 volts and micbias calculation logic. Change-Id: If3e4a2fdcf080b07fe3c363b6eb6115f101b91f4 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 1 + asoc/codecs/rouleur/rouleur-mbhc.c | 39 +++++++++++++++++++++++++++ asoc/codecs/rouleur/rouleur.c | 43 +++++++++++++++++++++++++----- asoc/codecs/wcd-mbhc-adc.c | 22 ++++++++------- asoc/codecs/wcd-mbhc-v2.c | 26 +++++++++++++++--- include/asoc/wcd-mbhc-v2.h | 6 +++++ 6 files changed, 118 insertions(+), 19 deletions(-) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index 7104685d7cd8..df8541e34041 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -82,6 +82,7 @@ struct rouleur_priv { int mbias_cnt; struct mutex rx_clk_lock; struct mutex main_bias_lock; + bool dev_up; }; struct rouleur_micbias_setting { diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index caf6d4a04fc8..78bef6a8ed09 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -820,6 +820,42 @@ 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; + + /* Read MBHC Micbias (Mic Bias2) voltage */ + WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); + + /* Formula for getting micbias from vout + * micbias = 1.6V + VOUT_CTL * 50mV + */ + *mb = 1600 + (vout_ctl * 50); + 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) +{ + if (pullup_enable) + rouleur_micbias_control(component, MIC_BIAS_2, + MICB_PULLUP_ENABLE, false); + else + rouleur_micbias_control(component, MIC_BIAS_2, + MICB_PULLUP_DISABLE, false); + +} + static const struct wcd_mbhc_cb mbhc_cb = { .request_irq = rouleur_mbhc_request_irq, .irq_control = rouleur_mbhc_irq_control, @@ -844,6 +880,9 @@ 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, }; 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 3f039c4082d8..cdb1de2c6996 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -1146,6 +1146,7 @@ int rouleur_micbias_control(struct snd_soc_component *component, int post_on_event = 0, post_dapm_off = 0; int post_dapm_on = 0; u8 pullup_mask = 0, enable_mask = 0; + int ret = 0; if ((micb_index < 0) || (micb_index > ROULEUR_MAX_MICBIAS - 1)) { dev_err(component->dev, "%s: Invalid micbias index, micb_ind:%d\n", @@ -1181,6 +1182,12 @@ int rouleur_micbias_control(struct snd_soc_component *component, switch (req) { case MICB_PULLUP_ENABLE: + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } rouleur->pullup_ref[micb_index]++; if ((rouleur->pullup_ref[micb_index] == 1) && (rouleur->micb_ref[micb_index] == 0)) @@ -1188,6 +1195,12 @@ int rouleur_micbias_control(struct snd_soc_component *component, pullup_mask, pullup_mask); break; case MICB_PULLUP_DISABLE: + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } if (rouleur->pullup_ref[micb_index] > 0) rouleur->pullup_ref[micb_index]--; if ((rouleur->pullup_ref[micb_index] == 0) && @@ -1196,11 +1209,15 @@ int rouleur_micbias_control(struct snd_soc_component *component, pullup_mask, 0x00); break; case MICB_ENABLE: + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } rouleur->micb_ref[micb_index]++; if (rouleur->micb_ref[micb_index] == 1) { rouleur_global_mbias_enable(component); - snd_soc_component_update_bits(component, micb_reg, - 0x80, 0x80); snd_soc_component_update_bits(component, micb_reg, enable_mask, enable_mask); if (post_on_event) @@ -1216,16 +1233,27 @@ int rouleur_micbias_control(struct snd_soc_component *component, case MICB_DISABLE: if (rouleur->micb_ref[micb_index] > 0) rouleur->micb_ref[micb_index]--; + if (!rouleur->dev_up) { + dev_dbg(component->dev, "%s: enable req %d wcd device down\n", + __func__, req); + ret = -ENODEV; + goto done; + } if ((rouleur->micb_ref[micb_index] == 0) && - (rouleur->pullup_ref[micb_index] == 0)) { + (rouleur->pullup_ref[micb_index] > 0)) { + snd_soc_component_update_bits(component, micb_reg, + pullup_mask, pullup_mask); + snd_soc_component_update_bits(component, micb_reg, + enable_mask, 0x00); + rouleur_global_mbias_disable(component); + } else if ((rouleur->micb_ref[micb_index] == 0) && + (rouleur->pullup_ref[micb_index] == 0)) { if (pre_off_event && rouleur->mbhc) blocking_notifier_call_chain( &rouleur->mbhc->notifier, pre_off_event, &rouleur->mbhc->wcd_mbhc); snd_soc_component_update_bits(component, micb_reg, enable_mask, 0x00); - snd_soc_component_update_bits(component, micb_reg, - 0x80, 0x00); rouleur_global_mbias_disable(component); if (post_off_event && rouleur->mbhc) blocking_notifier_call_chain( @@ -1243,8 +1271,8 @@ int rouleur_micbias_control(struct snd_soc_component *component, dev_dbg(component->dev, "%s: micb_num:%d, micb_ref: %d, pullup_ref: %d\n", __func__, micb_num, rouleur->micb_ref[micb_index], rouleur->pullup_ref[micb_index]); +done: mutex_unlock(&rouleur->micb_lock); - return 0; } EXPORT_SYMBOL(rouleur_micbias_control); @@ -1313,6 +1341,7 @@ static int rouleur_event_notify(struct notifier_block *block, 0x80, 0x00); break; case BOLERO_WCD_EVT_SSR_DOWN: + rouleur->dev_up = false; rouleur->mbhc->wcd_mbhc.deinit_in_progress = true; mbhc = &rouleur->mbhc->wcd_mbhc; rouleur_mbhc_ssr_down(rouleur->mbhc, component); @@ -1338,6 +1367,7 @@ static int rouleur_event_notify(struct notifier_block *block, rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg); } rouleur->mbhc->wcd_mbhc.deinit_in_progress = false; + rouleur->dev_up = true; break; default: dev_err(component->dev, "%s: invalid event %d\n", __func__, @@ -1969,6 +1999,7 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component) return ret; } } + rouleur->dev_up = true; done: return ret; } diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c index c57c011dfd24..47c7ebf62fd8 100644 --- a/asoc/codecs/wcd-mbhc-adc.c +++ b/asoc/codecs/wcd-mbhc-adc.c @@ -33,16 +33,20 @@ static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc) int micbias = 0; u8 vout_ctl = 0; - /* Read MBHC Micbias (Mic Bias2) voltage */ - WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); - - /* Formula for getting micbias from vout - * micbias = 1.0V + VOUT_CTL * 50mV - */ - micbias = 1000 + (vout_ctl * 50); - pr_debug("%s: vout_ctl: %d, micbias: %d\n", - __func__, vout_ctl, micbias); + if (mbhc->mbhc_cb->get_micbias_val) { + mbhc->mbhc_cb->get_micbias_val(mbhc, &micbias); + pr_debug("%s: micbias: %d\n", __func__, micbias); + } else { + /* Read MBHC Micbias (Mic Bias2) voltage */ + WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl); + /* Formula for getting micbias from vout + * micbias = 1.0V + VOUT_CTL * 50mV + */ + micbias = 1000 + (vout_ctl * 50); + pr_debug("%s: vout_ctl: %d, micbias: %d\n", + __func__, vout_ctl, micbias); + } return micbias; } diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 0da12eb653fc..5b07fcca233f 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -80,11 +80,17 @@ static void wcd_program_hs_vref(struct wcd_mbhc *mbhc) struct snd_soc_component *component = mbhc->component; u32 reg_val; - 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); + 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); - 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) @@ -993,6 +999,14 @@ 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) @@ -1070,6 +1084,10 @@ 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) diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index c7e412b34473..392e59418d68 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -456,6 +456,12 @@ struct wcd_mbhc_register { }; struct wcd_mbhc_cb { + void (*mbhc_micb_pullup_control) + (struct snd_soc_component *component, bool 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); From 313aa17ac428f67a027bc06d020a514ac7e18342 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 29 Apr 2020 20:43:53 +0530 Subject: [PATCH 2/5] asoc: codecs: Add comparator autozeroing support for rouleur When current source mode is enabled, comparator auto zeroing should be turned ON by HW. As rouleur codec HW doesn't do this automatically, add this support in SW to set the auto zero enable before FSM enable and reset to auto once FSM is enabled. Disable surge protection before ADC measurements and change HPHL and HPHR thresholds while identifying cross connection for proper accessory identification. Change-Id: Ib775de0f0bdb6c655a3c0eb4775276acfbca1e84 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/rouleur-mbhc.c | 59 +++++++++++++++++++----------- asoc/codecs/rouleur/rouleur.c | 36 ++++++++++++++---- asoc/codecs/wcd-mbhc-adc.c | 29 ++++++++++++++- asoc/codecs/wcd-mbhc-v2.c | 30 ++++----------- include/asoc/wcd-mbhc-v2.h | 14 +++++-- 5 files changed, 112 insertions(+), 56 deletions(-) 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; From 050e7403209b1add4fe51ce592f48f39b237c74f Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Sat, 28 Mar 2020 13:09:08 +0530 Subject: [PATCH 3/5] asoc: codecs: Enable impedance detection for rouleur codec Implement the impedance calculation logic for rouleur codec. Change-Id: I2b62e8c1109f949a12d2f31b4c1f6035a1bc2bba Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 2 + asoc/codecs/rouleur/rouleur-mbhc.c | 363 ++++++++++-------------- asoc/codecs/rouleur/rouleur-registers.h | 2 +- asoc/codecs/rouleur/rouleur-regmap.c | 2 +- asoc/codecs/rouleur/rouleur-tables.c | 2 +- asoc/codecs/rouleur/rouleur.c | 4 +- 6 files changed, 157 insertions(+), 218 deletions(-) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index df8541e34041..233ca519be57 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -170,4 +170,6 @@ extern int rouleur_mbhc_micb_adjust_voltage(struct snd_soc_component *component, extern int rouleur_get_micb_vout_ctl_val(u32 micb_mv); extern int rouleur_micbias_control(struct snd_soc_component *component, int micb_num, int req, bool is_dapm); +extern int rouleur_global_mbias_enable(struct snd_soc_component *component); +extern int rouleur_global_mbias_disable(struct snd_soc_component *component); #endif diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index 2f8e954b5a23..b5a1ac52ffb5 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -22,20 +22,15 @@ #define ROULEUR_ZDET_SUPPORTED true /* Z value defined in milliohm */ -#define ROULEUR_ZDET_VAL_32 32000 -#define ROULEUR_ZDET_VAL_400 400000 -#define ROULEUR_ZDET_VAL_1200 1200000 #define ROULEUR_ZDET_VAL_100K 100000000 /* Z floating defined in ohms */ #define ROULEUR_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE -#define ROULEUR_ZDET_NUM_MEASUREMENTS 900 -#define ROULEUR_MBHC_GET_C1(c) ((c & 0xC000) >> 14) -#define ROULEUR_MBHC_GET_X1(x) (x & 0x3FFF) -/* Z value compared in milliOhm */ -#define ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000)) -#define ROULEUR_MBHC_ZDET_CONST (86 * 16384) -#define ROULEUR_MBHC_MOISTURE_RREF R_24_KOHM +#define ROULEUR_ZDET_NUM_MEASUREMENTS 100 +#define ROULEUR_ZDET_RMAX 1280000 +#define ROULEUR_ZDET_C1 7500000 +#define ROULEUR_ZDET_C2 187 +#define ROULEUR_ZDET_C3 4500 /* Cross connection thresholds in mV */ #define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200 @@ -157,9 +152,6 @@ struct rouleur_mbhc_zdet_param { u16 ldo_ctl; u16 noff; u16 nshift; - u16 btn5; - u16 btn6; - u16 btn7; }; static int rouleur_mbhc_request_irq(struct snd_soc_component *component, @@ -380,174 +372,180 @@ static int rouleur_mbhc_micb_ctrl_threshold_mic( return rc; } -static inline void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur, - s16 *d1_a, u16 noff, - int32_t *zdet) +static void rouleur_mbhc_get_result_params(struct rouleur_priv *rouleur, + struct snd_soc_component *component, + int32_t *zdet) { int i; - int val = 0, val1 = 0; - s16 c1 = 0; - s32 x1 = 0, d1 = 0; - int32_t denom; - int minCode_param[] = { - 3277, 1639, 820, 410, 205, 103, 52, 26 - }; + int zcode = 0, zcode1 = 0, zdet_cal_result = 0, zdet_est_range = 0; + int noff = 0, ndac = 14; + int zdet_cal_coeff = 0, div_ratio = 0; + int num = 0, denom = 0; + /* Charge enable and wait for zcode to be updated */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x20); for (i = 0; i < ROULEUR_ZDET_NUM_MEASUREMENTS; i++) { - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &val); - if (val & 0x80) + regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode); + if (zcode & 0x80) break; + usleep_range(200, 210); } - val = val << 0x8; - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &val1); - val |= val1; - regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00); - x1 = ROULEUR_MBHC_GET_X1(val); - c1 = ROULEUR_MBHC_GET_C1(val); - /* If ramp is not complete, give additional 5ms */ - if ((c1 < 2) && x1) - usleep_range(5000, 5050); - if (!c1 || !x1) { + /* If zcode updation is not complete, give additional 10ms */ + if (!(zcode & 0x80)) + usleep_range(10000, 10100); + + regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &zcode); + if (!(zcode & 0x80)) { dev_dbg(rouleur->dev, - "%s: Impedance detect ramp error, c1=%d, x1=0x%x\n", - __func__, c1, x1); - goto ramp_down; + "%s: Impedance detect calculation error, zcode=0x%x\n", + __func__, zcode); + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, + 0x20, 0x00); + return; } - d1 = d1_a[c1]; - denom = (x1 * d1) - (1 << (14 - noff)); + zcode = zcode << 0x8; + zcode = zcode & 0x3FFF; + regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &zcode1); + zcode |= zcode1; + + dev_dbg(rouleur->dev, + "%s: zcode: %d, zcode1: %d\n", __func__, zcode, zcode1); + + /* Calculate calibration coefficient */ + zdet_cal_result = (snd_soc_component_read32(component, + ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)) & 0x1F; + zdet_cal_coeff = ROULEUR_ZDET_C1 / + ((ROULEUR_ZDET_C2 * zdet_cal_result) + ROULEUR_ZDET_C3); + /* Rload calculation */ + zdet_est_range = (snd_soc_component_read32(component, + ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT) & 0x60) >> 5; + + dev_dbg(rouleur->dev, + "%s: zdet_cal_result: %d, zdet_cal_coeff: %d, zdet_est_range: %d\n", + __func__, zdet_cal_result, zdet_cal_coeff, zdet_est_range); + switch (zdet_est_range) { + case 0: + default: + noff = 0; + div_ratio = 320; + break; + case 1: + noff = 0; + div_ratio = 64; + break; + case 2: + noff = 4; + div_ratio = 64; + break; + case 3: + noff = 5; + div_ratio = 40; + break; + } + + num = zdet_cal_coeff * ROULEUR_ZDET_RMAX; + denom = ((zcode * div_ratio * 100) - (1 << (ndac - noff)) * 1000); + dev_dbg(rouleur->dev, + "%s: num: %d, denom: %d\n", __func__, num, denom); if (denom > 0) - *zdet = (ROULEUR_MBHC_ZDET_CONST * 1000) / denom; - else if (x1 < minCode_param[noff]) + *zdet = (int32_t) ((num / denom) * 1000); + else *zdet = ROULEUR_ZDET_FLOATING_IMPEDANCE; - dev_dbg(rouleur->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n", - __func__, d1, c1, x1, *zdet); -ramp_down: - i = 0; - while (x1) { - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_1, &val); - regmap_read(rouleur->regmap, ROULEUR_ANA_MBHC_RESULT_2, &val1); - val = val << 0x8; - val |= val1; - x1 = ROULEUR_MBHC_GET_X1(val); - i++; - if (i == ROULEUR_ZDET_NUM_MEASUREMENTS) - break; - } + dev_dbg(rouleur->dev, "%s: z_val=%d(milliOhm)\n", + __func__, *zdet); + /* Start discharge */ + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x20, 0x00); } -#if 0 -static void rouleur_mbhc_zdet_ramp(struct snd_soc_component *component, - struct rouleur_mbhc_zdet_param *zdet_param, - int32_t *zl, int32_t *zr, s16 *d1_a) +static void rouleur_mbhc_zdet_start(struct snd_soc_component *component, + int32_t *zl, int32_t *zr) { struct rouleur_priv *rouleur = dev_get_drvdata(component->dev); int32_t zdet = 0; - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, - 0x70, zdet_param->ldo_ctl << 4); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN5, 0xFC, - zdet_param->btn5); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN6, 0xFC, - zdet_param->btn6); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_BTN7, 0xFC, - zdet_param->btn7); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, - 0x0F, zdet_param->noff); - snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, - 0x0F, zdet_param->nshift); - if (!zl) goto z_right; - /* Start impedance measurement for HPH_L */ + + /* HPHL pull down switch to force OFF */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x00); + /* Averaging enable for reliable results */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80); + /* ZDET left measurement enable */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x80, 0x80); - dev_dbg(rouleur->dev, "%s: ramp for HPH_L, noff = %d\n", - __func__, zdet_param->noff); - rouleur_mbhc_get_result_params(rouleur, d1_a, zdet_param->noff, &zdet); + /* Calculate the left Rload result */ + rouleur_mbhc_get_result_params(rouleur, component, &zdet); + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x80, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x30, 0x20); *zl = zdet; z_right: if (!zr) return; - /* Start impedance measurement for HPH_R */ + /* HPHR pull down switch to force OFF */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x00); + /* Averaging enable for reliable results */ + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x80); + /* ZDET right measurement enable */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x40, 0x40); - dev_dbg(rouleur->dev, "%s: ramp for HPH_R, noff = %d\n", - __func__, zdet_param->noff); - rouleur_mbhc_get_result_params(rouleur, d1_a, zdet_param->noff, &zdet); + + /* Calculate the right Rload result */ + rouleur_mbhc_get_result_params(rouleur, component, &zdet); + regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ZDET, 0x40, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_MBHC_ZDET_ANA_CTL, 0x80, 0x00); + regmap_update_bits(rouleur->regmap, + ROULEUR_ANA_HPHPA_CNP_CTL_2, 0x0C, 0x08); *zr = zdet; } -static inline void rouleur_wcd_mbhc_qfuse_cal( - struct snd_soc_component *component, - int32_t *z_val, int flag_l_r) -{ - s16 q1; - int q1_cal; - - if (*z_val < (ROULEUR_ZDET_VAL_400/1000)) - q1 = snd_soc_component_read32(component, - ROULEUR_DIGITAL_EFUSE_REG_23 + (2 * flag_l_r)); - else - q1 = snd_soc_component_read32(component, - ROULEUR_DIGITAL_EFUSE_REG_24 + (2 * flag_l_r)); - if (q1 & 0x80) - q1_cal = (10000 - ((q1 & 0x7F) * 25)); - else - q1_cal = (10000 + (q1 * 25)); - if (q1_cal > 0) - *z_val = ((*z_val) * 10000) / q1_cal; -} - static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, uint32_t *zr) { struct snd_soc_component *component = mbhc->component; struct rouleur_priv *rouleur = dev_get_drvdata(component->dev); - s16 reg0, reg1, reg2, reg3, reg4; + s16 reg0; int32_t z1L, z1R, z1Ls; int zMono, z_diff1, z_diff2; bool is_fsm_disable = false; - struct rouleur_mbhc_zdet_param zdet_param[] = { - {4, 0, 4, 0x08, 0x14, 0x18}, /* < 32ohm */ - {2, 0, 3, 0x18, 0x7C, 0x90}, /* 32ohm < Z < 400ohm */ - {1, 4, 5, 0x18, 0x7C, 0x90}, /* 400ohm < Z < 1200ohm */ - {1, 6, 7, 0x18, 0x7C, 0x90}, /* >1200ohm */ - }; - struct rouleur_mbhc_zdet_param *zdet_param_ptr = NULL; - s16 d1_a[][4] = { - {0, 30, 90, 30}, - {0, 30, 30, 5}, - {0, 30, 30, 5}, - {0, 30, 30, 5}, - }; - s16 *d1 = NULL; WCD_MBHC_RSC_ASSERT_LOCKED(mbhc); - reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN5); - reg1 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN6); - reg2 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_BTN7); - reg3 = snd_soc_component_read32(component, ROULEUR_MBHC_CTL_CLK); - reg4 = snd_soc_component_read32(component, - ROULEUR_ANA_MBHC_ZDET_ANA_CTL); + reg0 = snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT); - if (snd_soc_component_read32(component, ROULEUR_ANA_MBHC_ELECT) & - 0x80) { + if (reg0 & 0x80) { is_fsm_disable = true; regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ELECT, 0x80, 0x00); } + /* Enable electrical bias */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT, + 0x01, 0x01); + + /* Enable codec main bias */ + rouleur_global_mbias_enable(component); + + /* Enable RCO clock */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_CTL_1, + 0x80, 0x80); + /* For NO-jack, disable L_DET_EN before Z-det measurements */ if (mbhc->hphl_swh) regmap_update_bits(rouleur->regmap, @@ -557,79 +555,34 @@ static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_MECH, 0x01, 0x00); - /* Disable surge protection before impedance detection. + /* + * Disable surge protection before impedance detection. * This is done to give correct value for high impedance. */ - regmap_update_bits(rouleur->regmap, - ROULEUR_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0x00); + snd_soc_component_update_bits(component, ROULEUR_ANA_SURGE_EN, + 0xC0, 0x00); /* 1ms delay needed after disable surge protection */ usleep_range(1000, 1010); - /* First get impedance on Left */ - d1 = d1_a[1]; - zdet_param_ptr = &zdet_param[1]; - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); - - if (!ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z1L)) - goto left_ch_impedance; - - /* Second ramp for left ch */ - if (z1L < ROULEUR_ZDET_VAL_32) { - zdet_param_ptr = &zdet_param[0]; - d1 = d1_a[0]; - } else if ((z1L > ROULEUR_ZDET_VAL_400) && - (z1L <= ROULEUR_ZDET_VAL_1200)) { - zdet_param_ptr = &zdet_param[2]; - d1 = d1_a[2]; - } else if (z1L > ROULEUR_ZDET_VAL_1200) { - zdet_param_ptr = &zdet_param[3]; - d1 = d1_a[3]; - } - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, &z1L, NULL, d1); - -left_ch_impedance: + /* Start of left ch impedance calculation */ + rouleur_mbhc_zdet_start(component, &z1L, NULL); if ((z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) || - (z1L > ROULEUR_ZDET_VAL_100K)) { + (z1L > ROULEUR_ZDET_VAL_100K)) *zl = ROULEUR_ZDET_FLOATING_IMPEDANCE; - zdet_param_ptr = &zdet_param[1]; - d1 = d1_a[1]; - } else { + else *zl = z1L/1000; - rouleur_wcd_mbhc_qfuse_cal(component, zl, 0); - } + dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n", __func__, *zl); - /* Start of right impedance ramp and calculation */ - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, &z1R, d1); - if (ROULEUR_MBHC_IS_SECOND_RAMP_REQUIRED(z1R)) { - if (((z1R > ROULEUR_ZDET_VAL_1200) && - (zdet_param_ptr->noff == 0x6)) || - ((*zl) != ROULEUR_ZDET_FLOATING_IMPEDANCE)) - goto right_ch_impedance; - /* Second ramp for right ch */ - if (z1R < ROULEUR_ZDET_VAL_32) { - zdet_param_ptr = &zdet_param[0]; - d1 = d1_a[0]; - } else if ((z1R > ROULEUR_ZDET_VAL_400) && - (z1R <= ROULEUR_ZDET_VAL_1200)) { - zdet_param_ptr = &zdet_param[2]; - d1 = d1_a[2]; - } else if (z1R > ROULEUR_ZDET_VAL_1200) { - zdet_param_ptr = &zdet_param[3]; - d1 = d1_a[3]; - } - rouleur_mbhc_zdet_ramp(component, zdet_param_ptr, NULL, - &z1R, d1); - } -right_ch_impedance: + /* Start of right ch impedance calculation */ + rouleur_mbhc_zdet_start(component, NULL, &z1R); if ((z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) || - (z1R > ROULEUR_ZDET_VAL_100K)) { + (z1R > ROULEUR_ZDET_VAL_100K)) *zr = ROULEUR_ZDET_FLOATING_IMPEDANCE; - } else { + else *zr = z1R/1000; - rouleur_wcd_mbhc_qfuse_cal(component, zr, 1); - } + dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n", __func__, *zr); @@ -651,24 +604,10 @@ right_ch_impedance: mbhc->hph_type = WCD_MBHC_HPH_MONO; goto zdet_complete; } - snd_soc_component_update_bits(component, ROULEUR_HPH_R_ATEST, - 0x02, 0x02); - snd_soc_component_update_bits(component, ROULEUR_HPH_PA_CTL2, - 0x40, 0x01); - if (*zl < (ROULEUR_ZDET_VAL_32/1000)) - rouleur_mbhc_zdet_ramp(component, &zdet_param[0], &z1Ls, - NULL, d1); - else - rouleur_mbhc_zdet_ramp(component, &zdet_param[1], &z1Ls, - NULL, d1); - snd_soc_component_update_bits(component, ROULEUR_HPH_PA_CTL2, - 0x40, 0x00); - snd_soc_component_update_bits(component, ROULEUR_HPH_R_ATEST, - 0x02, 0x00); - z1Ls /= 1000; - rouleur_wcd_mbhc_qfuse_cal(component, &z1Ls, 0); - /* Parallel of left Z and 9 ohm pull down resistor */ - zMono = ((*zl) * 9) / ((*zl) + 9); + + z1Ls = z1L/1000; + /* Parallel of left Z and 20 ohm pull down resistor */ + zMono = ((*zl) * 20) / ((*zl) + 20); z_diff1 = (z1Ls > zMono) ? (z1Ls - zMono) : (zMono - z1Ls); z_diff2 = ((*zl) > z1Ls) ? ((*zl) - z1Ls) : (z1Ls - (*zl)); if ((z_diff1 * (*zl + z1Ls)) > (z_diff2 * (z1Ls + zMono))) { @@ -681,13 +620,10 @@ right_ch_impedance: mbhc->hph_type = WCD_MBHC_HPH_MONO; } +zdet_complete: /* Enable surge protection again after impedance detection */ regmap_update_bits(rouleur->regmap, - ROULEUR_HPH_SURGE_HPHLR_SURGE_EN, 0xC0, 0xC0); -zdet_complete: - snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN5, reg0); - snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN6, reg1); - snd_soc_component_write(component, ROULEUR_ANA_MBHC_BTN7, reg2); + ROULEUR_ANA_SURGE_EN, 0xC0, 0xC0); /* Turn on 100k pull down on HPHL */ regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_MECH, 0x01, 0x01); @@ -697,13 +633,14 @@ zdet_complete: regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_MECH, 0x80, 0x80); - snd_soc_component_write(component, ROULEUR_ANA_MBHC_ZDET_ANA_CTL, reg4); - snd_soc_component_write(component, ROULEUR_MBHC_CTL_CLK, reg3); + /* Restore electrical bias state */ + snd_soc_component_update_bits(component, ROULEUR_ANA_MBHC_ELECT, 0x01, + reg0 >> 7); if (is_fsm_disable) regmap_update_bits(rouleur->regmap, ROULEUR_ANA_MBHC_ELECT, 0x80, 0x80); + rouleur_global_mbias_disable(component); } -#endif static void rouleur_mbhc_gnd_det_ctrl(struct snd_soc_component *component, bool enable) @@ -843,10 +780,10 @@ static void rouleur_mbhc_comp_autozero_control(struct wcd_mbhc *mbhc, { if (az_enable) snd_soc_component_update_bits(mbhc->component, - ROULEUR_ANA_MBHC_MCLK, 0x08, 0x08); + ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x08); else snd_soc_component_update_bits(mbhc->component, - ROULEUR_ANA_MBHC_MCLK, 0x08, 0x00); + ROULEUR_ANA_MBHC_CTL_CLK, 0x08, 0x00); } @@ -889,7 +826,7 @@ static const struct wcd_mbhc_cb mbhc_cb = { .mbhc_micb_ramp_control = rouleur_mbhc_micb_ramp_control, .get_hwdep_fw_cal = rouleur_get_hwdep_fw_cal, .mbhc_micb_ctrl_thr_mic = rouleur_mbhc_micb_ctrl_threshold_mic, - //.compute_impedance = rouleur_wcd_mbhc_calc_impedance, + .compute_impedance = rouleur_wcd_mbhc_calc_impedance, .mbhc_gnd_det_ctrl = rouleur_mbhc_gnd_det_ctrl, .hph_pull_down_ctrl = rouleur_mbhc_hph_pull_down_ctrl, .mbhc_moisture_config = rouleur_mbhc_moisture_config, diff --git a/asoc/codecs/rouleur/rouleur-registers.h b/asoc/codecs/rouleur/rouleur-registers.h index 816e49237dfa..8cc0ae473af0 100644 --- a/asoc/codecs/rouleur/rouleur-registers.h +++ b/asoc/codecs/rouleur/rouleur-registers.h @@ -45,7 +45,7 @@ enum { #define ROULEUR_ANA_MBHC_ZDET_RAMP_CTL (ROULEUR_ANA_BASE_ADDR+0x06A) #define ROULEUR_ANA_MBHC_FSM_STATUS (ROULEUR_ANA_BASE_ADDR+0x06B) #define ROULEUR_ANA_MBHC_ADC_RESULT (ROULEUR_ANA_BASE_ADDR+0x06C) -#define ROULEUR_ANA_MBHC_MCLK (ROULEUR_ANA_BASE_ADDR+0x06D) +#define ROULEUR_ANA_MBHC_CTL_CLK (ROULEUR_ANA_BASE_ADDR+0x06D) #define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT (ROULEUR_ANA_BASE_ADDR+0x072) #define ROULEUR_ANA_NCP_EN (ROULEUR_ANA_BASE_ADDR+0x077) #define ROULEUR_ANA_HPHPA_CNP_CTL_1 (ROULEUR_ANA_BASE_ADDR+0x083) diff --git a/asoc/codecs/rouleur/rouleur-regmap.c b/asoc/codecs/rouleur/rouleur-regmap.c index 08b490db3a5f..23b8ddc96757 100644 --- a/asoc/codecs/rouleur/rouleur-regmap.c +++ b/asoc/codecs/rouleur/rouleur-regmap.c @@ -38,7 +38,7 @@ static const struct reg_default rouleur_defaults[] = { { ROULEUR_ANA_MBHC_ZDET_RAMP_CTL, 0x00 }, { ROULEUR_ANA_MBHC_FSM_STATUS, 0x00 }, { ROULEUR_ANA_MBHC_ADC_RESULT, 0x00 }, - { ROULEUR_ANA_MBHC_MCLK, 0x30 }, + { ROULEUR_ANA_MBHC_CTL_CLK, 0x30 }, { ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT, 0x00 }, { ROULEUR_ANA_NCP_EN, 0x00 }, { ROULEUR_ANA_HPHPA_CNP_CTL_1, 0x54 }, diff --git a/asoc/codecs/rouleur/rouleur-tables.c b/asoc/codecs/rouleur/rouleur-tables.c index 59b7cf2d3383..7912267dac33 100644 --- a/asoc/codecs/rouleur/rouleur-tables.c +++ b/asoc/codecs/rouleur/rouleur-tables.c @@ -33,7 +33,7 @@ const u8 rouleur_reg_access_analog[ROULEUR_REG( [ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_RAMP_CTL)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_FSM_STATUS)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ADC_RESULT)] = RD_REG, - [ROULEUR_REG(ROULEUR_ANA_MBHC_MCLK)] = RD_WR_REG, + [ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_CLK)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG, [ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG, [ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_1)] = RD_WR_REG, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index e1ecdba83f3b..418ed6711d04 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -304,7 +304,7 @@ static int rouleur_rx_connect_port(struct snd_soc_component *component, return ret; } -static int rouleur_global_mbias_enable(struct snd_soc_component *component) +int rouleur_global_mbias_enable(struct snd_soc_component *component) { struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); @@ -322,7 +322,7 @@ static int rouleur_global_mbias_enable(struct snd_soc_component *component) return 0; } -static int rouleur_global_mbias_disable(struct snd_soc_component *component) +int rouleur_global_mbias_disable(struct snd_soc_component *component) { struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component); From cbe9426358674e2bb2680b0de43b6b97b22deb7b Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Wed, 6 May 2020 14:09:09 +0530 Subject: [PATCH 4/5] asoc: codecs: Fix volume fluctuation issue in headphone playback HPH PA pull down control is set to force ON instead of auto due of which saturation/noise is observed in headset playback at highest volumes. Set pull down control to Auto to fix this issue. Change-Id: I465588f46b04bbb32d84f76b8b5bedd2ef21bd2a Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/rouleur-mbhc.c | 4 ++-- asoc/codecs/rouleur/rouleur.c | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/asoc/codecs/rouleur/rouleur-mbhc.c b/asoc/codecs/rouleur/rouleur-mbhc.c index b5a1ac52ffb5..f0eea091cba5 100644 --- a/asoc/codecs/rouleur/rouleur-mbhc.c +++ b/asoc/codecs/rouleur/rouleur-mbhc.c @@ -664,10 +664,10 @@ static void rouleur_mbhc_hph_pull_down_ctrl(struct snd_soc_component *component, if (enable) { snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x30, 0x10); + 0x30, 0x20); snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, - 0x0C, 0x04); + 0x0C, 0x08); } else { snd_soc_component_update_bits(component, ROULEUR_ANA_HPHPA_CNP_CTL_2, diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index 418ed6711d04..480e0ce7a522 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -472,7 +472,7 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, } snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX0_CTL, - 0x7C, 0x7C); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); @@ -486,6 +486,9 @@ static int rouleur_codec_hphl_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX0_CTL, + 0x80, 0x80); if (rouleur->comp1_enable) snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_COMP_CTL_0, @@ -544,7 +547,7 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, } snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX1_CTL, - 0x7C, 0x7C); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x08, 0x08); @@ -557,6 +560,9 @@ static int rouleur_codec_hphr_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x08, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX1_CTL, + 0x80, 0x80); if (rouleur->comp2_enable) snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_COMP_CTL_0, @@ -583,7 +589,7 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, rouleur_rx_clk_enable(component); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX0_CTL, - 0x7C, 0x7C); + 0x80, 0x00); snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x04); @@ -599,6 +605,9 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w, snd_soc_component_update_bits(component, ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL, 0x04, 0x00); + snd_soc_component_update_bits(component, + ROULEUR_DIG_SWR_CDC_RX0_CTL, + 0x80, 0x80); break; }; From f1035cd51c4a46dc041f0440e3ca092488596e31 Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Tue, 19 May 2020 10:41:35 +0530 Subject: [PATCH 5/5] asoc: codecs: Add delay to eliminate playback pause post SSR on hs Add delay in post ssr to eliminate playback pause on euro usbc headset. Post ssr, headset is detected as headphone as HPH PA gets turned ON before the completion of wcd_correct_swch_plug workqueue in MBHC. Change-Id: Ib0334b37aa12b7e7371146b26eb3a1f4484656a3 Signed-off-by: Aditya Bavanari --- asoc/codecs/rouleur/internal.h | 1 + asoc/codecs/rouleur/rouleur.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/asoc/codecs/rouleur/internal.h b/asoc/codecs/rouleur/internal.h index 233ca519be57..c6e7d112ee96 100644 --- a/asoc/codecs/rouleur/internal.h +++ b/asoc/codecs/rouleur/internal.h @@ -83,6 +83,7 @@ struct rouleur_priv { struct mutex rx_clk_lock; struct mutex main_bias_lock; bool dev_up; + bool usbc_hs_status; }; struct rouleur_micbias_setting { diff --git a/asoc/codecs/rouleur/rouleur.c b/asoc/codecs/rouleur/rouleur.c index 480e0ce7a522..7d4e68c57fdf 100644 --- a/asoc/codecs/rouleur/rouleur.c +++ b/asoc/codecs/rouleur/rouleur.c @@ -1341,6 +1341,17 @@ static int rouleur_get_logical_addr(struct swr_device *swr_dev) return 0; } +static bool get_usbc_hs_status(struct snd_soc_component *component, + struct wcd_mbhc_config *mbhc_cfg) +{ + if (mbhc_cfg->enable_usbc_analog) { + if (!(snd_soc_component_read32(component, ROULEUR_ANA_MBHC_MECH) + & 0x20)) + return true; + } + return false; +} + static int rouleur_event_notify(struct notifier_block *block, unsigned long val, void *data) @@ -1373,6 +1384,8 @@ static int rouleur_event_notify(struct notifier_block *block, rouleur->dev_up = false; rouleur->mbhc->wcd_mbhc.deinit_in_progress = true; mbhc = &rouleur->mbhc->wcd_mbhc; + rouleur->usbc_hs_status = get_usbc_hs_status(component, + mbhc->mbhc_cfg); rouleur_mbhc_ssr_down(rouleur->mbhc, component); rouleur_reset(rouleur->dev, 0x01); break; @@ -1394,6 +1407,8 @@ static int rouleur_event_notify(struct notifier_block *block, __func__); } else { rouleur_mbhc_hs_detect(component, mbhc->mbhc_cfg); + if (rouleur->usbc_hs_status) + mdelay(500); } rouleur->mbhc->wcd_mbhc.deinit_in_progress = false; rouleur->dev_up = true;