mtk平台typec模拟耳机补丁

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=<1>;
}

屏蔽后,正插能识别到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 = <&mic_state1>;
+	pinctrl-1 = <&mic_state2>;
+};
+&pio {
+	mic_state1:mic_state1{
+		pins_cmd_dat {
+			pinmux = <PINMUX_GPIO155__FUNC_GPIO155>;
+			slew-rate = <1>;  //1输出 0输入
+			bias-disable;
+			output-low;
+		};
+	};
+	mic_state2:mic_state2{
+		pins_cmd_dat {
+			pinmux = <PINMUX_GPIO155__FUNC_GPIO155>;
+			slew-rate = <1>;
+			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,应该也是可以的。 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值