From dc74259a8833d68afd2e8a3d55a5fac0b93698d7 Mon Sep 17 00:00:00 2001 From: "Li, Ning" Date: Thu, 22 Dec 2011 14:46:45 +0800 Subject: [PATCH] [PORT FROM R2] Add keypad driver patches BZ: 18179 This BZ includes the following BZ: 4915, 13482 Signed-off-by: Li, Ning Change-Id: Ief9354e35afa55991a0fba63f6f9edbac7778bed Reviewed-on: http://android.intel.com:8080/29697 Reviewed-by: Li, Ning Reviewed-by: Yang, Bin Reviewed-by: Du, Alek Tested-by: Wang, Zhifeng Reviewed-by: buildbot Tested-by: buildbot --- drivers/input/keyboard/gpio_keys.c | 62 +++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 07c3cab..851fd9e 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -26,7 +26,9 @@ #include #include +struct gpio_keys_drvdata; struct gpio_button_data { + struct gpio_keys_drvdata *ddata; struct gpio_keys_button *button; struct input_dev *input; struct timer_list timer; @@ -39,6 +41,7 @@ struct gpio_keys_drvdata { struct input_dev *input; struct mutex disable_lock; unsigned int n_buttons; + int force_trigger; int (*enable)(struct device *dev); void (*disable)(struct device *dev); struct gpio_button_data data[0]; @@ -398,9 +401,17 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct gpio_keys_button *button = bdata->button; + struct input_dev *input = bdata->input; + int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; BUG_ON(irq != gpio_to_irq(button->gpio)); + if (bdata->ddata->force_trigger && !state) { + unsigned int type = button->type ?: EV_KEY; + input_event(input, type, button->code, !state); + bdata->ddata->force_trigger = 0; + } + if (bdata->timer_debounce) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(bdata->timer_debounce)); @@ -539,6 +550,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) struct gpio_button_data *bdata = &ddata->data[i]; unsigned int type = button->type ?: EV_KEY; + bdata->ddata = ddata; bdata->input = input; bdata->button = button; @@ -625,16 +637,16 @@ static int gpio_keys_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; + struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); int i; - if (device_may_wakeup(&pdev->dev)) { - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup) { - int irq = gpio_to_irq(button->gpio); - enable_irq_wake(irq); - } - } + for (i = 0; i < pdata->nbuttons; i++) { + struct gpio_keys_button *button = &pdata->buttons[i]; + int irq = gpio_to_irq(button->gpio); + if (button->wakeup) + enable_irq_wake(irq); + else + free_irq(irq, &ddata->data[i]); } return 0; @@ -646,13 +658,31 @@ static int gpio_keys_resume(struct device *dev) struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; int i; + int error; - for (i = 0; i < pdata->nbuttons; i++) { + ddata->force_trigger = 0; + for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; - if (button->wakeup && device_may_wakeup(&pdev->dev)) { - int irq = gpio_to_irq(button->gpio); + int irq = gpio_to_irq(button->gpio); + + if (button->wakeup) disable_irq_wake(irq); + else { + unsigned long irqflags; + const char *desc; + struct gpio_button_data *bdata = &ddata->data[i]; + desc = button->desc ? button->desc : "gpio_keys"; + irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + if (!button->can_disable) + irqflags |= IRQF_SHARED; + error = request_irq(irq, gpio_keys_isr, irqflags, + desc, bdata); + if (error) { + dev_err(dev, "Unable to claim irq %d; error %d\n", + irq, error); + return error; + } } gpio_keys_report_event(&ddata->data[i]); @@ -662,9 +692,19 @@ static int gpio_keys_resume(struct device *dev) return 0; } +static int gpio_keys_resume_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); + + ddata->force_trigger = 1; + return 0; +} + static const struct dev_pm_ops gpio_keys_pm_ops = { .suspend = gpio_keys_suspend, .resume = gpio_keys_resume, + .resume_noirq = gpio_keys_resume_noirq, }; #endif -- 2.7.4