耳机检测方案
检测方案1(主流方案):耳机插拔中断接的PMIC (HP_EINT+ACCDET)
CONFIG_ACCDET_EINT_IRQ && CONFIG_ACCDET_SUPPORT_EINT0
CONFIG_ACCDET_EINT_IRQ && CONFIG_ACCDET_SUPPORT_EINT1//平台默认的是EINT0,EINT1不确定具体作用
采用默认的方案,工程师不用调试,接上耳机,手机就能识别到耳机,很方便。
检测方案2:耳机插拔中断接AP(EINT_EAR+ACCDET) 这种方式,需要稍微修改下代码
共同点:ACCDET用来检测mic的存在
差异:用不同的中断来检测耳机的插拔,默认都是用PMIC上的中断来检测耳机的插入,使用AP中断的方式来检测耳机感觉像是替补。
先看下耳机检测流程(HP_EINT+ACCDET kernel4.14)
pmic_register_interrupt_callback(INT_ACCDET_EINT0,accdet_eint_handler);
static void accdet_eint_handler(void)
{
accdet_irq_handle();
}
void accdet_irq_handle(void)
{
...
pmic_eint_queue_work(eintID);
...
}
static int pmic_eint_queue_work(int eintID)
{
...
#ifdef CONFIG_ACCDET_SUPPORT_EINT0
if (cur_eint_state == EINT_PIN_PLUG_IN) {
cur_eint_state = EINT_PIN_PLUG_OUT;
} else {
cur_eint_state = EINT_PIN_PLUG_IN;
}
queue_work(eint_workqueue, &eint_work); //INIT_WORK(&eint_work, eint_work_callback);
#endif
...
}
static void eint_work_callback(struct work_struct *work)
{
if (cur_eint_state == EINT_PIN_PLUG_IN) {
accdet_init();
/* set PWM IDLE on */
pmic_write(ACCDET_STATE_SWCTRL,(pmic_read(ACCDET_STATE_SWCTRL) | ACCDET_PWM_IDLE));
#ifdef CONFIG_ACCDET_EINT_IRQ
#ifdef CONFIG_ACCDET_SUPPORT_EINT0
enable_accdet(ACCDET_EINT0_PWM_IDLE_B11 | ACCDET_PWM_EN);
#endif
#else
enable_accdet(ACCDET_PWM_EN);//开启micbias
#endif
} else {
/* clc Accdet PWM idle */
pmic_write(ACCDET_STATE_SWCTRL,pmic_read(ACCDET_STATE_SWCTRL) & (~ACCDET_PWM_IDLE));
disable_accdet();
headset_plug_out();
}
#ifdef CONFIG_ACCDET_EINT
enable_irq(accdet_irq);
pr_info("accdet %s enable_irq !!\n", __func__);
#endif
}
这时就可以触发accdet中断(检测耳机类型)
pmic_register_interrupt_callback(INT_ACCDET, accdet_int_handler);
static void accdet_int_handler(void)
{
accdet_irq_handle();
}
void accdet_irq_handle(void)
{
...
#ifdef CONFIG_ACCDET_EINT_IRQ
eintID = get_triggered_eint();
#endif
irq_status = pmic_read(ACCDET_IRQ_STS);
if ((irq_status & ACCDET_IRQ_B0) && (eintID == 0)) {
accdet_queue_work();
}
}
...
}
static void accdet_queue_work(void)
{
...
ret = queue_work(accdet_workqueue, &accdet_work);//INIT_WORK(&accdet_work, accdet_work_callback);
...
}
static void accdet_work_callback(struct work_struct *work)
{
...
check_cable_type();
...
}
注意到了没有accdet_irq_handle函数跑了两遍,分别跑里面不同的部分。
以后的按键检测重复跑accdet_int_handler。
以上是根据代码分析到的流程。为什么要分析上述流程呢,因为楼主使用的硬件的需要用accdect only的方式来检测typce非标耳机(pmic不带cc脚,不能识别到标准typec耳机,如果使用其他ic来检测耳机会增加成本)。accdect only的方式,mtk说kernel3.18以后都没有维护了,只能自己来实现了,调完了再记录下吧。