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);