summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDavid Yu <davyu@nvidia.com>2014-01-20 13:10:26 +0900
committerHarry Hong <hhong@nvidia.com>2014-01-20 16:50:58 -0800
commit2c0336c6c590c27f90b8c2a6e32b5687f7098db9 (patch)
treec4c78d33020a195eb4bb04f2507627ee2ccc2e8c /drivers
parent16c5d4289ee983e8c52898401fdeb16b686c37cf (diff)
input: gpio_keys: Fix disordered wakeup key reports
- If power key is released before gpio_keys_gpio_report_wake() called, power key press-release events pair will be reported twice and supress display from coming back up. - If power key is released before enabling device driver to receive interrupts, power key release interrupt will be lost due to the previous pending key press intterupt, and we can only get the released key state. Change to call gpio_keys_gpio_report_wake() and gpio_keys_report_state() in gpio_keys_resume_noirq() callback to avoid the disordered reports. Bug 1372600 Bug 1346985 Bug 1437458 Change-Id: I8e35f6012f2fc600f4dd830e1c191f9f2782e621 Signed-off-by: Allen Yu <alleny@nvidia.com> Reviewed-on: http://git-master/r/280231 Signed-off-by: David Yu <davyu@nvidia.com> Reviewed-on: http://git-master/r/357540 Reviewed-by: Harry Hong <hhong@nvidia.com> Tested-by: Harry Hong <hhong@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/gpio_keys.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 93d7354fb17e..4a48be984e91 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -4,7 +4,7 @@
* Copyright 2005 Phil Blundell
* Copyright 2010, 2011 David Jander <david@protonic.nl>
*
- * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -812,21 +812,13 @@ static int gpio_keys_suspend(struct device *dev)
static int gpio_keys_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
- struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
- int wakeup_key = KEY_RESERVED;
int i;
- if (pdata->wakeup_key)
- wakeup_key = pdata->wakeup_key();
for (i = 0; i < ddata->n_buttons; i++) {
struct gpio_button_data *bdata = &ddata->data[i];
if (bdata->button->wakeup && device_may_wakeup(dev)) {
disable_irq_wake(bdata->irq);
-
- if (wakeup_key == bdata->button->code)
- gpio_keys_gpio_report_wake(bdata);
}
if (gpio_is_valid(bdata->button->gpio))
@@ -836,9 +828,41 @@ static int gpio_keys_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
+static int gpio_keys_suspend_noirq(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 = dev_get_drvdata(dev);
+ struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+ int wakeup_key = KEY_RESERVED;
+ int i;
+ if (pdata->wakeup_key)
+ wakeup_key = pdata->wakeup_key();
+
+ if (device_may_wakeup(dev)) {
+ for (i = 0; i < ddata->n_buttons; i++) {
+ struct gpio_button_data *bdata = &ddata->data[i];
+ if (bdata->button->wakeup &&
+ wakeup_key == bdata->button->code)
+ gpio_keys_gpio_report_wake(bdata);
+ }
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops gpio_keys_pm_ops = {
+ .suspend = gpio_keys_suspend,
+ .resume = gpio_keys_resume,
+ .suspend_noirq = gpio_keys_suspend_noirq,
+ .resume_noirq = gpio_keys_resume_noirq,
+};
+#endif
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
@@ -846,7 +870,9 @@ static struct platform_driver gpio_keys_device_driver = {
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
.pm = &gpio_keys_pm_ops,
+#endif
.of_match_table = gpio_keys_of_match,
}
};