From 0bd09750d03920d494326fef5269edfd947c8599 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=82=B1=E5=BB=BA=E6=96=8C?= Date: Fri, 8 Apr 2011 11:29:41 +0800 Subject: [PATCH] =?utf8?q?rk29phonesdk:=E8=80=B3=E6=9C=BA=E9=A9=B1?= =?utf8?q?=E5=8A=A8=E4=BF=AE=E6=94=B9=E5=B9=B6=E6=B5=8B=E8=AF=95=E5=8F=AF?= =?utf8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- arch/arm/mach-rk29/board-rk29-phonesdk.c | 22 ++- drivers/headset_observe/rk2818_headset.c | 193 ++++++++++++++++------- drivers/headset_observe/rk2818_headset.h | 1 + 3 files changed, 155 insertions(+), 61 deletions(-) mode change 100644 => 100755 drivers/headset_observe/rk2818_headset.c mode change 100644 => 100755 drivers/headset_observe/rk2818_headset.h diff --git a/arch/arm/mach-rk29/board-rk29-phonesdk.c b/arch/arm/mach-rk29/board-rk29-phonesdk.c index ed0aa689842b..3f49da2b2e30 100755 --- a/arch/arm/mach-rk29/board-rk29-phonesdk.c +++ b/arch/arm/mach-rk29/board-rk29-phonesdk.c @@ -61,7 +61,7 @@ #include #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 diff --git a/drivers/headset_observe/rk2818_headset.c b/drivers/headset_observe/rk2818_headset.c old mode 100644 new mode 100755 index d7bdecd0f4bb..f0e7133a8b58 --- a/drivers/headset_observe/rk2818_headset.c +++ b/drivers/headset_observe/rk2818_headset.c @@ -36,17 +36,17 @@ #include #include #include "rk2818_headset.h" +#include /* 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; } diff --git a/drivers/headset_observe/rk2818_headset.h b/drivers/headset_observe/rk2818_headset.h old mode 100644 new mode 100755 index 8d49d10aac0d..0a2036752dc4 --- a/drivers/headset_observe/rk2818_headset.h +++ b/drivers/headset_observe/rk2818_headset.h @@ -6,6 +6,7 @@ /* ¶ú»úÊý¾Ý½á¹¹Ìå */ struct rk2818_headset_data { + unsigned int gpio; unsigned int irq; unsigned int irq_type; unsigned int headset_in_type; -- 2.34.1