Merge "ASoC: wcd-mbhc: correct special headset detection logic"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
b418f419b0
@@ -343,14 +343,66 @@ done:
|
|||||||
return (plug_type == MBHC_PLUG_TYPE_GND_MIC_SWAP) ? true : false;
|
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,
|
static bool wcd_mbhc_adc_check_for_spl_headset(struct wcd_mbhc *mbhc,
|
||||||
int *spl_hs_cnt)
|
int *spl_hs_cnt)
|
||||||
{
|
{
|
||||||
bool spl_hs = false;
|
bool spl_hs = false;
|
||||||
int output_mv = 0;
|
int output_mv = 0;
|
||||||
int adc_threshold = 0, adc_hph_threshold = 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__);
|
pr_debug("%s: enter\n", __func__);
|
||||||
if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
|
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.
|
* btn press/relesae for HEADSET type during correct work.
|
||||||
*/
|
*/
|
||||||
output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
|
output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
|
||||||
|
adc_threshold = wcd_mbhc_adc_get_spl_hs_thres(mbhc);
|
||||||
if (mbhc->hs_thr &&
|
adc_hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc);
|
||||||
(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);
|
|
||||||
|
|
||||||
if (output_mv > adc_threshold || output_mv < adc_hph_threshold) {
|
if (output_mv > adc_threshold || output_mv < adc_hph_threshold) {
|
||||||
spl_hs = false;
|
spl_hs = false;
|
||||||
@@ -412,8 +452,6 @@ static bool wcd_is_special_headset(struct wcd_mbhc *mbhc)
|
|||||||
bool is_spl_hs = false;
|
bool is_spl_hs = false;
|
||||||
int output_mv = 0;
|
int output_mv = 0;
|
||||||
int adc_threshold = 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
|
* 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mbhc->hs_thr &&
|
adc_threshold = wcd_mbhc_adc_get_spl_hs_thres(mbhc);
|
||||||
(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);
|
|
||||||
|
|
||||||
while (!is_spl_hs) {
|
while (!is_spl_hs) {
|
||||||
if (mbhc->hs_detect_work_stop) {
|
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;
|
enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID;
|
||||||
u32 hph_thr = 0, hs_thr = 0;
|
u32 hph_thr = 0, hs_thr = 0;
|
||||||
|
|
||||||
if (mbhc->hs_thr)
|
hs_thr = wcd_mbhc_adc_get_hs_thres(mbhc);
|
||||||
hs_thr = mbhc->hs_thr;
|
hph_thr = wcd_mbhc_adc_get_hph_thres(mbhc);
|
||||||
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;
|
|
||||||
|
|
||||||
if (adc_result < hph_thr)
|
if (adc_result < hph_thr)
|
||||||
plug_type = MBHC_PLUG_TYPE_HEADPHONE;
|
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 output_mv = 0;
|
||||||
int cross_conn;
|
int cross_conn;
|
||||||
int try = 0;
|
int try = 0;
|
||||||
|
int hs_threshold, micbias_mv;
|
||||||
|
|
||||||
pr_debug("%s: enter\n", __func__);
|
pr_debug("%s: enter\n", __func__);
|
||||||
|
|
||||||
mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch);
|
mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch);
|
||||||
component = mbhc->component;
|
component = mbhc->component;
|
||||||
|
|
||||||
|
micbias_mv = wcd_mbhc_get_micbias(mbhc);
|
||||||
|
hs_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
|
||||||
|
|
||||||
WCD_MBHC_RSC_LOCK(mbhc);
|
WCD_MBHC_RSC_LOCK(mbhc);
|
||||||
/* Mask ADC COMPLETE interrupt */
|
/* Mask ADC COMPLETE interrupt */
|
||||||
wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
|
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);
|
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_count < WCD_MBHC_SPL_HS_CNT)) {
|
||||||
spl_hs = wcd_mbhc_adc_check_for_spl_headset(mbhc,
|
spl_hs = wcd_mbhc_adc_check_for_spl_headset(mbhc,
|
||||||
&spl_hs_count);
|
&spl_hs_count);
|
||||||
|
output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
|
||||||
|
|
||||||
if (spl_hs_count == WCD_MBHC_SPL_HS_CNT) {
|
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;
|
spl_hs = true;
|
||||||
mbhc->micbias_enable = true;
|
mbhc->micbias_enable = true;
|
||||||
}
|
}
|
||||||
@@ -707,7 +738,7 @@ correct_plug_type:
|
|||||||
is_pa_on = mbhc->mbhc_cb->hph_pa_on_status(
|
is_pa_on = mbhc->mbhc_cb->hph_pa_on_status(
|
||||||
mbhc->component);
|
mbhc->component);
|
||||||
|
|
||||||
if ((output_mv <= WCD_MBHC_ADC_HS_THRESHOLD_MV) &&
|
if ((output_mv <= hs_threshold) &&
|
||||||
(!is_pa_on)) {
|
(!is_pa_on)) {
|
||||||
/* Check for cross connection*/
|
/* Check for cross connection*/
|
||||||
ret = wcd_check_cross_conn(mbhc);
|
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__);
|
pr_debug("%s: cable is extension cable\n", __func__);
|
||||||
plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
|
plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
|
||||||
wrk_complete = true;
|
wrk_complete = true;
|
||||||
@@ -926,9 +957,8 @@ static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
|
|||||||
|
|
||||||
timeout = jiffies +
|
timeout = jiffies +
|
||||||
msecs_to_jiffies(WCD_FAKE_REMOVAL_MIN_PERIOD_MS);
|
msecs_to_jiffies(WCD_FAKE_REMOVAL_MIN_PERIOD_MS);
|
||||||
adc_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV *
|
adc_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
|
||||||
wcd_mbhc_get_micbias(mbhc)) /
|
|
||||||
WCD_MBHC_ADC_MICBIAS_MV);
|
|
||||||
do {
|
do {
|
||||||
retry++;
|
retry++;
|
||||||
/*
|
/*
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// 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/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@@ -1102,6 +1102,7 @@ int tavil_mbhc_init(struct wcd934x_mbhc **mbhc,
|
|||||||
struct wcd934x_mbhc *wcd934x_mbhc;
|
struct wcd934x_mbhc *wcd934x_mbhc;
|
||||||
struct wcd_mbhc *wcd_mbhc;
|
struct wcd_mbhc *wcd_mbhc;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct wcd9xxx_pdata *pdata;
|
||||||
|
|
||||||
wcd934x_mbhc = devm_kzalloc(component->dev, sizeof(struct wcd934x_mbhc),
|
wcd934x_mbhc = devm_kzalloc(component->dev, sizeof(struct wcd934x_mbhc),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
@@ -1122,6 +1123,14 @@ int tavil_mbhc_init(struct wcd934x_mbhc **mbhc,
|
|||||||
/* Setting default mbhc detection logic to ADC for Tavil */
|
/* Setting default mbhc detection logic to ADC for Tavil */
|
||||||
wcd_mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
|
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,
|
ret = wcd_mbhc_init(wcd_mbhc, component, &mbhc_cb,
|
||||||
&intr_ids, wcd_mbhc_registers,
|
&intr_ids, wcd_mbhc_registers,
|
||||||
TAVIL_ZDET_SUPPORTED);
|
TAVIL_ZDET_SUPPORTED);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* 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__
|
#ifndef __WCD_MBHC_V2_H__
|
||||||
#define __WCD_MBHC_V2_H__
|
#define __WCD_MBHC_V2_H__
|
||||||
@@ -540,6 +540,7 @@ struct wcd_mbhc {
|
|||||||
bool gnd_swh; /*track GND switch NC / NO */
|
bool gnd_swh; /*track GND switch NC / NO */
|
||||||
u32 hs_thr;
|
u32 hs_thr;
|
||||||
u32 hph_thr;
|
u32 hph_thr;
|
||||||
|
u32 micb_mv;
|
||||||
u32 swap_thr;
|
u32 swap_thr;
|
||||||
u32 moist_vref;
|
u32 moist_vref;
|
||||||
u32 moist_iref;
|
u32 moist_iref;
|
||||||
|
Reference in New Issue
Block a user