主要用到了这么几个文件:wcd-mbhc-v2.c wcd-mbhc-adc.c bengal.c
入口wcd_mbhc_init
switch (mbhc->mbhc_detection_logic) {
case WCD_DETECTION_LEGACY:
wcd_mbhc_legacy_init(mbhc);
break;
case WCD_DETECTION_ADC:
wcd_mbhc_adc_init(mbhc);
break;
default:
pr_err("%s: Unknown detection logic type %d\n",
__func__, mbhc->mbhc_detection_logic);
break;
}
if (!mbhc->mbhc_fn ||
!mbhc->mbhc_fn->wcd_mbhc_hs_ins_irq ||
!mbhc->mbhc_fn->wcd_mbhc_hs_rem_irq ||
!mbhc->mbhc_fn->wcd_mbhc_detect_plug_type ||
!mbhc->mbhc_fn->wcd_cancel_hs_detect_plug) {
pr_err("%s: mbhc function pointer is NULL\n", __func__);
goto err_mbhc_sw_irq;
}
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->mbhc_sw_intr,
wcd_mbhc_mech_plug_detect_irq,
"mbhc sw intr", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d, ret = %d\n", __func__,
mbhc->intr_ids->mbhc_sw_intr, ret);
goto err_mbhc_sw_irq;
}
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->mbhc_btn_press_intr,
wcd_mbhc_btn_press_handler,
"Button Press detect", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc->intr_ids->mbhc_btn_press_intr);
goto err_btn_press_irq;
}
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->mbhc_btn_release_intr,
wcd_mbhc_release_handler,
"Button Release detect", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc->intr_ids->mbhc_btn_release_intr);
goto err_btn_release_irq;
}
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->mbhc_hs_ins_intr,
mbhc->mbhc_fn->wcd_mbhc_hs_ins_irq,
"Elect Insert", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc->intr_ids->mbhc_hs_ins_intr);
goto err_mbhc_hs_ins_irq;
}
mbhc->mbhc_cb->irq_control(component, mbhc->intr_ids->mbhc_hs_ins_intr,
false);
clear_bit(WCD_MBHC_ELEC_HS_INS, &mbhc->intr_status);
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->mbhc_hs_rem_intr,
mbhc->mbhc_fn->wcd_mbhc_hs_rem_irq,
"Elect Remove", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc->intr_ids->mbhc_hs_rem_intr);
goto err_mbhc_hs_rem_irq;
}
mbhc->mbhc_cb->irq_control(component, mbhc->intr_ids->mbhc_hs_rem_intr,
false);
clear_bit(WCD_MBHC_ELEC_HS_REM, &mbhc->intr_status);
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->hph_left_ocp,
wcd_mbhc_hphl_ocp_irq, "HPH_L OCP detect",
mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc->intr_ids->hph_left_ocp);
goto err_hphl_ocp_irq;
}
ret = mbhc->mbhc_cb->request_irq(component,
mbhc->intr_ids->hph_right_ocp,
wcd_mbhc_hphr_ocp_irq, "HPH_R OCP detect",
mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc->intr_ids->hph_right_ocp);
goto err_hphr_ocp_irq;
}
mbhc->deinit_in_progress = false;
pr_debug("%s: leave ret %d\n", __func__, ret);
return ret;
1.初始化wcd-mbhc-adc.c里的wcd_mbhc_adc_init:主要INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);创建一个任务队列纠正当前类型。
2.注册了七个中断。
wcd_mbhc_mech_plug_detect_irq ----耳机中断,无论怎么插耳机必走
wcd_mbhc_btn_press_handler ----按键按下中断
wcd_mbhc_release_handler ----按键松开中断
wcd_mbhc_hs_ins_irq ----选择插入中断(一般插着typec转接线再插耳机会触发)WCD_MBHC_ELEC_HS_INS是标志位,通过wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);打开或者关闭这个中断。
wcd_mbhc_hs_rem_irq ----选择拔出中断,同上。
do {
retry++;
/*
* read output_mv every 10ms to look for
* any change in IN2_P
*/
usleep_range(10000, 10100);
output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
pr_debug("%s: Check for fake removal: output_mv %d\n",
__func__, output_mv);
if ((output_mv <= adc_threshold) &&
retry > FAKE_REM_RETRY_ATTEMPTS) {
pr_debug("%s: headset is NOT actually removed\n",
__func__);
goto exit;
}
} while (!time_after(jiffies, timeout));
有时候micbiae电压变化也会发出拔出中断,可以提高WCD_MBHC_ADC_HS_THRESHOLD_MV的值,比如2200。
最后bengal.c里.detect_extn_cable = true代表检测外部的连接线,会把WCD_MBHC_ELEC_HS_INS和WCD_MBHC_ELEC_HS_REM赋值为true,打开第4、5个中断。反之关掉这俩中断。