MTK6797 Accdet驱动分析总结

6735平台上耳机配置

  (2016-07-05 19:57:29)
标签: 

一牛网

 

mt6735

 

mtk

 
6735平台上耳机相关的宏有下面三个:
Audio define@
alps\vendor\mediatek\proprietary\custom\${project_name}\hal\audioflinger\audio\audio_custom_exp.h
#define HEADSET_MIC_MODE (1)………………………….For Headset Mic


Accdet define@
alps\kernel-3.10\drivers\misc\mediatek\mach\mt6735\${project_name}\accdet\accdet_custom_def.h
#define ACCDET_MIC_MODE (1) 
#define ACCDET_EINT


Audio Speech部分参考设计有修改:
1.外部EINT怎么配置:看三颗电阻--R11/ R12/ R13
6735平台上耳机配置  


 
   ACCDET as EINT    


    Use AP EINT     

  HW design   
  R13:47K ohm
  R11:NC
  R12:NC
  R13:NC
  R11:470K ohm
  R12:47K ohm

  SW Setting

  //#define ACCDET_EINT         



#define ACCDET_EINT          

请注意:ACC Mode不可以用ACCDET as EINT,只能使用AP EINT。

2. ACC Mode还是 DCC Mode? == > 看AU_VIN1_P和AU_VIN1_N两个Pin上是否有接隔直电容?
    有     ==> ACC Mode : ACCDET_MIC_MODE = 1
    没有  ==> DCC Mode : ACCDET_MIC_MODE = 2 或者 6

3. DCC Mode下 ACCDET_MIC_MODE 设 2还是设 6? == > 看 AU_MICBIAS1 上的 R10(2.5K ohm)是否有贴(如下图红框部分)?




Headset]如何在ADB shell中读取耳机状态和读取ACCDET寄存器

SandForm  SandForm  2016-07-18 16:35:19

  592人阅读  评论(2)  收藏  举报
  分类:

目录(?)[+]

MTK6797 Accdet驱动分析总结

一、相关概念介绍

1、EINT+ACCDET检测中断

        EINT中断:主要用来检测耳机的插入和拔出,即plug in 和plug out

        ACCDET中断:主要用来检测耳机的事件类型,包括PLUG_OUT、PLUG_IN、MIC_BIAS(耳机上的mic)和HOOK_SWITCH(耳机按键)

        a、采用AP端的中断作为EINT,(3 steps:a0 a1 a2)

               a0、如果采用此方式,需要打开宏

               CONFIG_ACCDET_EINT=y

               # CONFIG_ACCDET_EINT_IRQ is not set

                a1、also config the dws for eint

                a2、meanwhile reconfig the gpio in the dts

                                                                   

        b、采用PMIC的中断作为EINT,

               如果采用此方式,需要打开宏(only)

              CONFIG_ACCDET_EINT_IRQ =y

              #CONFGI_ACCDET_EINT is not set

2、耳机按键的检测

       耳机按键的原理图如下:



          PMIC有内部ADC通道可以读取不同的耳机电压,其中不同事件类型对应的电压如下:

        plug out:1.77<=voltage<=1.9

        mic bias:0.5v<=voltage<1.77v

        hook switch:0v<=voltage<=0.5v

        如上三个状态是通过ACCDET_STATE_RG寄存器获取的,通过2个bit A=bit1、B=bit0判断,对应如上的事件如下:

       plug out:1.77<=voltage<=1.9                 A=1,B=1,AB=3,

        mic bias:0.5v<=voltage<1.77v              A=0,B=1,AB=1,

        hook switch:0v<=voltage<=0.5v           A=0,B=0,AB=0,

       其中hook switch包括了up、middle、down三个按键,对应的电压如下;

        0v<=middle<=0.09v<=up<=0.24v<=down<=0.5v


二、耳机插入流程分析

          当插入耳机按键时,首先是触发了EINT中断,然后再触发ACCDET中断,这2个中断都是PMIC函数中注册的,属于PMIC端的中断。

          在probe初始化函数中注册了之前提到的两个中断函数,此为中断上半部分:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. pmic_register_interrupt_callback(12, accdet_int_handler );  
  2. pmic_register_interrupt_callback(13, accdet_eint_int_handler );  

        然后又初始化了两个工作队列accdet_work和accdet_eint_work,对应如上两个中断的下半部分。


1、总的大体流程如下,具体的耳机事件插拔检测在下一副流程图会介绍,

        

 

2、这里主要介绍两种耳机模式:MIC_BIAS和HOOK SWITCH

      a、MIC_BIAS模式,即插入耳机后的默认模式,状态从PLUG_OUT----->MIC_BIAS,主要代码如下

         

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. case PLUG_OUT:  
  2. #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION  
  3.         pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1);  
  4. #endif  
  5.         if (current_status == 0) {  
  6. #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION  
  7.             /*micbias always on during detected PIN recognition*/  
  8.             pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width);  
  9.             pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width);  
  10.             ACCDET_DEBUG("[Accdet]PIN recognition micbias always on!\n");  
  11.             ACCDET_DEBUG("[Accdet]before adc read, pin_adc_value = %d mv!\n", pin_adc_value);  
  12.             msleep(500);  
  13.             current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0) >> 6);    /*A=bit1; B=bit0*/  
  14.             if (current_status == 0 && show_icon_delay != 0) {  
  15.                 /*accdet_auxadc_switch(1);switch on when need to use auxadc read voltage*/  
  16.                 pin_adc_value = Accdet_PMIC_IMM_GetOneChannelValue(1);  
  17.                 ACCDET_DEBUG("[Accdet]pin_adc_value = %d mv!\n", pin_adc_value);  
  18.                 /*accdet_auxadc_switch(0);*/  
  19.                 if (180 > pin_adc_value && pin_adc_value > 90) {  /*90mv   ilegal headset*/  
  20.                     /*mt_set_gpio_out(GPIO_CAMERA_2_CMRST_PIN, GPIO_OUT_ONE);*/  
  21.                     /*ACCDET_DEBUG("[Accdet]PIN recognition change GPIO_OUT!\n");*/  
  22.                     mutex_lock(&accdet_eint_irq_sync_mutex);  
  23.                     if (1 == eint_accdet_sync_flag) {  
  24.                         cable_type = HEADSET_NO_MIC;  
  25.                         accdet_status = HOOK_SWITCH;  
  26.                         cable_pin_recognition = 1;  
  27.                         ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n",  
  28.                                  cable_pin_recognition);  
  29.                     } else {  
  30.                         ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  31.                     }  
  32.                     mutex_unlock(&accdet_eint_irq_sync_mutex);  
  33.                 } else {  
  34.                     mutex_lock(&accdet_eint_irq_sync_mutex);  
  35.                     if (1 == eint_accdet_sync_flag) {  
  36.                         cable_type = HEADSET_NO_MIC;  
  37.                         accdet_status = HOOK_SWITCH;  
  38.                     } else {  
  39.                         ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  40.                     }  
  41.                     mutex_unlock(&accdet_eint_irq_sync_mutex);  
  42.                 }  
  43.             }  
  44. #else  
  45.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  46.             if (1 == eint_accdet_sync_flag) {  
  47.                 cable_type = HEADSET_NO_MIC;  
  48.                 accdet_status = HOOK_SWITCH;  
  49.             } else {  
  50.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  51.             }  
  52.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  53. #endif  
  54.         } else if (current_status == 1) {  
  55.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  56.             if (1 == eint_accdet_sync_flag) {  
  57.                 accdet_status = MIC_BIAS;  
  58.                 cable_type = HEADSET_MIC;  
  59. #ifdef CONFIG_HEADSET_SUPPORT_FIVE_POLE  
  60.                 msleep(20);  
  61.                 if (pmic_pwrap_read(0x0F46) & 0x01) {  
  62.                     /*check 5 pole headset*/  
  63.                     ACCDET_DEBUG("[Accdet]check 5 pole headset: YES\n");  
  64.                     cable_type = HEADSET_FIVE_POLE;  
  65.                 }  
  66. #endif  
  67.                 /*AB=11 debounce=30ms*/  
  68.                 pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3 * 30);  
  69.             } else {  
  70.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  71.             }  
  72.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  73.             pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce);  
  74.             /*recover polling set AB 00-01*/  
  75. #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION  
  76.             pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));  
  77.             pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));  
  78. #endif  
  79.         } else if (current_status == 3) {  
  80.             ACCDET_DEBUG("[Accdet]PLUG_OUT state not change!\n");  
  81. #ifdef CONFIG_ACCDET_EINT  
  82.             ACCDET_DEBUG("[Accdet] do not send plug out event in plug out\n");  
  83. #else  
  84.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  85.             if (1 == eint_accdet_sync_flag) {  
  86.                 accdet_status = PLUG_OUT;  
  87.                 cable_type = NO_DEVICE;  
  88.             } else {  
  89.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  90.             }  
  91.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  92. #endif  
  93.         } else {  
  94.             ACCDET_DEBUG("[Accdet]PLUG_OUT can't change to this state!\n");  
  95.         }  
  96.         break;  

        b、HOOK_SWITCH模式,即耳机按键按下的状态,状态从MIC_BIAS----->HOOK_SWITCH,按键松开时HOOK_SWITCH----->MIC_BIAS,主要代码如下:
[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. case MIC_BIAS:  
  2.         /*solution: resume hook switch debounce time*/  
  3.         pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0);  
  4.   
  5.         if (current_status == 0) {  
  6.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  7.             if (1 == eint_accdet_sync_flag) {  
  8.                 while ((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT)  
  9.                     && (wait_clear_irq_times < 3)) {  
  10.                     ACCDET_DEBUG("[Accdet]check_cable_type: MIC BIAS clear IRQ on-going1....\n");  
  11.                     wait_clear_irq_times++;  
  12.                     msleep(20);  
  13.                 }  
  14.                 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS);  
  15.                 irq_temp = irq_temp & (~IRQ_CLR_BIT);  
  16.                 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp);  
  17.                 IRQ_CLR_FLAG = true;  
  18.                 accdet_status = HOOK_SWITCH;  
  19.             } else {  
  20.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  21.             }  
  22.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  23.             button_status = 1;  
  24.             if (button_status) {  
  25.                 mutex_lock(&accdet_eint_irq_sync_mutex);  
  26.                 if (1 == eint_accdet_sync_flag)  
  27.                     multi_key_detection(current_status);  
  28.                 else  
  29.                     ACCDET_DEBUG("[Accdet] multi_key_detection: Headset has plugged out\n");  
  30.                 mutex_unlock(&accdet_eint_irq_sync_mutex);  
  31.                 /*accdet_auxadc_switch(0);*/  
  32.                 /*recover  pwm frequency and duty*/  
  33.                 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));  
  34.                 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));  
  35.             }  
  36.         } else if (current_status == 1) {  
  37.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  38.             if (1 == eint_accdet_sync_flag) {  
  39.                 accdet_status = MIC_BIAS;  
  40.                 cable_type = HEADSET_MIC;  
  41.                 ACCDET_DEBUG("[Accdet]MIC_BIAS state not change!\n");  
  42.             } else {  
  43.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  44.             }  
  45.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  46.         } else if (current_status == 3) {  
  47. #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ  
  48.             ACCDET_DEBUG("[Accdet]do not send plug ou in micbiast\n");  
  49.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  50.             if (1 == eint_accdet_sync_flag)  
  51.                 accdet_status = PLUG_OUT;  
  52.             else  
  53.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  54.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  55. #else  
  56.             mutex_lock(&accdet_eint_irq_sync_mutex);  
  57.             if (1 == eint_accdet_sync_flag) {  
  58.                 accdet_status = PLUG_OUT;  
  59.                 cable_type = NO_DEVICE;  
  60.             } else {  
  61.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");  
  62.             }  
  63.             mutex_unlock(&accdet_eint_irq_sync_mutex);  
  64. #endif  
  65.         } else {  
  66.             ACCDET_DEBUG("[Accdet]MIC_BIAS can't change to this state!\n");  
  67.         }  
  68.         break;  
  69. case HOOK_SWITCH: //按键松开后  
  70.         if (current_status == 0) {   
  71.             mutex_lock(&accdet_eint_irq_sync_mutex);   
  72.             if (1 == eint_accdet_sync_flag) {   
  73.                 /*for avoid 01->00 framework of Headset will report press key info for Audio*/   
  74.                 /*cable_type = HEADSET_NO_MIC;*/   
  75.                 /*accdet_status = HOOK_SWITCH;*/   
  76.                 ACCDET_DEBUG("[Accdet]HOOK_SWITCH state not change!\n");   
  77.             } else {   
  78.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");   
  79.             }   
  80.             mutex_unlock(&accdet_eint_irq_sync_mutex);   
  81.         } else if (current_status == 1) {   
  82.             mutex_lock(&accdet_eint_irq_sync_mutex);   
  83.             if (1 == eint_accdet_sync_flag) {   
  84.                 multi_key_detection(current_status);   
  85.                 accdet_status = MIC_BIAS;   
  86.                 cable_type = HEADSET_MIC;   
  87.             } else {   
  88.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");   
  89.             }   
  90.             mutex_unlock(&accdet_eint_irq_sync_mutex);   
  91.             /*accdet_auxadc_switch(0);*/   
  92. #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION   
  93.             cable_pin_recognition = 0;   
  94.             ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition);   
  95.             pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));   
  96.             pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));   
  97. #endif   
  98.             /*solution: reduce hook switch debounce time to 0x400*/   
  99.             pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce);   
  100.         } else if (current_status == 3) {   
  101.    
  102. #ifdef CONFIG_ACCDET_PIN_RECOGNIZATION   
  103.             cable_pin_recognition = 0;   
  104.             ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition);   
  105.             mutex_lock(&accdet_eint_irq_sync_mutex);   
  106.             if (1 == eint_accdet_sync_flag)   
  107.                 accdet_status = PLUG_OUT;   
  108.             else   
  109.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");   
  110.             mutex_unlock(&accdet_eint_irq_sync_mutex);   
  111. #endif   
  112. #if defined CONFIG_ACCDET_EINT || defined CONFIG_ACCDET_EINT_IRQ   
  113.             ACCDET_DEBUG("[Accdet] do not send plug out event in hook switch\n");   
  114.             mutex_lock(&accdet_eint_irq_sync_mutex);   
  115.             if (1 == eint_accdet_sync_flag)   
  116.                 accdet_status = PLUG_OUT;   
  117.             else   
  118.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");   
  119.             mutex_unlock(&accdet_eint_irq_sync_mutex);   
  120. #else   
  121.             mutex_lock(&accdet_eint_irq_sync_mutex);   
  122.             if (1 == eint_accdet_sync_flag) {   
  123.                 accdet_status = PLUG_OUT;   
  124.                 cable_type = NO_DEVICE;   
  125.             } else {   
  126.                 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");   
  127.             }   
  128.             mutex_unlock(&accdet_eint_irq_sync_mutex);   
  129. #endif   
  130.         } else {   
  131.             ACCDET_DEBUG("[Accdet]HOOK_SWITCH can't change to this state!\n");   
  132.         }   
  133.         break;   

      代码对应的耳机按键处理流程如下:


三、总结

            耳机按键处理主要依靠2个中断EINT+ACCDET,然后按键检测依靠内部ADC检测,上报按键事件时,按下和松开都要通过send_key_event进行上报。

  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值