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>
This commit is contained in:
Ajay Dudani 2012-09-05 17:07:13 +05:30 committed by Iliyan Malchev
parent 75f55110dc
commit 93c63d759f

View file

@ -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 @@ static irqreturn_t pwrkey_press_irq(int irq, void *_pwrkey)
{
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 @@ static irqreturn_t pwrkey_release_irq(int irq, void *_pwrkey)
{
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 @@ static int pmic8xxx_pwrkey_suspend(struct device *dev)
{
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 @@ static int pmic8xxx_pwrkey_resume(struct device *dev)
{
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 @@ static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev)
}
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);