input: pwrkey: Handle out-of-order press and release interrupts
There is a possibility of receiving a release interrupt
before press when both these actions (press and release) of the
power-key are very close-by (~1-2ms) to the debounce time
of the key. Handle this case by maintaining a state variable.
Also mark the release interrupt as a wakeup source to
wakeup the system when the above mentioned abnormal case
occurs.
CRs-Fixed: 394289
Change-Id: I74475c1e5159dd30e52aca91243eec7e2fac4d57
Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index 65791cb..4f21adc 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, The Linux Foundation. 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 and
@@ -35,6 +35,8 @@
struct pmic8xxx_pwrkey {
struct input_dev *pwr;
int key_press_irq;
+ int key_release_irq;
+ bool press;
const struct pm8xxx_pwrkey_platform_data *pdata;
};
@@ -42,6 +44,13 @@
{
struct pmic8xxx_pwrkey *pwrkey = _pwrkey;
+ if (pwrkey->press == true) {
+ pwrkey->press = false;
+ return IRQ_HANDLED;
+ } else {
+ pwrkey->press = true;
+ }
+
input_report_key(pwrkey->pwr, KEY_POWER, 1);
input_sync(pwrkey->pwr);
@@ -52,6 +61,14 @@
{
struct pmic8xxx_pwrkey *pwrkey = _pwrkey;
+ if (pwrkey->press == false) {
+ input_report_key(pwrkey->pwr, KEY_POWER, 1);
+ input_sync(pwrkey->pwr);
+ pwrkey->press = true;
+ } else {
+ pwrkey->press = false;
+ }
+
input_report_key(pwrkey->pwr, KEY_POWER, 0);
input_sync(pwrkey->pwr);
@@ -63,8 +80,10 @@
{
struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
enable_irq_wake(pwrkey->key_press_irq);
+ enable_irq_wake(pwrkey->key_release_irq);
+ }
return 0;
}
@@ -73,8 +92,10 @@
{
struct pmic8xxx_pwrkey *pwrkey = dev_get_drvdata(dev);
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev)) {
disable_irq_wake(pwrkey->key_press_irq);
+ disable_irq_wake(pwrkey->key_release_irq);
+ }
return 0;
}
@@ -155,7 +176,9 @@
}
pwrkey->key_press_irq = key_press_irq;
+ pwrkey->key_release_irq = key_release_irq;
pwrkey->pwr = pwr;
+ pwrkey->press = false;
platform_set_drvdata(pdev, pwrkey);