diff options
author | Roland Scheidegger <sroland@tungstengraphics.com> | 2007-05-08 01:31:40 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-05-08 01:31:40 -0400 |
commit | d2ada5597d33a9108acb2caf912f85cbc9caab1e (patch) | |
tree | c8fe7ebaf381f6874e768b21f978bff887137852 /drivers/input/serio/i8042.c | |
parent | 334d0dd8b660557608142f0f77abc6812b48f08b (diff) |
Input: i8042 - fix AUX port detection with some chips
The i8042 driver fails detection of the AUX port with some chips,
because they apparently do not change the I8042_CTR_AUXDIS bit
immediately. This is known to affect at least HP500/HP510 notebooks,
consequently the built-in touchpad will not work. The patch will simply
reread the value until it gets the expected value or a retry limit is
hit, without touching other workaround code in the same area.
Signed-off-by: Roland Scheidegger <sroland@tungstengraphics.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/serio/i8042.c')
-rw-r--r-- | drivers/input/serio/i8042.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 7c17377a65b9..3888dc307e0c 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
@@ -526,6 +526,33 @@ static irqreturn_t __devinit i8042_aux_test_irq(int irq, void *dev_id) | |||
526 | return IRQ_HANDLED; | 526 | return IRQ_HANDLED; |
527 | } | 527 | } |
528 | 528 | ||
529 | /* | ||
530 | * i8042_toggle_aux - enables or disables AUX port on i8042 via command and | ||
531 | * verifies success by readinng CTR. Used when testing for presence of AUX | ||
532 | * port. | ||
533 | */ | ||
534 | static int __devinit i8042_toggle_aux(int on) | ||
535 | { | ||
536 | unsigned char param; | ||
537 | int i; | ||
538 | |||
539 | if (i8042_command(¶m, | ||
540 | on ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE)) | ||
541 | return -1; | ||
542 | |||
543 | /* some chips need some time to set the I8042_CTR_AUXDIS bit */ | ||
544 | for (i = 0; i < 100; i++) { | ||
545 | udelay(50); | ||
546 | |||
547 | if (i8042_command(¶m, I8042_CMD_CTL_RCTR)) | ||
548 | return -1; | ||
549 | |||
550 | if (!(param & I8042_CTR_AUXDIS) == on) | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | return -1; | ||
555 | } | ||
529 | 556 | ||
530 | /* | 557 | /* |
531 | * i8042_check_aux() applies as much paranoia as it can at detecting | 558 | * i8042_check_aux() applies as much paranoia as it can at detecting |
@@ -580,16 +607,12 @@ static int __devinit i8042_check_aux(void) | |||
580 | * Bit assignment test - filters out PS/2 i8042's in AT mode | 607 | * Bit assignment test - filters out PS/2 i8042's in AT mode |
581 | */ | 608 | */ |
582 | 609 | ||
583 | if (i8042_command(¶m, I8042_CMD_AUX_DISABLE)) | 610 | if (i8042_toggle_aux(0)) { |
584 | return -1; | ||
585 | if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (~param & I8042_CTR_AUXDIS)) { | ||
586 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); | 611 | printk(KERN_WARNING "Failed to disable AUX port, but continuing anyway... Is this a SiS?\n"); |
587 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); | 612 | printk(KERN_WARNING "If AUX port is really absent please use the 'i8042.noaux' option.\n"); |
588 | } | 613 | } |
589 | 614 | ||
590 | if (i8042_command(¶m, I8042_CMD_AUX_ENABLE)) | 615 | if (i8042_toggle_aux(1)) |
591 | return -1; | ||
592 | if (i8042_command(¶m, I8042_CMD_CTL_RCTR) || (param & I8042_CTR_AUXDIS)) | ||
593 | return -1; | 616 | return -1; |
594 | 617 | ||
595 | /* | 618 | /* |