diff options
| -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); |
