aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <rpurdie@rpsys.net>2005-09-06 18:18:59 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:52 -0400
commit8240a4a4bc95814502da522d5ee929fe0f0dc679 (patch)
treed8e453ecac05f8efe2ae50a0b869df1628fca71f
parentaba5a4c055dde13a3cece53e1b4b060294d631ed (diff)
[PATCH] Corgi Keyboard: Add some power management code
Add some power management code to the corgi keyboard driver so that only one power event gets reported within any reasonable time frame and the driver doesn't enter an infinte loop due to key repeat. Signed-off-by: Richard Purdie <rpurdie@rpsys.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/input/keyboard/corgikbd.c42
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
83static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data) 87static 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
269static 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
278static 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
258static int __init corgikbd_probe(struct device *dev) 294static 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
348static int __devinit corgikbd_init(void) 388static int __devinit corgikbd_init(void)