[PATCH] ASoC: codecs: MBHC: Add support for special headset
Update MBHC driver to support special headset such as apple and huwawei headsets.
Signed-off-by: Srinivasa Rao Mandadapu srivasam@codeaurora.org Co-developed-by: Venkata Prasad Potturu potturu@codeaurora.org Signed-off-by: Venkata Prasad Potturu potturu@codeaurora.org --- sound/soc/codecs/wcd-mbhc-v2.c | 78 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 405128c..3b4cd39 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1022,6 +1022,57 @@ static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result) return plug_type; }
+static int wcd_mbhc_get_spl_hs_thres(struct wcd_mbhc *mbhc) +{ + int hs_threshold, micbias_mv; + + micbias_mv = wcd_mbhc_get_micbias(mbhc); + if (mbhc->cfg->hs_thr && mbhc->cfg->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) { + if (mbhc->cfg->micb_mv == micbias_mv) + hs_threshold = mbhc->cfg->hs_thr; + else + hs_threshold = (mbhc->cfg->hs_thr * micbias_mv) / + mbhc->cfg->micb_mv; + } else { + hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * micbias_mv) / + WCD_MBHC_ADC_MICBIAS_MV); + } + return hs_threshold; +} + +static bool wcd_mbhc_check_for_spl_headset(struct wcd_mbhc *mbhc) +{ + bool is_spl_hs = false; + int output_mv, hs_threshold, hph_threshold; + + if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) + return false; + + /* Bump up MIC_BIAS2 to 2.7V */ + mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, true); + usleep_range(10000, 10100); + + output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P); + hs_threshold = wcd_mbhc_get_spl_hs_thres(mbhc); + hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc); + + if (output_mv > hs_threshold || output_mv < hph_threshold) { + if (mbhc->force_linein == true) + is_spl_hs = false; + } else { + is_spl_hs = true; + } + + /* Back MIC_BIAS2 to 1.8v if the type is not special headset */ + if (!is_spl_hs) { + mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, false); + /* Add 10ms delay for micbias to settle */ + usleep_range(10000, 10100); + } + + return is_spl_hs; +} + static void wcd_correct_swch_plug(struct work_struct *work) { struct wcd_mbhc *mbhc; @@ -1029,12 +1080,14 @@ static void wcd_correct_swch_plug(struct work_struct *work) enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID; unsigned long timeout; int pt_gnd_mic_swap_cnt = 0; - int output_mv, cross_conn, hs_threshold, try = 0; + int output_mv, cross_conn, hs_threshold, try = 0, micbias_mv; + bool is_spl_hs = false; bool is_pa_on;
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);
/* Mask ADC COMPLETE interrupt */ @@ -1097,6 +1150,18 @@ static void wcd_correct_swch_plug(struct work_struct *work) plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv); is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN);
+ + if ((output_mv > hs_threshold) && + (!is_spl_hs)) { + is_spl_hs = wcd_mbhc_check_for_spl_headset(mbhc); + output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P); + + if (is_spl_hs) { + hs_threshold = (hs_threshold * wcd_mbhc_get_micbias(mbhc)) / + micbias_mv; + } + } + if ((output_mv <= hs_threshold) && !is_pa_on) { /* Check for cross connection*/ cross_conn = wcd_check_cross_conn(mbhc); @@ -1122,14 +1187,19 @@ static void wcd_correct_swch_plug(struct work_struct *work) } }
- if (output_mv > hs_threshold) /* cable is extension cable */ + /* cable is extension cable */ + if (output_mv > hs_threshold || mbhc->force_linein == true) plug_type = MBHC_PLUG_TYPE_HIGH_HPH; }
wcd_mbhc_bcs_enable(mbhc, plug_type, true);
- if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) - wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1); + if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) { + if (is_spl_hs) + plug_type = MBHC_PLUG_TYPE_HEADSET; + else + wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1); + }
wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0); wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
Thanks for adding this support.
few minor nits,
On 03/11/2021 11:18, Srinivasa Rao Mandadapu wrote:
Update MBHC driver to support special headset such as apple and huwawei headsets.
Signed-off-by: Srinivasa Rao Mandadapu srivasam@codeaurora.org Co-developed-by: Venkata Prasad Potturu potturu@codeaurora.org Signed-off-by: Venkata Prasad Potturu potturu@codeaurora.org
sound/soc/codecs/wcd-mbhc-v2.c | 78 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 405128c..3b4cd39 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -1022,6 +1022,57 @@ static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result) return plug_type; }
+static int wcd_mbhc_get_spl_hs_thres(struct wcd_mbhc *mbhc) +{
- int hs_threshold, micbias_mv;
- micbias_mv = wcd_mbhc_get_micbias(mbhc);
- if (mbhc->cfg->hs_thr && mbhc->cfg->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) {
if (mbhc->cfg->micb_mv == micbias_mv)
hs_threshold = mbhc->cfg->hs_thr;
else
hs_threshold = (mbhc->cfg->hs_thr * micbias_mv) /
mbhc->cfg->micb_mv;
You should consider using 100 chars per line, so that reading is much easy.
- } else {
hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * micbias_mv) /
WCD_MBHC_ADC_MICBIAS_MV);
- }
- return hs_threshold;
+}
+static bool wcd_mbhc_check_for_spl_headset(struct wcd_mbhc *mbhc) +{
- bool is_spl_hs = false;
- int output_mv, hs_threshold, hph_threshold;
- if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
return false;
- /* Bump up MIC_BIAS2 to 2.7V */
- mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, true);
- usleep_range(10000, 10100);
- output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
- hs_threshold = wcd_mbhc_get_spl_hs_thres(mbhc);
- hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc);
- if (output_mv > hs_threshold || output_mv < hph_threshold) {
if (mbhc->force_linein == true)
is_spl_hs = false;
- } else {
is_spl_hs = true;
- }
- /* Back MIC_BIAS2 to 1.8v if the type is not special headset */
- if (!is_spl_hs) {
mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, false);
/* Add 10ms delay for micbias to settle */
usleep_range(10000, 10100);
- }
- return is_spl_hs;
+}
- static void wcd_correct_swch_plug(struct work_struct *work) { struct wcd_mbhc *mbhc;
@@ -1029,12 +1080,14 @@ static void wcd_correct_swch_plug(struct work_struct *work) enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID; unsigned long timeout; int pt_gnd_mic_swap_cnt = 0;
- int output_mv, cross_conn, hs_threshold, try = 0;
int output_mv, cross_conn, hs_threshold, try = 0, micbias_mv;
bool is_spl_hs = false; bool is_pa_on;
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);
/* Mask ADC COMPLETE interrupt */
@@ -1097,6 +1150,18 @@ static void wcd_correct_swch_plug(struct work_struct *work) plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv); is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN);
unnecessary extra new line here.
if ((output_mv > hs_threshold) &&
(!is_spl_hs)) {
wrap to 100 chars and unneccessary brackets around the conditions.
With those fixed
Reviewed-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org
--srini
is_spl_hs = wcd_mbhc_check_for_spl_headset(mbhc);
output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
if (is_spl_hs) {
hs_threshold = (hs_threshold * wcd_mbhc_get_micbias(mbhc)) /
micbias_mv; > + }
}
- if ((output_mv <= hs_threshold) && !is_pa_on) { /* Check for cross connection*/ cross_conn = wcd_check_cross_conn(mbhc);
@@ -1122,14 +1187,19 @@ static void wcd_correct_swch_plug(struct work_struct *work) } }
if (output_mv > hs_threshold) /* cable is extension cable */
/* cable is extension cable */
if (output_mv > hs_threshold || mbhc->force_linein == true) plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
}
wcd_mbhc_bcs_enable(mbhc, plug_type, true);
- if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH)
wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1);
if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
if (is_spl_hs)
plug_type = MBHC_PLUG_TYPE_HEADSET;
else
wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1);
}
wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0); wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
On Wed, 3 Nov 2021 16:48:44 +0530, Srinivasa Rao Mandadapu wrote:
Update MBHC driver to support special headset such as apple and huwawei headsets.
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
Thanks!
[1/1] ASoC: codecs: MBHC: Add support for special headset commit: 3c8a3ad4019126f06016ab0128dde11817502f52
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
participants (3)
-
Mark Brown
-
Srinivas Kandagatla
-
Srinivasa Rao Mandadapu