rk29phonesdk:耳机驱动修改并测试可用
author邱建斌 <qjb@rock-chips.com>
Fri, 8 Apr 2011 03:29:41 +0000 (11:29 +0800)
committer邱建斌 <qjb@rock-chips.com>
Fri, 8 Apr 2011 03:29:41 +0000 (11:29 +0800)
arch/arm/mach-rk29/board-rk29-phonesdk.c
drivers/headset_observe/rk2818_headset.c [changed mode: 0644->0755]
drivers/headset_observe/rk2818_headset.h [changed mode: 0644->0755]

index ed0aa689842b733d946b417b778463dd60a62f88..3f49da2b2e305f94c339249c3e4f974468347804 100755 (executable)
@@ -61,7 +61,7 @@
 #include <linux/mtk23d.h>
 #endif
 
-
+#include "../../../drivers/headset_observe/rk2818_headset.h"
 /*set touchscreen different type header*/
 #if defined(CONFIG_TOUCHSCREEN_XPT2046_NORMAL_SPI)
 #include "../../../drivers/input/touchscreen/xpt2046_ts.h"
@@ -1383,6 +1383,23 @@ struct wm8994_pdata wm8994_platdata = {
 };
 #endif 
 
+#ifdef CONFIG_HEADSET_DET
+#define HEADSET_GPIO RK29_PIN4_PD2
+struct rk2818_headset_data rk2818_headset_info = {
+       .gpio           = HEADSET_GPIO,
+       .irq_type       = IRQF_TRIGGER_RISING,//IRQF_TRIGGER_RISING -- ÉÏÉýÑØ   IRQF_TRIGGER_FALLING -- Ï½µÑØ
+       .headset_in_type= HEADSET_IN_HIGH,
+};
+
+struct platform_device rk28_device_headset = {
+               .name   = "rk2818_headsetdet",
+               .id     = 0,
+               .dev    = {
+                   .platform_data = &rk2818_headset_info,
+               }
+};
+#endif
+
 /*****************************************************************************************
  * i2c devices
  * author: kfx@rock-chips.com
@@ -2571,6 +2588,9 @@ static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_VIDEO_RK29XX_VOUT
        &rk29_v4l2_output_devce,
 #endif
+#ifdef CONFIG_HEADSET_DET
+    &rk28_device_headset,
+#endif
 };
 
 #ifdef CONFIG_RK29_VMAC
old mode 100644 (file)
new mode 100755 (executable)
index d7bdecd..f0e7133
 #include <asm/atomic.h>
 #include <asm/mach-types.h>
 #include "rk2818_headset.h"
+#include <linux/earlysuspend.h>
 
 /* Debug */
-#if 0
-#define DBG(x...) printk(KERN_INFO x)
+#if 1
+#define DBG(x...) printk(x)
 #else
 #define DBG(x...) do { } while (0)
 #endif
 
-/* ¶ú»ú״̬ */
-#define BIT_HEADSET             (1 << 0)//´øMICµÄ¶ú»ú
-#define BIT_HEADSET_NO_MIC      (1 << 1)//²»´øMICµÄ¶ú»ú
+#define BIT_HEADSET             (1 << 0)
+#define BIT_HEADSET_NO_MIC      (1 << 1)
 
 struct rk2818_headset_dev{
        struct switch_dev sdev;
@@ -56,75 +56,135 @@ struct rk2818_headset_dev{
 };
 
 static struct rk2818_headset_dev Headset_dev;
-static struct work_struct g_headsetobserve_work;
+static struct delayed_work g_headsetobserve_work;
 static struct rk2818_headset_data *prk2818_headset_info;
-static irqreturn_t headset_interrupt(int irq, void *dev_id);
-unsigned int headset_irq_type;
+#if defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_BENGO) || defined(CONFIG_MACH_Z5) || defined(CONFIG_MACH_Z5_V2) || defined(CONFIG_MACH_A22)
+extern void detect_HSMic(void);
+#endif
 
 int headset_status(void)
 {          
-    if(Headset_dev.cur_headset_status & BIT_HEADSET)                   
-        return 1;          
-    else                      
-        return 0;
+       if(Headset_dev.cur_headset_status & BIT_HEADSET)                        
+               return 1;
+       else
+               return 0;
 }
 
 EXPORT_SYMBOL_GPL(headset_status);
 
-static void headsetobserve_work(void)
+static irqreturn_t headset_interrupt(int irq, void *dev_id)
 {
-       if(gpio_get_value(prk2818_headset_info->irq)){
-               if(prk2818_headset_info->headset_in_type)
-                       {DBG("headset in-----cjq------/n");Headset_dev.cur_headset_status = BIT_HEADSET;}
-               else
-                       Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+       DBG("---headset_interrupt---\n");       
+       schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(20));
+       return IRQ_HANDLED;
+}
 
-               if(headset_irq_type != (IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING))
-                       headset_irq_type = IRQF_TRIGGER_FALLING;
+static int headset_change_irqtype(unsigned int irq_type)
+{
+       int ret = 0;
+       DBG("--------%s----------",__FUNCTION__);
+       free_irq(prk2818_headset_info->irq,NULL);
+       
+       ret = request_irq(prk2818_headset_info->irq, headset_interrupt, irq_type, NULL, NULL);
+       if (ret) 
+       {
+               DBG("headsetobserve: request irq failed\n");
+        return ret;
        }
-       else{
-               if(prk2818_headset_info->headset_in_type)
-                       {DBG("headset out-----cjq------/n");Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);}
-               else
-                       Headset_dev.cur_headset_status = BIT_HEADSET;
+       return ret;
+}
+
+static void headsetobserve_work(struct work_struct *work)
+{
+       int i,level = 0;
 
-               if(headset_irq_type != (IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING))
-                       headset_irq_type = IRQF_TRIGGER_RISING; 
+       DBG("---headsetobserve_work---\n");
+       mutex_lock(&Headset_dev.mutex_lock);
+
+       for(i=0; i<3; i++)
+       {
+               level = gpio_get_value(prk2818_headset_info->gpio);
+               if(level < 0)
+               {
+                       printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,prk2818_headset_info->irq,i);
+                       msleep(1);
+                       continue;
+               }
+               else
+               break;
+       }
+       if(level < 0)
+       {
+               printk("%s:get pin level  err!\n",__FUNCTION__);
+               return;
+       }
+       
+       switch(prk2818_headset_info->headset_in_type)
+       {
+               case HEADSET_IN_HIGH:
+                       if(level > 0)
+                       {//插入--高电平
+                               DBG("---headset in---\n");
+                               Headset_dev.cur_headset_status = BIT_HEADSET;
+                               headset_change_irqtype(IRQF_TRIGGER_FALLING);//设置为下降沿
+                       }
+                       else if(level == 0)
+                       {//拔出--低电平
+                               DBG("---headset out---\n");             
+                               Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+                               headset_change_irqtype(IRQF_TRIGGER_RISING);//设置为上升沿
+                       }
+                       break;
+               case HEADSET_IN_LOW:
+                       if(level == 0)
+                       {//插入--低电平
+                               DBG("---headset in---\n");
+                               Headset_dev.cur_headset_status = BIT_HEADSET;
+                               headset_change_irqtype(IRQF_TRIGGER_RISING);///设置为上升沿
+                       }
+                       else if(level > 0)
+                       {//拔出--高电平
+                               DBG("---headset out---\n");             
+                               Headset_dev.cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC);
+                               headset_change_irqtype(IRQF_TRIGGER_FALLING);//设置为下降沿
+                       }
+                       break;                  
+               default:
+                       DBG("---- ERROR: on headset headset_in_type error -----\n");
+                       break;                  
        }
 
        if(Headset_dev.cur_headset_status != Headset_dev.pre_headset_status)
        {
-               Headset_dev.pre_headset_status = Headset_dev.cur_headset_status;
-               mutex_lock(&Headset_dev.mutex_lock);
-               switch_set_state(&Headset_dev.sdev, Headset_dev.cur_headset_status);
-               mutex_unlock(&Headset_dev.mutex_lock);
-               DBG("---------------cur_headset_status = [0x%x]\n", Headset_dev.cur_headset_status);
+               Headset_dev.pre_headset_status = Headset_dev.cur_headset_status;                                        
+               switch_set_state(&Headset_dev.sdev, Headset_dev.cur_headset_status);    
+               DBG("Headset_dev.cur_headset_status = %d\n",Headset_dev.cur_headset_status);
+#if defined(CONFIG_MACH_BENGO_V2) || defined(CONFIG_MACH_BENGO) || defined(CONFIG_MACH_Z5) || defined(CONFIG_MACH_Z5_V2) || defined(CONFIG_MACH_A22)
+               detect_HSMic();
+#endif
        }
-
-       if(headset_irq_type == (IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING))return;
-
-       free_irq(prk2818_headset_info->irq,NULL);
-       if (request_irq(prk2818_headset_info->irq, headset_interrupt, headset_irq_type, NULL, NULL))
-               DBG("headsetobserve: request irq failed\n");
+       mutex_unlock(&Headset_dev.mutex_lock);  
 }
 
-static irqreturn_t headset_interrupt(int irq, void *dev_id)
+static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
 {
-       schedule_work(&g_headsetobserve_work);
-       DBG("---------------headset_interrupt---------------\n");
-       
-       return IRQ_HANDLED;
+       return sprintf(buf, "Headset\n");
 }
 
-static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void headset_early_resume(struct early_suspend *h)
 {
-       return sprintf(buf, "Headset\n");
+       schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(10));
+       //DBG(">>>>>headset_early_resume\n");
 }
 
+static struct early_suspend hs_early_suspend;
+#endif
+
 static int rockchip_headsetobserve_probe(struct platform_device *pdev)
 {
        int ret;
-       
+
        DBG("RockChip headset observe driver\n");
        prk2818_headset_info = pdev->dev.platform_data;
        
@@ -136,26 +196,39 @@ static int rockchip_headsetobserve_probe(struct platform_device *pdev)
 
        ret = switch_dev_register(&Headset_dev.sdev);
        if (ret < 0)
-               return 0;
+               return ret;
 
-       INIT_WORK(&g_headsetobserve_work, headsetobserve_work);
+       INIT_DELAYED_WORK(&g_headsetobserve_work, headsetobserve_work);
     
-       ret = gpio_request(prk2818_headset_info->irq, "headset_det");
-       if (ret) {
-               DBG( "headsetobserve: failed to request FPGA_PIO0_00\n");
+       ret = gpio_request(prk2818_headset_info->gpio, "headset_det");
+       if (ret) 
+       {
+               DBG("headsetobserve: request gpio_request failed\n");
                return ret;
        }
-
-       gpio_direction_input(prk2818_headset_info->irq);
-
-       prk2818_headset_info->irq = gpio_to_irq(prk2818_headset_info->irq);
-       headset_irq_type = prk2818_headset_info->irq_type;
-       ret = request_irq(prk2818_headset_info->irq, headset_interrupt, headset_irq_type, NULL, NULL);
-       if (ret ) {
+       gpio_pull_updown(prk2818_headset_info->gpio, GPIONormal);//不上拉也不下拉
+       gpio_direction_input(prk2818_headset_info->gpio);
+       prk2818_headset_info->irq = gpio_to_irq(prk2818_headset_info->gpio);
+
+       if(prk2818_headset_info->headset_in_type == HEADSET_IN_HIGH)
+               prk2818_headset_info->irq_type = IRQF_TRIGGER_RISING;
+       else
+               prk2818_headset_info->irq_type = IRQF_TRIGGER_FALLING;
+       ret = request_irq(prk2818_headset_info->irq, headset_interrupt, prk2818_headset_info->irq_type, NULL, NULL);
+       if (ret) 
+       {
                DBG("headsetobserve: request irq failed\n");
-               return ret;
+        return ret;
        }
-       headsetobserve_work();
+
+       schedule_delayed_work(&g_headsetobserve_work, msecs_to_jiffies(500));
+       
+#ifdef CONFIG_HAS_EARLYSUSPEND
+    hs_early_suspend.suspend = NULL;
+    hs_early_suspend.resume = headset_early_resume;
+    hs_early_suspend.level = ~0x0;
+    register_early_suspend(&hs_early_suspend);
+#endif
 
        return 0;       
 }
old mode 100644 (file)
new mode 100755 (executable)
index 8d49d10..0a20367
@@ -6,6 +6,7 @@
 
 /* ¶ú»úÊý¾Ý½á¹¹Ìå */
 struct rk2818_headset_data {
+       unsigned int gpio;
        unsigned int irq;
        unsigned int irq_type;
        unsigned int headset_in_type;