diff options
-rw-r--r-- | drivers/input/misc/sirfsoc-onkey.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c index 81cdf51f8246..a6e76080af5f 100644 --- a/drivers/input/misc/sirfsoc-onkey.c +++ b/drivers/input/misc/sirfsoc-onkey.c | |||
@@ -13,16 +13,41 @@ | |||
13 | #include <linux/input.h> | 13 | #include <linux/input.h> |
14 | #include <linux/rtc/sirfsoc_rtciobrg.h> | 14 | #include <linux/rtc/sirfsoc_rtciobrg.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/workqueue.h> | ||
16 | 17 | ||
17 | struct sirfsoc_pwrc_drvdata { | 18 | struct sirfsoc_pwrc_drvdata { |
18 | u32 pwrc_base; | 19 | u32 pwrc_base; |
19 | struct input_dev *input; | 20 | struct input_dev *input; |
21 | struct delayed_work work; | ||
20 | }; | 22 | }; |
21 | 23 | ||
22 | #define PWRC_ON_KEY_BIT (1 << 0) | 24 | #define PWRC_ON_KEY_BIT (1 << 0) |
23 | 25 | ||
24 | #define PWRC_INT_STATUS 0xc | 26 | #define PWRC_INT_STATUS 0xc |
25 | #define PWRC_INT_MASK 0x10 | 27 | #define PWRC_INT_MASK 0x10 |
28 | #define PWRC_PIN_STATUS 0x14 | ||
29 | #define PWRC_KEY_DETECT_UP_TIME 20 /* ms*/ | ||
30 | |||
31 | static int sirfsoc_pwrc_is_on_key_down(struct sirfsoc_pwrc_drvdata *pwrcdrv) | ||
32 | { | ||
33 | u32 state = sirfsoc_rtc_iobrg_readl(pwrcdrv->pwrc_base + | ||
34 | PWRC_PIN_STATUS); | ||
35 | return !(state & PWRC_ON_KEY_BIT); /* ON_KEY is active low */ | ||
36 | } | ||
37 | |||
38 | static void sirfsoc_pwrc_report_event(struct work_struct *work) | ||
39 | { | ||
40 | struct sirfsoc_pwrc_drvdata *pwrcdrv = | ||
41 | container_of(work, struct sirfsoc_pwrc_drvdata, work.work); | ||
42 | |||
43 | if (sirfsoc_pwrc_is_on_key_down(pwrcdrv)) { | ||
44 | schedule_delayed_work(&pwrcdrv->work, | ||
45 | msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); | ||
46 | } else { | ||
47 | input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 0); | ||
48 | input_sync(pwrcdrv->input); | ||
49 | } | ||
50 | } | ||
26 | 51 | ||
27 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | 52 | static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) |
28 | { | 53 | { |
@@ -34,17 +59,10 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id) | |||
34 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, | 59 | sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT, |
35 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); | 60 | pwrcdrv->pwrc_base + PWRC_INT_STATUS); |
36 | 61 | ||
37 | /* | 62 | input_event(pwrcdrv->input, EV_KEY, KEY_POWER, 1); |
38 | * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c | ||
39 | * to queue a SUSPEND APM event | ||
40 | */ | ||
41 | input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1); | ||
42 | input_sync(pwrcdrv->input); | 63 | input_sync(pwrcdrv->input); |
43 | 64 | schedule_delayed_work(&pwrcdrv->work, | |
44 | /* | 65 | msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME)); |
45 | * Todo: report KEY_POWER event for Android platforms, Android PowerManager | ||
46 | * will handle the suspend and powerdown/hibernation | ||
47 | */ | ||
48 | 66 | ||
49 | return IRQ_HANDLED; | 67 | return IRQ_HANDLED; |
50 | } | 68 | } |
@@ -76,6 +94,7 @@ static void sirfsoc_pwrc_close(struct input_dev *input) | |||
76 | struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); | 94 | struct sirfsoc_pwrc_drvdata *pwrcdrv = input_get_drvdata(input); |
77 | 95 | ||
78 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); | 96 | sirfsoc_pwrc_toggle_interrupts(pwrcdrv, false); |
97 | cancel_delayed_work_sync(&pwrcdrv->work); | ||
79 | } | 98 | } |
80 | 99 | ||
81 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { | 100 | static const struct of_device_id sirfsoc_pwrc_of_match[] = { |
@@ -115,7 +134,9 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev) | |||
115 | 134 | ||
116 | pwrcdrv->input->name = "sirfsoc pwrckey"; | 135 | pwrcdrv->input->name = "sirfsoc pwrckey"; |
117 | pwrcdrv->input->phys = "pwrc/input0"; | 136 | pwrcdrv->input->phys = "pwrc/input0"; |
118 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR); | 137 | pwrcdrv->input->evbit[0] = BIT_MASK(EV_KEY); |
138 | |||
139 | INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event); | ||
119 | 140 | ||
120 | pwrcdrv->input->open = sirfsoc_pwrc_open; | 141 | pwrcdrv->input->open = sirfsoc_pwrc_open; |
121 | pwrcdrv->input->close = sirfsoc_pwrc_close; | 142 | pwrcdrv->input->close = sirfsoc_pwrc_close; |