summaryrefslogtreecommitdiff
path: root/drivers/headset_observe
diff options
context:
space:
mode:
author邱建斌 <qjb@rock-chips.com>2011-06-28 10:32:21 +0800
committer邱建斌 <qjb@rock-chips.com>2011-06-28 10:32:21 +0800
commit7451a831e63aa77878d7025926ef4f39b00fb999 (patch)
tree9944c93c2e7b74b3d1dc9d0b90f825cfd32081f0 /drivers/headset_observe
parentd9dced963e481235b1e219990783ef4c644d7a28 (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-xdrivers/headset_observe/rk_headset.c229
-rwxr-xr-xdrivers/headset_observe/rk_headset.h2
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
};