typec模拟耳机在某些高端手机上已经很常见了,但拿到的代码默认不支持typec模拟耳机(在某些平台上默认就是typec模拟耳机),那只能自己修改了。
这里用的版本为Android11,kernel4.19。
由于默认的耳机检测驱动mt6357-accdet.c已换成ko的形式(非ko方式可忽略该修改),导致无法调用该驱动里的函数,先把该驱动编译进内核。
defconfig加入CONFIG_SND_SOC_MT6357_ACCDET=y
BoardConfig.mk
- @@ -53,8 +53,7 @@ BOARD_FLASH_BLOCK_SIZE := 4096 KERNEL_OUT ?= $(OUT_DIR)/target/project/$(TARGET_DEVICE)/obj/KERNEL_OBJ # in-tree kernel modules installed to vendor # For Common-BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_OUT)/sound/soc/codecs/mt6357-accdet.ko \- $(KERNEL_OUT)/kernel/trace/trace_mmstat.ko \+BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_OUT)/kernel/trace/trace_mmstat.ko \
复制代码 然后将CC脚检测到的耳机信号发出来
- --- a/kernel-4.19/drivers/misc/mediatek/typec/tcpc/rt_pd_manager.c+++ b/kernel-4.19/drivers/misc/mediatek/typec/tcpc/rt_pd_manager.c@@ -52,7 +52,7 @@ void __attribute__((weak)) usb_dpdm_pulldown(bool enable) { pr_notice("%s is not defined\n", __func__); }-+extern void typec_headphone_irq_handler(int state); static int pd_tcp_notifier_call(struct notifier_block *nb, unsigned long event, void *data) {@@ -91,10 +91,12 @@ static int pd_tcp_notifier_call(struct notifier_block *nb, if (noti->typec_state.old_state == TYPEC_UNATTACHED && noti->typec_state.new_state == TYPEC_ATTACHED_AUDIO) { /* AUDIO plug in */+ typec_headphone_irq_handler(1); pr_info("%s audio plug in\n", __func__); } else if (noti->typec_state.old_state == TYPEC_ATTACHED_AUDIO && noti->typec_state.new_state == TYPEC_UNATTACHED) { /* AUDIO plug out */+ typec_headphone_irq_handler(0); pr_info("%s audio plug out\n", __func__); } break;
复制代码 在mt6357-accdet.c加入如下修改
- +void typec_headphone_irq_handler(int state)+{+ if (accdet->cur_eint_state == EINT_PLUG_IN) {+ accdet->cur_eint_state = EINT_PLUG_OUT;+ } else {+ accdet->cur_eint_state = EINT_PLUG_IN;+ mod_timer(&micbias_timer,jiffies + MICBIAS_DISABLE_TIMER);+ }+ queue_work(accdet->eint_workqueue, &accdet->eint_work);+}+EXPORT_SYMBOL(typec_headphone_irq_handler);
复制代码 这时,系统已经能检测到耳机了,播放音乐能正常听到音乐。
但检测到都是3段耳机,理论上正插和反插有一次是对的,不需要举行mic和gnd的切换。
这时丈量micbias电压(有将micbias关闭的地方屏蔽),妥妥的0v。
跟mtk沟通,说要屏蔽住这里
- ret = of_property_read_u32(node, "headset-eint-num", &tmp); if (ret) tmp = 0; if (tmp == 0) accdet->data->caps |= ACCDET_PMIC_EINT0; else if (tmp == 1) accdet->data->caps |= ACCDET_PMIC_EINT1; else if (tmp == 2) accdet->data->caps |= ACCDET_PMIC_BI_EINT;
复制代码 同时加入如下修改
- &pmic_accdet{+ headset-use-ap-eint=;}
复制代码
屏蔽后,正插能识别到4段耳机,反插识别为3段耳机。推测PMIC_EINT的作用是accdet中断来了,才华打开micbias,但由于触发不了accdet中断,导致micbias无法开启。
如果像小米一样接纳自动切换mic和gnd的ic FSA4480(https://github.com/MiCode/Xiaomi_Kernel_OpenSource/blob/cezanne-q-oss/drivers/misc/mediatek/accdet/mt6359/accdet.c),这里的工作已经是完成了。
但这里接纳切换ic是需要手工识别的,还需判定mic引脚的电压,如果电压偏低,需要举行切换。
用dct工具设置切换ic的引脚为平凡gpio模式,同时确认该引脚没有被占用
- +&pmic_accdet{+ pinctrl-names ="mic_state1","mic_state2";+ pinctrl-0 = ;+ pinctrl-1 = ;+};+&pio {+ mic_state1:mic_state1{+ pins_cmd_dat {+ pinmux = ;+ slew-rate = ; //1输出 0输入+ bias-disable;+ output-low;+ };+ };+ mic_state2:mic_state2{+ pins_cmd_dat {+ pinmux = ;+ slew-rate = ;+ bias-disable;+ output-high;+ };+ };+};
复制代码 在probe中加入如下函数mic_gpio_get(pdev);
- static inline int mic_gpio_get(struct platform_device *platform_device){ int ret = 0; accdet->pinctrl = devm_pinctrl_get(&platform_device->dev); if (IS_ERR(accdet->pinctrl)) { ret = PTR_ERR(accdet->pinctrl); return ret; } accdet->mic1 = pinctrl_lookup_state(accdet->pinctrl, "mic_state1"); if (IS_ERR(accdet->mic1)) { ret = PTR_ERR(accdet->mic1); return ret; } accdet->mic2 = pinctrl_lookup_state(accdet->pinctrl, "mic_state2"); if (IS_ERR(accdet->mic2)) { ret = PTR_ERR(accdet->mic2); return ret; } return 0;}
复制代码- --- a/kernel-4.19/sound/soc/codecs/mt6357-accdet.c+++ b/kernel-4.19/sound/soc/codecs/mt6357-accdet.c@@ -99,6 +99,8 @@ struct mt63xx_accdet_data { /* when caps include ACCDET_AP_GPIO_EINT */ struct pinctrl *pinctrl; struct pinctrl_state *pins_eint;+ struct pinctrl_state *mic1;+ struct pinctrl_state *mic2; u32 gpiopin; u32 gpio_hp_deb; u32 gpioirq;
复制代码
这里的600对应0.6v,实际该值改为0.4v,应该也是可以的。
来源:https://blog.csdn.net/mike8825/article/details/112062132
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |