Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b418f419 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wcd-mbhc: correct special headset detection logic"

parents 6bc6eec8 37621b06
Loading
Loading
Loading
Loading
+71 −41
Original line number Diff line number Diff line
@@ -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)
@@ -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 @@ 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;
			}
@@ -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);
@@ -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;
@@ -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++;
		/*
+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>
@@ -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);
+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__
@@ -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;