diff --git a/asoc/codecs/wcd-mbhc-adc.c b/asoc/codecs/wcd-mbhc-adc.c index 4ab510c7e0..4a2c928a90 100644 --- a/asoc/codecs/wcd-mbhc-adc.c +++ b/asoc/codecs/wcd-mbhc-adc.c @@ -343,14 +343,66 @@ done: return (plug_type == MBHC_PLUG_TYPE_GND_MIC_SWAP) ? true : false; } +static int wcd_mbhc_adc_get_spl_hs_thres(struct wcd_mbhc *mbhc) +{ + int hs_threshold, micbias_mv; + + micbias_mv = wcd_mbhc_get_micbias(mbhc); + if (mbhc->hs_thr && mbhc->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) { + if (mbhc->micb_mv == micbias_mv) + hs_threshold = mbhc->hs_thr; + else + hs_threshold = (mbhc->hs_thr * + micbias_mv) / mbhc->micb_mv; + } else { + hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * + micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV); + } + return hs_threshold; +} + +static int wcd_mbhc_adc_get_hs_thres(struct wcd_mbhc *mbhc) +{ + int hs_threshold, micbias_mv; + + micbias_mv = wcd_mbhc_get_micbias(mbhc); + if (mbhc->hs_thr) { + if (mbhc->micb_mv == micbias_mv) + hs_threshold = mbhc->hs_thr; + else + hs_threshold = (mbhc->hs_thr * + micbias_mv) / mbhc->micb_mv; + } else { + hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * + micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV); + } + return hs_threshold; +} + +static int wcd_mbhc_adc_get_hph_thres(struct wcd_mbhc *mbhc) +{ + int hph_threshold, micbias_mv; + + micbias_mv = wcd_mbhc_get_micbias(mbhc); + if (mbhc->hph_thr) { + if (mbhc->micb_mv == micbias_mv) + hph_threshold = mbhc->hph_thr; + else + hph_threshold = (mbhc->hph_thr * + micbias_mv) / mbhc->micb_mv; + } else { + hph_threshold = ((WCD_MBHC_ADC_HPH_THRESHOLD_MV * + micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV); + } + return hph_threshold; +} + static bool wcd_mbhc_adc_check_for_spl_headset(struct wcd_mbhc *mbhc, int *spl_hs_cnt) { bool spl_hs = false; int output_mv = 0; int adc_threshold = 0, adc_hph_threshold = 0; - struct snd_soc_component *component = mbhc->component; - struct wcd9xxx_pdata *pdata = dev_get_platdata(component->dev->parent); pr_debug("%s: enter\n", __func__); if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) @@ -366,20 +418,8 @@ static bool wcd_mbhc_adc_check_for_spl_headset(struct wcd_mbhc *mbhc, * btn press/relesae for HEADSET type during correct work. */ output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P); - - if (mbhc->hs_thr && - (pdata->micbias.micb2_mv != WCD_MBHC_ADC_MICBIAS_MV)) - adc_threshold = mbhc->hs_thr; - else - adc_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * - wcd_mbhc_get_micbias(mbhc))/WCD_MBHC_ADC_MICBIAS_MV); - - if (mbhc->hph_thr) - adc_hph_threshold = mbhc->hph_thr; - else - adc_hph_threshold = ((WCD_MBHC_ADC_HPH_THRESHOLD_MV * - wcd_mbhc_get_micbias(mbhc))/ - WCD_MBHC_ADC_MICBIAS_MV); + adc_threshold = wcd_mbhc_adc_get_spl_hs_thres(mbhc); + adc_hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc); if (output_mv > adc_threshold || output_mv < adc_hph_threshold) { spl_hs = false; @@ -412,8 +452,6 @@ static bool wcd_is_special_headset(struct wcd_mbhc *mbhc) bool is_spl_hs = false; int output_mv = 0; int adc_threshold = 0; - struct snd_soc_component *component = mbhc->component; - struct wcd9xxx_pdata *pdata = dev_get_platdata(component->dev->parent); /* * Increase micbias to 2.7V to detect headsets with @@ -433,13 +471,7 @@ static bool wcd_is_special_headset(struct wcd_mbhc *mbhc) return false; } } - if (mbhc->hs_thr && - (pdata->micbias.micb2_mv != WCD_MBHC_ADC_MICBIAS_MV)) - adc_threshold = mbhc->hs_thr; - else - adc_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * - wcd_mbhc_get_micbias(mbhc)) / - WCD_MBHC_ADC_MICBIAS_MV); + adc_threshold = wcd_mbhc_adc_get_spl_hs_thres(mbhc); while (!is_spl_hs) { if (mbhc->hs_detect_work_stop) { @@ -573,15 +605,8 @@ static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result) enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID; u32 hph_thr = 0, hs_thr = 0; - if (mbhc->hs_thr) - hs_thr = mbhc->hs_thr; - else - hs_thr = WCD_MBHC_ADC_HS_THRESHOLD_MV; - - if (mbhc->hph_thr) - hph_thr = mbhc->hph_thr; - else - hph_thr = WCD_MBHC_ADC_HPH_THRESHOLD_MV; + hs_thr = wcd_mbhc_adc_get_hs_thres(mbhc); + hph_thr = wcd_mbhc_adc_get_hph_thres(mbhc); if (adc_result < hph_thr) plug_type = MBHC_PLUG_TYPE_HEADPHONE; @@ -609,12 +634,16 @@ static void wcd_correct_swch_plug(struct work_struct *work) int output_mv = 0; int cross_conn; int try = 0; + int hs_threshold, micbias_mv; pr_debug("%s: enter\n", __func__); mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch); component = mbhc->component; + micbias_mv = wcd_mbhc_get_micbias(mbhc); + hs_threshold = wcd_mbhc_adc_get_hs_thres(mbhc); + WCD_MBHC_RSC_LOCK(mbhc); /* Mask ADC COMPLETE interrupt */ wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false); @@ -691,13 +720,15 @@ correct_plug_type: */ plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv); - if ((output_mv > WCD_MBHC_ADC_HS_THRESHOLD_MV) && + if ((output_mv > hs_threshold) && (spl_hs_count < WCD_MBHC_SPL_HS_CNT)) { spl_hs = wcd_mbhc_adc_check_for_spl_headset(mbhc, &spl_hs_count); + output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P); if (spl_hs_count == WCD_MBHC_SPL_HS_CNT) { - output_mv = WCD_MBHC_ADC_HS_THRESHOLD_MV; + hs_threshold = (hs_threshold * + wcd_mbhc_get_micbias(mbhc)) / micbias_mv; spl_hs = true; mbhc->micbias_enable = true; } @@ -707,7 +738,7 @@ correct_plug_type: is_pa_on = mbhc->mbhc_cb->hph_pa_on_status( mbhc->component); - if ((output_mv <= WCD_MBHC_ADC_HS_THRESHOLD_MV) && + if ((output_mv <= hs_threshold) && (!is_pa_on)) { /* Check for cross connection*/ ret = wcd_check_cross_conn(mbhc); @@ -761,7 +792,7 @@ correct_plug_type: } } - if (output_mv > WCD_MBHC_ADC_HS_THRESHOLD_MV) { + if (output_mv > hs_threshold) { pr_debug("%s: cable is extension cable\n", __func__); plug_type = MBHC_PLUG_TYPE_HIGH_HPH; wrk_complete = true; @@ -926,9 +957,8 @@ static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data) timeout = jiffies + msecs_to_jiffies(WCD_FAKE_REMOVAL_MIN_PERIOD_MS); - adc_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * - wcd_mbhc_get_micbias(mbhc)) / - WCD_MBHC_ADC_MICBIAS_MV); + adc_threshold = wcd_mbhc_adc_get_hs_thres(mbhc); + do { retry++; /* diff --git a/asoc/codecs/wcd934x/wcd934x-mbhc.c b/asoc/codecs/wcd934x/wcd934x-mbhc.c index f00e4c0a98..d777d8d564 100644 --- a/asoc/codecs/wcd934x/wcd934x-mbhc.c +++ b/asoc/codecs/wcd934x/wcd934x-mbhc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. */ #include #include @@ -1102,6 +1102,7 @@ int tavil_mbhc_init(struct wcd934x_mbhc **mbhc, struct wcd934x_mbhc *wcd934x_mbhc; struct wcd_mbhc *wcd_mbhc; int ret; + struct wcd9xxx_pdata *pdata; wcd934x_mbhc = devm_kzalloc(component->dev, sizeof(struct wcd934x_mbhc), GFP_KERNEL); @@ -1122,6 +1123,14 @@ int tavil_mbhc_init(struct wcd934x_mbhc **mbhc, /* Setting default mbhc detection logic to ADC for Tavil */ wcd_mbhc->mbhc_detection_logic = WCD_DETECTION_ADC; + pdata = dev_get_platdata(component->dev->parent); + if (!pdata) { + dev_err(component->dev, "%s: pdata pointer is NULL\n", __func__); + ret = -EINVAL; + goto err; + } + wcd_mbhc->micb_mv = pdata->micbias.micb2_mv; + ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb, &intr_ids, wcd_mbhc_registers, TAVIL_ZDET_SUPPORTED); diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index c98cdda944..9341e3d3c7 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2019, The Linux Foundation. All rights reserved. */ #ifndef __WCD_MBHC_V2_H__ #define __WCD_MBHC_V2_H__ @@ -540,6 +540,7 @@ struct wcd_mbhc { bool gnd_swh; /*track GND switch NC / NO */ u32 hs_thr; u32 hph_thr; + u32 micb_mv; u32 swap_thr; u32 moist_vref; u32 moist_iref;