diff options
author | 邱建斌 <qjb@rock-chips.com> | 2011-06-28 10:32:21 +0800 |
---|---|---|
committer | 邱建斌 <qjb@rock-chips.com> | 2011-06-28 10:32:21 +0800 |
commit | 7451a831e63aa77878d7025926ef4f39b00fb999 (patch) | |
tree | 9944c93c2e7b74b3d1dc9d0b90f825cfd32081f0 /drivers/headset_observe | |
parent | d9dced963e481235b1e219990783ef4c644d7a28 (diff) |
rk29_phone: fix hook key irq. if headset have not hook key then not reported keydown
Diffstat (limited to 'drivers/headset_observe')
-rwxr-xr-x | drivers/headset_observe/rk_headset.c | 229 | ||||
-rwxr-xr-x | drivers/headset_observe/rk_headset.h | 2 |
2 files changed, 152 insertions, 79 deletions
diff --git a/drivers/headset_observe/rk_headset.c b/drivers/headset_observe/rk_headset.c index 64d870c10298..5fcccad31090 100755 --- a/drivers/headset_observe/rk_headset.c +++ b/drivers/headset_observe/rk_headset.c @@ -39,7 +39,7 @@ #include <linux/earlysuspend.h> /* Debug */ -#if 0 +#if 1 #define DBG(x...) printk(x) #else #define DBG(x...) do { } while (0) @@ -51,21 +51,30 @@ #define HEADSET 0 #define HOOK 1 +#define HEADSET_IN 1 +#define HEADSET_OUT 0 +#define HOOK_DOWN 0 +#define HOOK_UP 1 +#define enable 1 +#define disable 0 + +extern int wm8994_set_status(void); /* headset private data */ struct headset_priv { struct input_dev *input_dev; struct rk_headset_pdata *pdata; unsigned int headset_status:1; unsigned int hook_status:1; - - struct switch_dev sdev; + unsigned int isMic:1; + unsigned int isHook_irq:1; int cur_headset_status; - struct mutex mutex_lock[2]; unsigned int irq[2]; unsigned int irq_type[2]; - struct delayed_work h_delayed_work[2]; - + struct delayed_work h_delayed_work[2]; + struct switch_dev sdev; + struct mutex mutex_lock[2]; + struct timer_list headset_timer; unsigned char *keycodes; }; static struct headset_priv *headset_info; @@ -74,13 +83,14 @@ static struct headset_priv *headset_info; static irqreturn_t headset_interrupt(int irq, void *dev_id) { // DBG("---headset_interrupt---\n"); - schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(20)); + schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(50)); return IRQ_HANDLED; } static irqreturn_t Hook_interrupt(int irq, void *dev_id) { // DBG("---Hook_interrupt---\n"); +// disable_irq_nosync(headset_info->irq[HOOK]); schedule_delayed_work(&headset_info->h_delayed_work[HOOK], msecs_to_jiffies(100)); return IRQ_HANDLED; } @@ -117,7 +127,7 @@ static void headsetobserve_work(struct work_struct *work) int i,level = 0; struct rk_headset_pdata *pdata = headset_info->pdata; static unsigned int old_status = 0; -// DBG("---headsetobserve_work---\n"); + DBG("---headsetobserve_work---\n"); mutex_lock(&headset_info->mutex_lock[HEADSET]); for(i=0; i<3; i++) @@ -135,7 +145,7 @@ static void headsetobserve_work(struct work_struct *work) if(level < 0) { printk("%s:get pin level err!\n",__FUNCTION__); - return; + goto RE_ERROR; } old_status = headset_info->headset_status; @@ -143,15 +153,15 @@ static void headsetobserve_work(struct work_struct *work) { case HEADSET_IN_HIGH: if(level > 0) - headset_info->headset_status = 1; + headset_info->headset_status = HEADSET_IN; else if(level == 0) - headset_info->headset_status = 0; + headset_info->headset_status = HEADSET_OUT; break; case HEADSET_IN_LOW: if(level == 0) - headset_info->headset_status = 1; + headset_info->headset_status = HEADSET_IN; else if(level > 0) - headset_info->headset_status = 0; + headset_info->headset_status = HEADSET_OUT; break; default: DBG("---- ERROR: on headset headset_in_type error -----\n"); @@ -159,58 +169,60 @@ static void headsetobserve_work(struct work_struct *work) } if(old_status == headset_info->headset_status) { - printk("old_status == headset_info->headset_status\n"); - mutex_unlock(&headset_info->mutex_lock[HEADSET]); - return; + DBG("old_status == headset_info->headset_status\n"); + goto RE_ERROR; } switch(pdata->headset_in_type) { - case HEADSET_IN_HIGH: - if(level > 0) - {//in--High level - DBG("--- HEADSET_IN_HIGH headset in HIGH---\n"); - enable_irq(headset_info->irq[HOOK]); - headset_info->headset_status = 1; - headset_info->cur_headset_status = BIT_HEADSET; - headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);// - } - else if(level == 0) - {//out--Low level - DBG("---HEADSET_IN_HIGH headset out HIGH---\n"); + case HEADSET_IN_HIGH: + if(level > 0) + {//in--High level + DBG("--- HEADSET_IN_HIGH headset in HIGH---\n"); + // enable_irq(headset_info->irq[HOOK]); + headset_info->cur_headset_status = BIT_HEADSET; + headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);// + del_timer(&headset_info->headset_timer);//Æô¶¯¶¨Ê±Æ÷£¬µÈ´ýÇл»µ½¶ú»úͨ· + headset_info->headset_timer.expires = jiffies + 500; + add_timer(&headset_info->headset_timer); + } + else if(level == 0) + {//out--Low level + DBG("---HEADSET_IN_HIGH headset out HIGH---\n"); + if(headset_info->isHook_irq == enable) + { + DBG("disable_irq\n"); + headset_info->isHook_irq = disable; disable_irq(headset_info->irq[HOOK]); - headset_info->headset_status = 0; - headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC); - headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);// - } - break; - case HEADSET_IN_LOW: - if(level == 0) - {//in--High level - DBG("---HEADSET_IN_LOW headset in LOW ---\n"); - headset_info->headset_status = 1; - headset_info->cur_headset_status = BIT_HEADSET; - headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);// - enable_irq(headset_info->irq[HOOK]); - } - else if(level > 0) - {//out--High level - DBG("---HEADSET_IN_LOW headset out LOW ---\n"); - headset_info->headset_status = 0; - headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC); - headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);// - disable_irq(headset_info->irq[HOOK]); - } - break; - default: - DBG("---- ERROR: on headset headset_in_type error -----\n"); - break; + } + headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC); + headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);// + } + break; + case HEADSET_IN_LOW: + if(level == 0) + {//in--High level + DBG("---HEADSET_IN_LOW headset in LOW ---\n"); + headset_info->cur_headset_status = BIT_HEADSET; + headset_change_irqtype(HEADSET,IRQF_TRIGGER_RISING);// + enable_irq(headset_info->irq[HOOK]); + } + else if(level > 0) + {//out--High level + DBG("---HEADSET_IN_LOW headset out LOW ---\n"); + headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC); + headset_change_irqtype(HEADSET,IRQF_TRIGGER_FALLING);// + disable_irq(headset_info->irq[HOOK]); + } + break; + default: + DBG("---- ERROR: on headset headset_in_type error -----\n"); + break; } - switch_set_state(&headset_info->sdev, headset_info->cur_headset_status); - DBG("Headset_dev.cur_headset_status = %d\n",headset_info->cur_headset_status); - + DBG("headset_info->cur_headset_status = %d\n",headset_info->cur_headset_status); +RE_ERROR: mutex_unlock(&headset_info->mutex_lock[HEADSET]); } @@ -219,14 +231,13 @@ static void Hook_work(struct work_struct *work) int i,level = 0; struct rk_headset_pdata *pdata = headset_info->pdata; static unsigned int old_status = 0; - + DBG("---Hook_work---\n"); mutex_lock(&headset_info->mutex_lock[HOOK]); - if(headset_info->headset_status == 0) + if(headset_info->headset_status == HEADSET_OUT) { - printk("Headset is out\n"); - mutex_unlock(&headset_info->mutex_lock[HOOK]); - return; + DBG("Headset is out\n"); + goto RE_ERROR; } for(i=0; i<3; i++) @@ -244,39 +255,92 @@ static void Hook_work(struct work_struct *work) if(level < 0) { printk("%s:get pin level err!\n",__FUNCTION__); - return; + goto RE_ERROR; } old_status = headset_info->hook_status; if(level == 0) - headset_info->hook_status = 1; + headset_info->hook_status = HOOK_UP; else if(level > 0) - headset_info->hook_status = 0; + headset_info->hook_status = HOOK_DOWN; if(old_status == headset_info->hook_status) { - printk("old_status == headset_info->hook_status\n"); - mutex_unlock(&headset_info->mutex_lock[HOOK]); - return; + DBG("old_status == headset_info->hook_status\n"); + goto RE_ERROR; } if(level == 0) { DBG("---HOOK Down ---\n"); headset_change_irqtype(HOOK,IRQF_TRIGGER_RISING);// - input_report_key(headset_info->input_dev,KEY_MEDIA,headset_info->hook_status); - input_sync(headset_info->input_dev); + input_report_key(headset_info->input_dev,pdata->hook_key_code,headset_info->hook_status); + input_sync(headset_info->input_dev); } else if(level > 0) { DBG("---HOOK Up ---\n"); headset_change_irqtype(HOOK,IRQF_TRIGGER_FALLING);// - input_report_key(headset_info->input_dev,KEY_MEDIA,headset_info->hook_status); - input_sync(headset_info->input_dev); + input_report_key(headset_info->input_dev,pdata->hook_key_code,headset_info->hook_status); + input_sync(headset_info->input_dev); } - +RE_ERROR: mutex_unlock(&headset_info->mutex_lock[HOOK]); } +static void headset_timer_callback(unsigned long arg) +{ + struct headset_priv *headset = (struct headset_priv *)(arg); + struct rk_headset_pdata *pdata = headset->pdata; + int i,level = 0; + + DBG("headset_timer_callback\n"); + + if(headset->headset_status == HEADSET_OUT) + { + DBG("Headset is out\n"); + goto out; + } + if(wm8994_set_status() < 0) + { + DBG("wm8994 is not set on heatset channel\n"); + headset_info->headset_timer.expires = jiffies + 500; + add_timer(&headset_info->headset_timer); + goto out; + } + + for(i=0; i<3; i++) + { + level = gpio_get_value(pdata->Hook_gpio); + if(level < 0) + { + printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,pdata->Hook_gpio,i); + msleep(1); + continue; + } + else + break; + } + if(level < 0) + { + printk("%s:get pin level err!\n",__FUNCTION__); + goto out; + } + +//ÑÓ³ÙÒ»¶Îʱ¼ä¶ú»ú»¹ÊÇ°´ÏµĻ°£¬ÄÇôӦ¸ÃÊÇÎÞ°´¼ü¶ú»ú + if(level == 0) + headset->isMic= 0;//No microphone + else if(level > 0) + { + headset->isMic = 1;//have mic + DBG("enable_irq\n"); + enable_irq(headset_info->irq[HOOK]); + headset->isHook_irq = enable; + } + DBG("headset->isMic = %d\n",headset->isMic); +out: + return; +} + static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf) { return sprintf(buf, "Headset\n"); @@ -319,8 +383,9 @@ static int rockchip_headsetobserve_probe(struct platform_device *pdev) } headset->pdata = pdev->dev.platform_data; pdata = headset->pdata; - headset->headset_status = 0; - headset->hook_status = 0; + headset->headset_status = HEADSET_OUT; + headset->hook_status = HOOK_UP; + headset->isHook_irq = disable; headset->cur_headset_status = 0; headset->sdev.name = "h2w"; headset->sdev.print_name = h2w_print_name; @@ -333,6 +398,15 @@ static int rockchip_headsetobserve_probe(struct platform_device *pdev) INIT_DELAYED_WORK(&headset->h_delayed_work[HEADSET], headsetobserve_work); INIT_DELAYED_WORK(&headset->h_delayed_work[HOOK], Hook_work); + +// init_timer(&headset->headset_timer); +// headset->headset_timer.function = headset_timer_callback; +// headset->headset_timer.data = (unsigned long)headset; +// headset->headset_timer.expires = jiffies + 3000; + headset->isMic = 0; + setup_timer(&headset->headset_timer, headset_timer_callback, (unsigned long)headset); +// headset->headset_timer.expires = jiffies + 1000; +// add_timer(&headset->headset_timer); //------------------------------------------------------------------ ret = gpio_request(pdata->Headset_gpio, NULL); if (ret) @@ -361,8 +435,7 @@ static int rockchip_headsetobserve_probe(struct platform_device *pdev) if (ret) goto failed_free; disable_irq(headset->irq[HOOK]); -//------------------------------------------------------------------ - +//------------------------------------------------------------------ // Create and register the input driver. headset->input_dev = input_allocate_device(); if (!headset->input_dev) { @@ -392,7 +465,7 @@ static int rockchip_headsetobserve_probe(struct platform_device *pdev) // set_bit(KEY_MEDIA, headset->input_dev->keybit); // clear_bit(0, headset->input_dev->keybit); - input_set_capability(headset->input_dev, EV_KEY, KEY_MEDIA); + input_set_capability(headset->input_dev, EV_KEY, pdata->hook_key_code); // input_set_capability(headset->input_dev, EV_SW, SW_HEADPHONE_INSERT); // input_set_capability(headset->input_dev, EV_KEY, KEY_END); diff --git a/drivers/headset_observe/rk_headset.h b/drivers/headset_observe/rk_headset.h index c1f7a91862ec..51e2655d3fbc 100755 --- a/drivers/headset_observe/rk_headset.h +++ b/drivers/headset_observe/rk_headset.h @@ -7,7 +7,7 @@ struct rk_headset_pdata{ unsigned int Hook_gpio;//Detection Headset--Must be set - + int hook_key_code; unsigned int Headset_gpio;//Detection Headset--Must be set unsigned int headset_in_type;// Headphones into the state level--Must be set }; |