diff options
-rw-r--r-- | drivers/input/keyboard/corgikbd.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index a31c3d64af32..43d6edb3cf09 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/input.h> | 17 | #include <linux/input.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/jiffies.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
@@ -78,6 +79,9 @@ struct corgikbd { | |||
78 | 79 | ||
79 | struct timer_list timer; | 80 | struct timer_list timer; |
80 | struct timer_list htimer; | 81 | struct timer_list htimer; |
82 | |||
83 | unsigned int suspended; | ||
84 | unsigned long suspend_jiffies; | ||
81 | }; | 85 | }; |
82 | 86 | ||
83 | static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data) | 87 | static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data) |
@@ -85,8 +89,11 @@ static void handle_scancode(unsigned int pressed,unsigned int scancode, struct c | |||
85 | if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) { | 89 | if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) { |
86 | corgikbd_data->state[scancode] |= CORGIKBD_PRESSED; | 90 | corgikbd_data->state[scancode] |= CORGIKBD_PRESSED; |
87 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1); | 91 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1); |
88 | if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) | 92 | if ((corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) |
93 | && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { | ||
89 | input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); | 94 | input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); |
95 | corgikbd_data->suspend_jiffies=jiffies; | ||
96 | } | ||
90 | } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) { | 97 | } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) { |
91 | corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED; | 98 | corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED; |
92 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0); | 99 | input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0); |
@@ -153,6 +160,9 @@ static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs | |||
153 | unsigned long flags; | 160 | unsigned long flags; |
154 | unsigned int num_pressed; | 161 | unsigned int num_pressed; |
155 | 162 | ||
163 | if (corgikbd_data->suspended) | ||
164 | return; | ||
165 | |||
156 | spin_lock_irqsave(&corgikbd_data->lock, flags); | 166 | spin_lock_irqsave(&corgikbd_data->lock, flags); |
157 | 167 | ||
158 | if (regs) | 168 | if (regs) |
@@ -255,6 +265,32 @@ static void corgikbd_hinge_timer(unsigned long data) | |||
255 | mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); | 265 | mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); |
256 | } | 266 | } |
257 | 267 | ||
268 | #ifdef CONFIG_PM | ||
269 | static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level) | ||
270 | { | ||
271 | if (level == SUSPEND_POWER_DOWN) { | ||
272 | struct corgikbd *corgikbd = dev_get_drvdata(dev); | ||
273 | corgikbd->suspended = 1; | ||
274 | } | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int corgikbd_resume(struct device *dev, uint32_t level) | ||
279 | { | ||
280 | if (level == RESUME_POWER_ON) { | ||
281 | struct corgikbd *corgikbd = dev_get_drvdata(dev); | ||
282 | |||
283 | /* Upon resume, ignore the suspend key for a short while */ | ||
284 | corgikbd->suspend_jiffies=jiffies; | ||
285 | corgikbd->suspended = 0; | ||
286 | } | ||
287 | return 0; | ||
288 | } | ||
289 | #else | ||
290 | #define corgikbd_suspend NULL | ||
291 | #define corgikbd_resume NULL | ||
292 | #endif | ||
293 | |||
258 | static int __init corgikbd_probe(struct device *dev) | 294 | static int __init corgikbd_probe(struct device *dev) |
259 | { | 295 | { |
260 | int i; | 296 | int i; |
@@ -279,6 +315,8 @@ static int __init corgikbd_probe(struct device *dev) | |||
279 | corgikbd->htimer.function = corgikbd_hinge_timer; | 315 | corgikbd->htimer.function = corgikbd_hinge_timer; |
280 | corgikbd->htimer.data = (unsigned long) corgikbd; | 316 | corgikbd->htimer.data = (unsigned long) corgikbd; |
281 | 317 | ||
318 | corgikbd->suspend_jiffies=jiffies; | ||
319 | |||
282 | init_input_dev(&corgikbd->input); | 320 | init_input_dev(&corgikbd->input); |
283 | corgikbd->input.private = corgikbd; | 321 | corgikbd->input.private = corgikbd; |
284 | corgikbd->input.name = "Corgi Keyboard"; | 322 | corgikbd->input.name = "Corgi Keyboard"; |
@@ -343,6 +381,8 @@ static struct device_driver corgikbd_driver = { | |||
343 | .bus = &platform_bus_type, | 381 | .bus = &platform_bus_type, |
344 | .probe = corgikbd_probe, | 382 | .probe = corgikbd_probe, |
345 | .remove = corgikbd_remove, | 383 | .remove = corgikbd_remove, |
384 | .suspend = corgikbd_suspend, | ||
385 | .resume = corgikbd_resume, | ||
346 | }; | 386 | }; |
347 | 387 | ||
348 | static int __devinit corgikbd_init(void) | 388 | static int __devinit corgikbd_init(void) |