diff options
Diffstat (limited to 'drivers/input/keyboard/atkbd.c')
-rw-r--r-- | drivers/input/keyboard/atkbd.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index a6512372c7a3..28e6110d1ff8 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
@@ -233,6 +233,7 @@ struct atkbd { | |||
233 | */ | 233 | */ |
234 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); | 234 | static void (*atkbd_platform_fixup)(struct atkbd *, const void *data); |
235 | static void *atkbd_platform_fixup_data; | 235 | static void *atkbd_platform_fixup_data; |
236 | static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int); | ||
236 | 237 | ||
237 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, | 238 | static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, |
238 | ssize_t (*handler)(struct atkbd *, char *)); | 239 | ssize_t (*handler)(struct atkbd *, char *)); |
@@ -393,6 +394,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
393 | 394 | ||
394 | input_event(dev, EV_MSC, MSC_RAW, code); | 395 | input_event(dev, EV_MSC, MSC_RAW, code); |
395 | 396 | ||
397 | if (atkbd_platform_scancode_fixup) | ||
398 | code = atkbd_platform_scancode_fixup(atkbd, code); | ||
399 | |||
396 | if (atkbd->translated) { | 400 | if (atkbd->translated) { |
397 | 401 | ||
398 | if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { | 402 | if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) { |
@@ -923,6 +927,22 @@ static unsigned int atkbd_volume_forced_release_keys[] = { | |||
923 | }; | 927 | }; |
924 | 928 | ||
925 | /* | 929 | /* |
930 | * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas | ||
931 | * they should be generating e4-e6 (0x80 | code). | ||
932 | */ | ||
933 | static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd, | ||
934 | unsigned int code) | ||
935 | { | ||
936 | if (atkbd->translated && atkbd->emul == 1 && | ||
937 | (code == 0x64 || code == 0x65 || code == 0x66)) { | ||
938 | atkbd->emul = 0; | ||
939 | code |= 0x80; | ||
940 | } | ||
941 | |||
942 | return code; | ||
943 | } | ||
944 | |||
945 | /* | ||
926 | * atkbd_set_keycode_table() initializes keyboard's keycode table | 946 | * atkbd_set_keycode_table() initializes keyboard's keycode table |
927 | * according to the selected scancode set | 947 | * according to the selected scancode set |
928 | */ | 948 | */ |
@@ -1154,6 +1174,18 @@ static int atkbd_reconnect(struct serio *serio) | |||
1154 | return -1; | 1174 | return -1; |
1155 | 1175 | ||
1156 | atkbd_activate(atkbd); | 1176 | atkbd_activate(atkbd); |
1177 | |||
1178 | /* | ||
1179 | * Restore LED state and repeat rate. While input core | ||
1180 | * will do this for us at resume time reconnect may happen | ||
1181 | * because user requested it via sysfs or simply because | ||
1182 | * keyboard was unplugged and plugged in again so we need | ||
1183 | * to do it ourselves here. | ||
1184 | */ | ||
1185 | atkbd_set_leds(atkbd); | ||
1186 | if (!atkbd->softrepeat) | ||
1187 | atkbd_set_repeat_rate(atkbd); | ||
1188 | |||
1157 | } | 1189 | } |
1158 | 1190 | ||
1159 | atkbd_enable(atkbd); | 1191 | atkbd_enable(atkbd); |
@@ -1402,6 +1434,7 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) | |||
1402 | 1434 | ||
1403 | atkbd->dev = new_dev; | 1435 | atkbd->dev = new_dev; |
1404 | atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); | 1436 | atkbd->set = atkbd_select_set(atkbd, value, atkbd->extra); |
1437 | atkbd_reset_state(atkbd); | ||
1405 | atkbd_activate(atkbd); | 1438 | atkbd_activate(atkbd); |
1406 | atkbd_set_keycode_table(atkbd); | 1439 | atkbd_set_keycode_table(atkbd); |
1407 | atkbd_set_device_attrs(atkbd); | 1440 | atkbd_set_device_attrs(atkbd); |
@@ -1527,6 +1560,13 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id) | |||
1527 | return 0; | 1560 | return 0; |
1528 | } | 1561 | } |
1529 | 1562 | ||
1563 | static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) | ||
1564 | { | ||
1565 | atkbd_platform_scancode_fixup = id->driver_data; | ||
1566 | |||
1567 | return 0; | ||
1568 | } | ||
1569 | |||
1530 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | 1570 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { |
1531 | { | 1571 | { |
1532 | .ident = "Dell Laptop", | 1572 | .ident = "Dell Laptop", |
@@ -1663,6 +1703,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
1663 | .callback = atkbd_setup_forced_release, | 1703 | .callback = atkbd_setup_forced_release, |
1664 | .driver_data = atkdb_soltech_ta12_forced_release_keys, | 1704 | .driver_data = atkdb_soltech_ta12_forced_release_keys, |
1665 | }, | 1705 | }, |
1706 | { | ||
1707 | .ident = "OQO Model 01+", | ||
1708 | .matches = { | ||
1709 | DMI_MATCH(DMI_SYS_VENDOR, "OQO"), | ||
1710 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), | ||
1711 | }, | ||
1712 | .callback = atkbd_setup_scancode_fixup, | ||
1713 | .driver_data = atkbd_oqo_01plus_scancode_fixup, | ||
1714 | }, | ||
1666 | { } | 1715 | { } |
1667 | }; | 1716 | }; |
1668 | 1717 | ||