aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/serio/i8042.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-09-09 22:08:15 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-09-11 01:11:35 -0400
commit5ddbc77c3eb54336fcd44b7b66b44784d65677e2 (patch)
tree738c92c53e79c316052bf90e9f912a32345101a2 /drivers/input/serio/i8042.c
parentbd96f37895197563bc1d6d6f7c012b3ae7df1c45 (diff)
Input: i8042 - try disabling and re-enabling AUX port at close
Ever since we switched from having a polling timer to registering IRQ handlers for both keyboard and AUX ports at the driver registration time, on certain boxes probing for a mouse results in keyboard stopping working. The only real difference between old and new way is that before we disabled ports after unsuccessful probe whereas now we leave them as is. Try to emulate the old behavior by disabling and immediately re-enabling AUX and KBD ports when corresponding serio port is being closed. Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r--drivers/input/serio/i8042.c50
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
273static 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
399static int i8042_enable_kbd_port(void) 442static 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);