diff options
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 4709e15af607..a6512372c7a3 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -574,11 +574,22 @@ static void atkbd_event_work(struct work_struct *work) | |||
574 | 574 | ||
575 | mutex_lock(&atkbd->event_mutex); | 575 | mutex_lock(&atkbd->event_mutex); |
576 | 576 | ||
577 | if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) | 577 | if (!atkbd->enabled) { |
578 | atkbd_set_leds(atkbd); | 578 | /* |
579 | * Serio ports are resumed asynchronously so while driver core | ||
580 | * thinks that device is already fully operational in reality | ||
581 | * it may not be ready yet. In this case we need to keep | ||
582 | * rescheduling till reconnect completes. | ||
583 | */ | ||
584 | schedule_delayed_work(&atkbd->event_work, | ||
585 | msecs_to_jiffies(100)); | ||
586 | } else { | ||
587 | if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) | ||
588 | atkbd_set_leds(atkbd); | ||
579 | 589 | ||
580 | if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) | 590 | if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) |
581 | atkbd_set_repeat_rate(atkbd); | 591 | atkbd_set_repeat_rate(atkbd); |
592 | } | ||
582 | 593 | ||
583 | mutex_unlock(&atkbd->event_mutex); | 594 | mutex_unlock(&atkbd->event_mutex); |
584 | } | 595 | } |
@@ -770,6 +781,30 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra | |||
770 | return 3; | 781 | return 3; |
771 | } | 782 | } |
772 | 783 | ||
784 | static int atkbd_reset_state(struct atkbd *atkbd) | ||
785 | { | ||
786 | struct ps2dev *ps2dev = &atkbd->ps2dev; | ||
787 | unsigned char param[1]; | ||
788 | |||
789 | /* | ||
790 | * Set the LEDs to a predefined state (all off). | ||
791 | */ | ||
792 | |||
793 | param[0] = 0; | ||
794 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS)) | ||
795 | return -1; | ||
796 | |||
797 | /* | ||
798 | * Set autorepeat to fastest possible. | ||
799 | */ | ||
800 | |||
801 | param[0] = 0; | ||
802 | if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP)) | ||
803 | return -1; | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
773 | static int atkbd_activate(struct atkbd *atkbd) | 808 | static int atkbd_activate(struct atkbd *atkbd) |
774 | { | 809 | { |
775 | struct ps2dev *ps2dev = &atkbd->ps2dev; | 810 | struct ps2dev *ps2dev = &atkbd->ps2dev; |
@@ -852,29 +887,6 @@ static unsigned int atkbd_hp_forced_release_keys[] = { | |||
852 | }; | 887 | }; |
853 | 888 | ||
854 | /* | 889 | /* |
855 | * Inventec system with broken key release on volume keys | ||
856 | */ | ||
857 | static unsigned int atkbd_inventec_forced_release_keys[] = { | ||
858 | 0xae, 0xb0, -1U | ||
859 | }; | ||
860 | |||
861 | /* | ||
862 | * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release | ||
863 | * for its volume buttons | ||
864 | */ | ||
865 | static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { | ||
866 | 0xae, 0xb0, -1U | ||
867 | }; | ||
868 | |||
869 | /* | ||
870 | * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate | ||
871 | * release for their volume buttons | ||
872 | */ | ||
873 | static unsigned int atkbd_hp_r4000_forced_release_keys[] = { | ||
874 | 0xae, 0xb0, -1U | ||
875 | }; | ||
876 | |||
877 | /* | ||
878 | * Samsung NC10,NC20 with Fn+F? key release not working | 890 | * Samsung NC10,NC20 with Fn+F? key release not working |
879 | */ | 891 | */ |
880 | static unsigned int atkbd_samsung_forced_release_keys[] = { | 892 | static unsigned int atkbd_samsung_forced_release_keys[] = { |
@@ -882,14 +894,6 @@ static unsigned int atkbd_samsung_forced_release_keys[] = { | |||
882 | }; | 894 | }; |
883 | 895 | ||
884 | /* | 896 | /* |
885 | * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop | ||
886 | * do not generate release events so we have to do it ourselves. | ||
887 | */ | ||
888 | static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = { | ||
889 | 0xb0, 0xae, -1U | ||
890 | }; | ||
891 | |||
892 | /* | ||
893 | * Amilo Pi 3525 key release for Fn+Volume keys not working | 897 | * Amilo Pi 3525 key release for Fn+Volume keys not working |
894 | */ | 898 | */ |
895 | static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = { | 899 | static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = { |
@@ -911,6 +915,14 @@ static unsigned int atkdb_soltech_ta12_forced_release_keys[] = { | |||
911 | }; | 915 | }; |
912 | 916 | ||
913 | /* | 917 | /* |
918 | * Many notebooks don't send key release event for volume up/down | ||
919 | * keys, with key list below common among them | ||
920 | */ | ||
921 | static unsigned int atkbd_volume_forced_release_keys[] = { | ||
922 | 0xae, 0xb0, -1U | ||
923 | }; | ||
924 | |||
925 | /* | ||
914 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 926 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
915 | * according to the selected scancode set | 927 | * according to the selected scancode set |
916 | */ | 928 | */ |
@@ -1087,6 +1099,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
1087 | } | 1099 | } |
1088 | 1100 | ||
1089 | atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); | 1101 | atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); |
1102 | atkbd_reset_state(atkbd); | ||
1090 | atkbd_activate(atkbd); | 1103 | atkbd_activate(atkbd); |
1091 | 1104 | ||
1092 | } else { | 1105 | } else { |
@@ -1267,6 +1280,7 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
1267 | 1280 | ||
1268 | atkbd->dev = new_dev; | 1281 | atkbd->dev = new_dev; |
1269 | atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); | 1282 | atkbd->set = atkbd_select_set(atkbd, atkbd->set, value); |
1283 | atkbd_reset_state(atkbd); | ||
1270 | atkbd_activate(atkbd); | 1284 | atkbd_activate(atkbd); |
1271 | atkbd_set_keycode_table(atkbd); | 1285 | atkbd_set_keycode_table(atkbd); |
1272 | atkbd_set_device_attrs(atkbd); | 1286 | atkbd_set_device_attrs(atkbd); |
@@ -1548,7 +1562,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1548 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), | 1562 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), |
1549 | }, | 1563 | }, |
1550 | .callback = atkbd_setup_forced_release, | 1564 | .callback = atkbd_setup_forced_release, |
1551 | .driver_data = atkbd_hp_zv6100_forced_release_keys, | 1565 | .driver_data = atkbd_volume_forced_release_keys, |
1552 | }, | 1566 | }, |
1553 | { | 1567 | { |
1554 | .ident = "HP Presario R4000", | 1568 | .ident = "HP Presario R4000", |
@@ -1557,7 +1571,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1557 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"), | 1571 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"), |
1558 | }, | 1572 | }, |
1559 | .callback = atkbd_setup_forced_release, | 1573 | .callback = atkbd_setup_forced_release, |
1560 | .driver_data = atkbd_hp_r4000_forced_release_keys, | 1574 | .driver_data = atkbd_volume_forced_release_keys, |
1561 | }, | 1575 | }, |
1562 | { | 1576 | { |
1563 | .ident = "HP Presario R4100", | 1577 | .ident = "HP Presario R4100", |
@@ -1566,7 +1580,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1566 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"), | 1580 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"), |
1567 | }, | 1581 | }, |
1568 | .callback = atkbd_setup_forced_release, | 1582 | .callback = atkbd_setup_forced_release, |
1569 | .driver_data = atkbd_hp_r4000_forced_release_keys, | 1583 | .driver_data = atkbd_volume_forced_release_keys, |
1570 | }, | 1584 | }, |
1571 | { | 1585 | { |
1572 | .ident = "HP Presario R4200", | 1586 | .ident = "HP Presario R4200", |
@@ -1575,7 +1589,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1575 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"), | 1589 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"), |
1576 | }, | 1590 | }, |
1577 | .callback = atkbd_setup_forced_release, | 1591 | .callback = atkbd_setup_forced_release, |
1578 | .driver_data = atkbd_hp_r4000_forced_release_keys, | 1592 | .driver_data = atkbd_volume_forced_release_keys, |
1579 | }, | 1593 | }, |
1580 | { | 1594 | { |
1581 | .ident = "Inventec Symphony", | 1595 | .ident = "Inventec Symphony", |
@@ -1584,7 +1598,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1584 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), | 1598 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), |
1585 | }, | 1599 | }, |
1586 | .callback = atkbd_setup_forced_release, | 1600 | .callback = atkbd_setup_forced_release, |
1587 | .driver_data = atkbd_inventec_forced_release_keys, | 1601 | .driver_data = atkbd_volume_forced_release_keys, |
1588 | }, | 1602 | }, |
1589 | { | 1603 | { |
1590 | .ident = "Samsung NC10", | 1604 | .ident = "Samsung NC10", |
@@ -1620,7 +1634,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1620 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), | 1634 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), |
1621 | }, | 1635 | }, |
1622 | .callback = atkbd_setup_forced_release, | 1636 | .callback = atkbd_setup_forced_release, |
1623 | .driver_data = atkbd_amilo_pa1510_forced_release_keys, | 1637 | .driver_data = atkbd_volume_forced_release_keys, |
1624 | }, | 1638 | }, |
1625 | { | 1639 | { |
1626 | .ident = "Fujitsu Amilo Pi 3525", | 1640 | .ident = "Fujitsu Amilo Pi 3525", |