MTK 底层耳机中断上报流程

来源:互联网 发布:已定义两个字符数组ab 编辑:程序博客网 时间:2024/04/29 18:22

【背景知识】:

国标耳机插头信号定义:             <<<【左声道】【右声道】【麦克】【地】美标耳机插入信号定义:             <<<【左声道】【右声道】【地】【麦克】    

【micbias】: 是用来在耳机有 Mic 的情况下,给 Mic 提供直流偏置,让其正常工作的。他使用 PWM 控制,用于降低麦克的功耗, 在不用麦克的情况下,可以降低轮询检测按键的功耗。
【PMCI ACCDET 模块】:是用来检测耳机类型及按键类型的。

【线控耳机原理图】:这里写图片描述

图片盗自百度,见谅。

解释下大概原理吧,首先这是个美标耳机,从左至右四段依次为
【左声道】【右声道】【地】【麦克】
左、右声道与麦克共地,重点看麦克与地之间,他在地之间并了 4 个元件,CPU 判断哪个按键的原理就是依靠麦克与地之间的按下按键时的不同的电阻值,导致麦克与地之间电压变化:
  MIC: 电阻很高(600Ω至10kΩ)
  接听/播放按键,按下时电阻为 0
  上一曲:按下时电阻为 600
  下一曲:按下时电阻为 220
在麦克线路上,上面会连接到 PMIC 的 Accdet 引脚,以及 micbias 引脚,micbias 会产生一个 PWM 波形,波峰时会进行录音,检查【麦克脚与地】之间的电压,从而判断现在是接上 MIC 还是按下按键了。

【检测电路解释】

MTK 检测耳机有两种方式:

  1. Accdet only
    此方式是让耳机 micbias 常开下,依靠 PMIC 内部中断来检测耳机处于的状态的。但此方式会带来耳机插入瞬间有 pop 杂音的出现。

  2. Accdet+EINT 方式
    此方式在耳机为插入时,micbias 是被 disable 的。利用中断让 AP 检测到有耳机插入后,在中断中打开 micbias,从而达到省功耗和减小杂音的效果的。待插入后,再检测耳机类型,检测走的路线还是通过 PMIC 的 accdet 内部中断。
    摘自 FAQ13724

【驱动代码流程】

“//Accdet_drv.c (mediatek\kernel\drivers\accdet)
module_init(accdet_mod_init);
platform_driver_register(&accdet_driver);
        // static struct platform_driver accdet_driver = {
        // .probe = accdet_probe,
        // //.suspend = accdet_suspend,
        // //.resume = accdet_resume,
        // .remove = accdet_remove,
        // .driver = {
        // .name = “Accdet_Driver”,
        // #ifdef CONFIG_PM
        // .pm = &accdet_pm_ops,
        // #endif
        // },

//////////////////////////////////////////////////////////////////
// 匹配后执行
accdet_probe(struct platform_device *dev)

//////////////////////////////////////////////////////////////////////
// Accdet.c ediatek\platform\mt6582\kernel\drivers\accdet)
mt_accdet_probe();

/////////////////////////////////////////////////////////////////////
// 0. 设置长按判断的时长
press_key_time = get_headset_key_custom_setting();
/////////////////////////////////////////////////////////////////////
// 1,注册一个 switch 设备, /sys/class/swithc/h2w/state
主要是供安卓层调用,判断耳机状态
accdet_data.name = “h2w”;
accdet_data.index = 0;
accdet_data.state = NO_DEVICE;
// 获得耳机的 micbias 的 PWM 波形,这个波形用来采样,可以节约功耗
cust_headset_settings = get_cust_headset_settings();
// 注册一个 switch 设备,表示耳机状态
ret = switch_dev_register(&accdet_data);
/////////////////////////////////////////////////////////////////////
// 2. 创建一个字符设备节点
ret = alloc_chrdev_region(&accdet_devno, 0, 1, CCDET_DEVNAME);
accdet_cdev = cdev_alloc();
accdet_cdev->owner = THIS_MODULE;
accdet_cdev->ops = accdet_get_fops();
ret = cdev_add(accdet_cdev, accdet_devno, 1);
/////////////////////////////////////////////////////////////////////
// 3. 创建 /sys 目录下的文件节点
accdet_class = class_create(THIS_MODULE, ACCDET_DEVNAME);
// if we want auto creat device node, we must call this
accdet_nor_device = device_create(accdet_class, NULL, accdet_devno, NULL, ACCDET_DEVNAME);
/////////////////////////////////////////////////////////////////////
// 4. 创建一个 input 输入设备, 用于上报耳机按键事件,创建一个定时器
// 每 6s 自动关闭 micbias,达到省电目的。同时设置 input 输入设备上
// 报的键值类型,并注册输入设备。
kpd_accdet_dev = input_allocate_device();
// 通过定时器每 6s 自动关闭 MICBIAS,达到省电目的,因为中断会唤醒使能 micbias 检测耳机类型与 mic 及按键,如果没有 mic, 且不需要检测按键,则可以直接关闭 micbias 偏置
init_timer(&micbias_timer);
micbias_timer.expires = jiffies + MICBIAS_DISABLE_TIMER;
micbias_timer.function = &disable_micbias;
//define multi-key keycode
// 设置 input 输入设备上报的键值类型
__set_bit(EV_KEY, kpd_accdet_dev->evbit);
__set_bit(KEY_CALL, kpd_accdet_dev->keybit);
。。。
// 注册 input 输入设备
input_register_device(kpd_accdet_dev)
/////////////////////////////////////////////////////////////////////
// 5. 注册工作队列,用于处理 ACCDET 模块识别按键流程 , 他会根据 PMIC 的状态,判断是否有耳机插入,及耳机类型和按键类型,如果有按键,通过 input 上报处理完后,同步更新 switch 模块的状态
accdet_workqueue = create_singlethread_workqueue(“accdet”);
INIT_WORK(&accdet_work, accdet_work_callback);
/////////////////////////////////////////////////////////////////////
// 6. 创建一个按键上报线程,用于按键上报
init_waitqueue_head(&send_event_wq);
//start send key event thread
keyEvent_thread = kthread_run(sendKeyEvent, 0, “keyEvent_send”);
/////////////////////////////////////////////////////////////////////
// 7. 针对第一次启动,初始化 accdet 模块硬件,及注册 ap 的耳机中断函数,在 ap 耳机中断函数中
     0. 变更耳机中断电平,保证插入/拔出都有中断
    1. 如果是耳机插入,则创建一个定时器,用于耳机插入 6s 后,检测耳机是否有 mic 及按键,没有则关闭 micbias。
    2. 调用 accdet_eint_work_callback() 函数,用于打开/关闭 accdet 模块。
if (g_accdet_first == 1)
。。。

【相关源码】

一如既往,需要分析的同志可以下载注释的原码分析,地址如下:
链接: http://pan.baidu.com/s/1c1Fhg3I 密码: mvkx
觉得有帮助请点赞[笑脸]

2 0