mtk耳机调试

时间:2024-03-05 18:10:34
一.耳机的基本知识
    1.手机全部使用了标准的3.5mm接口,对于一款采用3段式3.5mm接口的耳机来说是不存在兼容问题了,但采用四段式的线控耳机仍旧是有不兼容情况。常见的三段式接口叫做TRS端子,四段式为TRRS端子
            
 
   2. 智能手机所使用四段式的3.5mm TRRS端子是有两种接口定义标准的,OMTP和CTIA,OMTP就是我们俗称的国家标准,CTIA是国际标准,两种标准在接口前两段的定义都是相同的。最新的手机基本都使用了CTIA标准。
    
 
    3. 三段式的TRS端子的定义,从上到下依次是左声道、右声道和接地,这也就是为什么它能兼容任何手机的原因了。
     
 
    4.线控结构,其实原理也很简单,耳机接口上用于输入信号的只有麦克风正极了,既然多键线控耳机一样是使用4段式的接口,那么线控的命令一定也是通过这里输入手机
    
        市面上常见的线控类型大致有这几种,音量滑块带麦线控、单键带麦和多键带麦,通过音量滑块改变音量原理很简单,只要在电路当中串入可变电阻即可实现。采用多按键的就比较复杂了,但依旧是通过改变电阻来实现的,从原理电路图上不难看出,不同的按键下串入了不同的电阻,当按键被按下后不同的电阻被接入到了回路当中,麦克风正极接收到的信号也随之发生改变,借此手机可以来识别用户按下的是哪个按键,应该执行何种操作。
 
 
二.MTK平台耳机的检测方式
   1.Accdet only

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


 2.Accdet+EINT方式
        此方式在耳机为插入时,micbias是被disable的。利用中断EINT来打开micbias`,从而达到省功耗和减小杂音的效果的。待插入后,耳机检测走的路线还是accdet内部中断。
 
 

三.Accdet检测pin内部比较器
电压范围说明
    mt6589/72:
– Plug out state: 1.77V Voltage 1.9V (A=1, B=1);
– Mic Bias state: 0.5V Voltage<1.77V (A=0, B=1);
– Hook Switch state: 0V Voltage < 0.5V (A=0, B=0).
 
其中Hook switch multi-key电压分布:
        0v<=MD<0.09V<=UP<0.24V<=DW<0.5V
内部通过adc读取电压值,
MD:middle key
UP: up key
DW:down key
 

另外一种:看芯片手册(pmu)或者驱动

               MD                 UP                   DW
|--------------------|---------------|---------------|
0V<=MD< 0.08V<= UP<0.22V<=DW <0.5V
 
耳机按键的电阻值推荐如下:
Middle Key:0欧
Up Key:220欧
Down Key:600欧
    ADC读取的耳机按键电压是根据基准电压1.9V来输出,就算MICBIAS电压调整到2.7V,PMIC ADC芯片内部会根据读取到的电压转换基准电压后输出一个值。
     这就解释了为什么MICBIAS电压调整后,耳机按键检测的电压范围不改变的原因。
 


四.
ACCDET模块耳机检测的原理
       ACCDET内部有两个比较器,会根据传入的电压判断并产生中断。ACCDET的输入电压即耳机 MIC PIN 的电压,内部比较器的输出分别对应A/B两个寄存器。
     ACCDET内部两个比较器的Vref分别是1.77V和0.5V(硬件决定的,不能修改),所以,对应的电压有 3个范围: 
           1.77V-1.9V: 未插入耳机的状态(AB=B11) 
            0.5V-1.77V: 插入4段式(有Mic)耳机时的状态(AB = B01) 
            0-0.5V : 插入3段式耳机时的状态,   或者4段式按键按下时的状态(AB = B00)
    耳机的状态会保存到ACCDET的寄存器中,当电压在任意2个范围间切换时,状态发生变化,ACCDET产生 中断,中断处理中读取状态寄存器的值,并根据状态的变化做相应的处理.
    如果电压调整到2.5或者其他.各段会按照比例变化。



五.
调整耳机MICBIAS电压的方法
    修改文件
     alps\kernel-3.10\drivers\misc\mediatek\mach\$platform\$project\accdet\accdet_custom_def.h
 
修改下面的宏:
#define ACCDET_HIGH_VOL_MODE
#ifdef ACCDET_HIGH_VOL_MODE
#define ACCDET_MIC_VOL 7 //2.7v
#else
#define ACCDET_MIC_VOL 2 //1.9v
#endif
 
 其中数字表示的电压如下:
MIC Bias 0 Output voltage selection
0: 1.7V
1: 1.8V
2: 1.9V
3: 2.0V
4: 2.1V
5: 2.3V
6: 2.5V
7: 2.7V
 
六.驱动分析
    驱动入口:
accdet_mod_init:  Accdet_drv.c (kernel-3.10\drivers\misc\mediatek\accdet)
     platform_driver_register(&accdet_driver); //调用accdet_probe函数
           accdet_probe
                 mt_accdet_probe(); //调用的这个函数在Accdet.c (kernel-3.10\drivers\misc\mediatek\accdet\mt6735)
                        press_key_time = get_headset_key_custom_setting(); //得到长按的时间:在Accdet_custom.c (kernel-3.10\drivers\misc\mediatek\mach\mt6735\lentk6753_65c_l1\accdet)中
                        switch_dev_register(&accdet_data); //创建sysfs接口
                        cdev_add(accdet_cdev, accdet_devno, 1); //添加字符设备
                        init_timer(&micbias_timer);  //定时器用于插入三段式耳机后关闭micbias,因为不需要录音
                        input_register_device(kpd_accdet_dev) //注册input子系统用于耳机按键上报
                        INIT_WORK(&accdet_work, accdet_work_callback); //accdet_work的工作队列
                        pmic_register_interrupt_callback(12,accdet_int_handler); //设置中断的调用函数
                pmic_register_interrupt_callback(13,accdet_eint_int_handler);
                        accdet_init(); //初始化accdet,这个pmu中的寄存器
                        queue_work(accdet_workqueue, &accdet_work); //schedule a work for the first detection ,第一次检测
                        INIT_WORK(&accdet_disable_work, disable_micbias_callback); //初始化micbias的工作队列
                        INIT_WORK(&accdet_eint_work, accdet_eint_work_callback); //accdet中断的工作队列
                        INIT_WORK(&sendkey_eint_work, sendkey_eint_work_callback); //自定义的sendkey工作队列
                        accdet_setup_eint //初始化中断
                             mt65xx_eint_registration(, accdet_eint_func, 0);中断处理函数为accdet_eint_func
到这里初始化完成了
 
 
执行第一次检测:比如耳机插入后开机这种情况
 queue_work(accdet_workqueue, &accdet_work);
       accdet_work_callback
            check_cable_type //检测耳机的状态,就是是不是一上电已经插入了
            switch_set_state((struct switch_dev *)&accdet_data, cable_type); //如果已经插入就上报
                  kobject_uevent_env //填充上报环境变量
                  kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE); //上报,发送改变
    
 
 
当开机后插入耳机时,int中断产生
accdet_eint_func
     if(cur_eint_state ==  EINT_PIN_PLUG_IN ) //如果已经插入了,现在就是拔出
     cur_eint_state = EINT_PIN_PLUG_IN; //没有插入,就设置为插入状态
     queue_work(accdet_eint_workqueue, &accdet_eint_work); //调用accdet_eint_work工作队列
           accdet_eint_work_callback //调用相应函数
                eint_accdet_sync_flag = 1; //设置为1
                accdet_init();// do set pwm_idle on in accdet_init,初始化accdet
                enable_accdet(ACCDET_SWCTRL_EN); //启动accdet
                //Turn on micbias always
pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width);  //打开micbias ,公司定义的
            pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width);//公司定义的
sendkey_setup_eint(); //sendkey中断注册,公司定义的
                
 
检测按键
        当按下按键accdet检测到电压区域变化: 通过pmu的中断,pm会调用设置callback函数,分别是pmu的中断12和中断13
pmic_register_interrupt_callback(12,accdet_int_handler); //设置中断的调用函数
pmic_register_interrupt_callback(13,accdet_eint_int_handler);
 
accdet_int_handler和 accdet_eint_int_handler都调用accdet_irq_handler
 
accdet_irq_handler
     accdet_get_current_time //得到现在的时间
     clear_accdet_interrupt(); //清中断
     accdet_workqueue_func
         queue_work(accdet_workqueue, &accdet_work); //执行函数为accdet_work_callback
              accdet_work_callback
                    check_cable_type(); //
                         current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0)>>6) //得到现在的状态, 包括按键检测,三段式耳机检测等
                    if(1 == eint_accdet_sync_flag) {  switch_set_state((struct switch_dev *)&accdet_data, cable_type); /、
 
 
 
 
七.在kernel层实现sendkey的长按,双击,单击上报:accdet.c
    附件中用
        #ifdef RUNBO_CUST_HEADSET
        #endif
   包含的代码是用于实现这个功能
                                            
 
注意:mic的mode很重要,有没有接电容可能导致mic无声,还有五六脚一定要接地。mic的P端的电压一般在0.7,N端接地。