Loading asoc/codecs/wcd-mbhc-adc.c +71 −41 Original line number Diff line number Diff line Loading @@ -343,14 +343,66 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) 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) Loading @@ -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; Loading Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -691,13 +720,15 @@ static void wcd_correct_swch_plug(struct work_struct *work) */ 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; } Loading @@ -707,7 +738,7 @@ static void wcd_correct_swch_plug(struct work_struct *work) 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); Loading Loading @@ -761,7 +792,7 @@ static void wcd_correct_swch_plug(struct work_struct *work) } } 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; Loading Loading @@ -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++; /* Loading asoc/codecs/wcd934x/wcd934x-mbhc.c +10 −1 Original line number Diff line number Diff line // 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 <linux/module.h> #include <linux/init.h> Loading Loading @@ -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); Loading @@ -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); Loading include/asoc/wcd-mbhc-v2.h +2 −1 Original line number Diff line number Diff line /* 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__ Loading Loading @@ -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; Loading Loading
asoc/codecs/wcd-mbhc-adc.c +71 −41 Original line number Diff line number Diff line Loading @@ -343,14 +343,66 @@ static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) 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) Loading @@ -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; Loading Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -691,13 +720,15 @@ static void wcd_correct_swch_plug(struct work_struct *work) */ 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; } Loading @@ -707,7 +738,7 @@ static void wcd_correct_swch_plug(struct work_struct *work) 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); Loading Loading @@ -761,7 +792,7 @@ static void wcd_correct_swch_plug(struct work_struct *work) } } 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; Loading Loading @@ -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++; /* Loading
asoc/codecs/wcd934x/wcd934x-mbhc.c +10 −1 Original line number Diff line number Diff line // 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 <linux/module.h> #include <linux/init.h> Loading Loading @@ -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); Loading @@ -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); Loading
include/asoc/wcd-mbhc-v2.h +2 −1 Original line number Diff line number Diff line /* 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__ Loading Loading @@ -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; Loading