diff options
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r-- | drivers/input/serio/i8042.c | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index b53a015bf8a5..8aaf8fcacf62 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -264,6 +264,49 @@ static int i8042_aux_write(struct serio *serio, unsigned char c) | |||
264 | I8042_CMD_MUX_SEND + port->mux); | 264 | I8042_CMD_MUX_SEND + port->mux); |
265 | } | 265 | } |
266 | 266 | ||
267 | |||
268 | /* | ||
269 | * i8042_aux_close attempts to clear AUX or KBD port state by disabling | ||
270 | * and then re-enabling it. | ||
271 | */ | ||
272 | |||
273 | static void i8042_port_close(struct serio *serio) | ||
274 | { | ||
275 | int irq_bit; | ||
276 | int disable_bit; | ||
277 | const char *port_name; | ||
278 | |||
279 | if (serio == i8042_ports[I8042_AUX_PORT_NO].serio) { | ||
280 | irq_bit = I8042_CTR_AUXINT; | ||
281 | disable_bit = I8042_CTR_AUXDIS; | ||
282 | port_name = "AUX"; | ||
283 | } else { | ||
284 | irq_bit = I8042_CTR_KBDINT; | ||
285 | disable_bit = I8042_CTR_KBDDIS; | ||
286 | port_name = "KBD"; | ||
287 | } | ||
288 | |||
289 | i8042_ctr &= ~irq_bit; | ||
290 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
291 | printk(KERN_WARNING | ||
292 | "i8042.c: Can't write CTR while closing %s port.\n", | ||
293 | port_name); | ||
294 | |||
295 | udelay(50); | ||
296 | |||
297 | i8042_ctr &= ~disable_bit; | ||
298 | i8042_ctr |= irq_bit; | ||
299 | if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) | ||
300 | printk(KERN_ERR "i8042.c: Can't reactivate %s port.\n", | ||
301 | port_name); | ||
302 | |||
303 | /* | ||
304 | * See if there is any data appeared while we were messing with | ||
305 | * port state. | ||
306 | */ | ||
307 | i8042_interrupt(0, NULL); | ||
308 | } | ||
309 | |||
267 | /* | 310 | /* |
268 | * i8042_start() is called by serio core when port is about to finish | 311 | * i8042_start() is called by serio core when port is about to finish |
269 | * registering. It will mark port as existing so i8042_interrupt can | 312 | * registering. It will mark port as existing so i8042_interrupt can |
@@ -393,7 +436,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
393 | } | 436 | } |
394 | 437 | ||
395 | /* | 438 | /* |
396 | * i8042_enable_kbd_port enables keybaord port on chip | 439 | * i8042_enable_kbd_port enables keyboard port on chip |
397 | */ | 440 | */ |
398 | 441 | ||
399 | static int i8042_enable_kbd_port(void) | 442 | static int i8042_enable_kbd_port(void) |
@@ -841,6 +884,9 @@ static void i8042_controller_reset(void) | |||
841 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; | 884 | i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS; |
842 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); | 885 | i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT); |
843 | 886 | ||
887 | if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR)) | ||
888 | printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n"); | ||
889 | |||
844 | /* | 890 | /* |
845 | * Disable MUX mode if present. | 891 | * Disable MUX mode if present. |
846 | */ | 892 | */ |
@@ -1026,6 +1072,7 @@ static int __devinit i8042_create_kbd_port(void) | |||
1026 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; | 1072 | serio->write = i8042_dumbkbd ? NULL : i8042_kbd_write; |
1027 | serio->start = i8042_start; | 1073 | serio->start = i8042_start; |
1028 | serio->stop = i8042_stop; | 1074 | serio->stop = i8042_stop; |
1075 | serio->close = i8042_port_close; | ||
1029 | serio->port_data = port; | 1076 | serio->port_data = port; |
1030 | serio->dev.parent = &i8042_platform_device->dev; | 1077 | serio->dev.parent = &i8042_platform_device->dev; |
1031 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); | 1078 | strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name)); |
@@ -1056,6 +1103,7 @@ static int __devinit i8042_create_aux_port(int idx) | |||
1056 | if (idx < 0) { | 1103 | if (idx < 0) { |
1057 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); | 1104 | strlcpy(serio->name, "i8042 AUX port", sizeof(serio->name)); |
1058 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); | 1105 | strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys)); |
1106 | serio->close = i8042_port_close; | ||
1059 | } else { | 1107 | } else { |
1060 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); | 1108 | snprintf(serio->name, sizeof(serio->name), "i8042 AUX%d port", idx); |
1061 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); | 1109 | snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, idx + 1); |