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 @@ #include #include #include +#include #include #include #include @@ -78,6 +79,9 @@ struct corgikbd { struct timer_list timer; struct timer_list htimer; + + unsigned int suspended; + unsigned long suspend_jiffies; }; 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 if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) { corgikbd_data->state[scancode] |= CORGIKBD_PRESSED; input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1); - if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) + if ((corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) + && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); + corgikbd_data->suspend_jiffies=jiffies; + } } else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) { corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED; 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 unsigned long flags; unsigned int num_pressed; + if (corgikbd_data->suspended) + return; + spin_lock_irqsave(&corgikbd_data->lock, flags); if (regs) @@ -255,6 +265,32 @@ static void corgikbd_hinge_timer(unsigned long data) mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL); } +#ifdef CONFIG_PM +static int corgikbd_suspend(struct device *dev, pm_message_t state, uint32_t level) +{ + if (level == SUSPEND_POWER_DOWN) { + struct corgikbd *corgikbd = dev_get_drvdata(dev); + corgikbd->suspended = 1; + } + return 0; +} + +static int corgikbd_resume(struct device *dev, uint32_t level) +{ + if (level == RESUME_POWER_ON) { + struct corgikbd *corgikbd = dev_get_drvdata(dev); + + /* Upon resume, ignore the suspend key for a short while */ + corgikbd->suspend_jiffies=jiffies; + corgikbd->suspended = 0; + } + return 0; +} +#else +#define corgikbd_suspend NULL +#define corgikbd_resume NULL +#endif + static int __init corgikbd_probe(struct device *dev) { int i; @@ -279,6 +315,8 @@ static int __init corgikbd_probe(struct device *dev) corgikbd->htimer.function = corgikbd_hinge_timer; corgikbd->htimer.data = (unsigned long) corgikbd; + corgikbd->suspend_jiffies=jiffies; + init_input_dev(&corgikbd->input); corgikbd->input.private = corgikbd; corgikbd->input.name = "Corgi Keyboard"; @@ -343,6 +381,8 @@ static struct device_driver corgikbd_driver = { .bus = &platform_bus_type, .probe = corgikbd_probe, .remove = corgikbd_remove, + .suspend = corgikbd_suspend, + .resume = corgikbd_resume, }; static int __devinit corgikbd_init(void)