diff options
-rw-r--r-- | drivers/platform/x86/Kconfig | 2 | ||||
-rw-r--r-- | drivers/platform/x86/toshiba_acpi.c | 191 |
2 files changed, 66 insertions, 127 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1ca392f5c82..b96db80fad9 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -496,6 +496,8 @@ config ACPI_TOSHIBA | |||
496 | depends on INPUT | 496 | depends on INPUT |
497 | depends on RFKILL || RFKILL = n | 497 | depends on RFKILL || RFKILL = n |
498 | select INPUT_POLLDEV | 498 | select INPUT_POLLDEV |
499 | select INPUT_SPARSEKMAP | ||
500 | select BACKLIGHT_CLASS_DEVICE | ||
499 | ---help--- | 501 | ---help--- |
500 | This driver adds support for access to certain system settings | 502 | This driver adds support for access to certain system settings |
501 | on "legacy free" Toshiba laptops. These laptops can be recognized by | 503 | on "legacy free" Toshiba laptops. These laptops can be recognized by |
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 7d67a45bb2b..06f304f46e0 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/platform_device.h> | 48 | #include <linux/platform_device.h> |
49 | #include <linux/rfkill.h> | 49 | #include <linux/rfkill.h> |
50 | #include <linux/input.h> | 50 | #include <linux/input.h> |
51 | #include <linux/input/sparse-keymap.h> | ||
51 | #include <linux/leds.h> | 52 | #include <linux/leds.h> |
52 | #include <linux/slab.h> | 53 | #include <linux/slab.h> |
53 | 54 | ||
@@ -121,36 +122,28 @@ static const struct acpi_device_id toshiba_device_ids[] = { | |||
121 | }; | 122 | }; |
122 | MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); | 123 | MODULE_DEVICE_TABLE(acpi, toshiba_device_ids); |
123 | 124 | ||
124 | struct key_entry { | 125 | static const struct key_entry toshiba_acpi_keymap[] __initconst = { |
125 | char type; | 126 | { KE_KEY, 0x101, { KEY_MUTE } }, |
126 | u16 code; | 127 | { KE_KEY, 0x102, { KEY_ZOOMOUT } }, |
127 | u16 keycode; | 128 | { KE_KEY, 0x103, { KEY_ZOOMIN } }, |
128 | }; | 129 | { KE_KEY, 0x13b, { KEY_COFFEE } }, |
129 | 130 | { KE_KEY, 0x13c, { KEY_BATTERY } }, | |
130 | enum {KE_KEY, KE_END}; | 131 | { KE_KEY, 0x13d, { KEY_SLEEP } }, |
131 | 132 | { KE_KEY, 0x13e, { KEY_SUSPEND } }, | |
132 | static struct key_entry toshiba_acpi_keymap[] = { | 133 | { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } }, |
133 | {KE_KEY, 0x101, KEY_MUTE}, | 134 | { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } }, |
134 | {KE_KEY, 0x102, KEY_ZOOMOUT}, | 135 | { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } }, |
135 | {KE_KEY, 0x103, KEY_ZOOMIN}, | 136 | { KE_KEY, 0x142, { KEY_WLAN } }, |
136 | {KE_KEY, 0x13b, KEY_COFFEE}, | 137 | { KE_KEY, 0x143, { KEY_PROG1 } }, |
137 | {KE_KEY, 0x13c, KEY_BATTERY}, | 138 | { KE_KEY, 0xb05, { KEY_PROG2 } }, |
138 | {KE_KEY, 0x13d, KEY_SLEEP}, | 139 | { KE_KEY, 0xb06, { KEY_WWW } }, |
139 | {KE_KEY, 0x13e, KEY_SUSPEND}, | 140 | { KE_KEY, 0xb07, { KEY_MAIL } }, |
140 | {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE}, | 141 | { KE_KEY, 0xb30, { KEY_STOP } }, |
141 | {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN}, | 142 | { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } }, |
142 | {KE_KEY, 0x141, KEY_BRIGHTNESSUP}, | 143 | { KE_KEY, 0xb32, { KEY_NEXTSONG } }, |
143 | {KE_KEY, 0x142, KEY_WLAN}, | 144 | { KE_KEY, 0xb33, { KEY_PLAYPAUSE } }, |
144 | {KE_KEY, 0x143, KEY_PROG1}, | 145 | { KE_KEY, 0xb5a, { KEY_MEDIA } }, |
145 | {KE_KEY, 0xb05, KEY_PROG2}, | 146 | { KE_END, 0 }, |
146 | {KE_KEY, 0xb06, KEY_WWW}, | ||
147 | {KE_KEY, 0xb07, KEY_MAIL}, | ||
148 | {KE_KEY, 0xb30, KEY_STOP}, | ||
149 | {KE_KEY, 0xb31, KEY_PREVIOUSSONG}, | ||
150 | {KE_KEY, 0xb32, KEY_NEXTSONG}, | ||
151 | {KE_KEY, 0xb33, KEY_PLAYPAUSE}, | ||
152 | {KE_KEY, 0xb5a, KEY_MEDIA}, | ||
153 | {KE_END, 0, 0}, | ||
154 | }; | 147 | }; |
155 | 148 | ||
156 | /* utility | 149 | /* utility |
@@ -852,64 +845,9 @@ static struct backlight_ops toshiba_backlight_data = { | |||
852 | .update_status = set_lcd_status, | 845 | .update_status = set_lcd_status, |
853 | }; | 846 | }; |
854 | 847 | ||
855 | static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code) | ||
856 | { | ||
857 | struct key_entry *key; | ||
858 | |||
859 | for (key = toshiba_acpi_keymap; key->type != KE_END; key++) | ||
860 | if (code == key->code) | ||
861 | return key; | ||
862 | |||
863 | return NULL; | ||
864 | } | ||
865 | |||
866 | static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code) | ||
867 | { | ||
868 | struct key_entry *key; | ||
869 | |||
870 | for (key = toshiba_acpi_keymap; key->type != KE_END; key++) | ||
871 | if (code == key->keycode && key->type == KE_KEY) | ||
872 | return key; | ||
873 | |||
874 | return NULL; | ||
875 | } | ||
876 | |||
877 | static int toshiba_acpi_getkeycode(struct input_dev *dev, | ||
878 | unsigned int scancode, unsigned int *keycode) | ||
879 | { | ||
880 | struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode); | ||
881 | |||
882 | if (key && key->type == KE_KEY) { | ||
883 | *keycode = key->keycode; | ||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | return -EINVAL; | ||
888 | } | ||
889 | |||
890 | static int toshiba_acpi_setkeycode(struct input_dev *dev, | ||
891 | unsigned int scancode, unsigned int keycode) | ||
892 | { | ||
893 | struct key_entry *key; | ||
894 | unsigned int old_keycode; | ||
895 | |||
896 | key = toshiba_acpi_get_entry_by_scancode(scancode); | ||
897 | if (key && key->type == KE_KEY) { | ||
898 | old_keycode = key->keycode; | ||
899 | key->keycode = keycode; | ||
900 | set_bit(keycode, dev->keybit); | ||
901 | if (!toshiba_acpi_get_entry_by_keycode(old_keycode)) | ||
902 | clear_bit(old_keycode, dev->keybit); | ||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | return -EINVAL; | ||
907 | } | ||
908 | |||
909 | static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) | 848 | static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) |
910 | { | 849 | { |
911 | u32 hci_result, value; | 850 | u32 hci_result, value; |
912 | struct key_entry *key; | ||
913 | 851 | ||
914 | if (event != 0x80) | 852 | if (event != 0x80) |
915 | return; | 853 | return; |
@@ -922,19 +860,11 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) | |||
922 | if (value & 0x80) | 860 | if (value & 0x80) |
923 | continue; | 861 | continue; |
924 | 862 | ||
925 | key = toshiba_acpi_get_entry_by_scancode | 863 | if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev, |
926 | (value); | 864 | value, 1, true)) { |
927 | if (!key) { | ||
928 | printk(MY_INFO "Unknown key %x\n", | 865 | printk(MY_INFO "Unknown key %x\n", |
929 | value); | 866 | value); |
930 | continue; | ||
931 | } | 867 | } |
932 | input_report_key(toshiba_acpi.hotkey_dev, | ||
933 | key->keycode, 1); | ||
934 | input_sync(toshiba_acpi.hotkey_dev); | ||
935 | input_report_key(toshiba_acpi.hotkey_dev, | ||
936 | key->keycode, 0); | ||
937 | input_sync(toshiba_acpi.hotkey_dev); | ||
938 | } else if (hci_result == HCI_NOT_SUPPORTED) { | 868 | } else if (hci_result == HCI_NOT_SUPPORTED) { |
939 | /* This is a workaround for an unresolved issue on | 869 | /* This is a workaround for an unresolved issue on |
940 | * some machines where system events sporadically | 870 | * some machines where system events sporadically |
@@ -945,34 +875,17 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context) | |||
945 | } while (hci_result != HCI_EMPTY); | 875 | } while (hci_result != HCI_EMPTY); |
946 | } | 876 | } |
947 | 877 | ||
948 | static int toshiba_acpi_setup_keyboard(char *device) | 878 | static int __init toshiba_acpi_setup_keyboard(char *device) |
949 | { | 879 | { |
950 | acpi_status status; | 880 | acpi_status status; |
951 | acpi_handle handle; | 881 | int error; |
952 | int result; | ||
953 | const struct key_entry *key; | ||
954 | 882 | ||
955 | status = acpi_get_handle(NULL, device, &handle); | 883 | status = acpi_get_handle(NULL, device, &toshiba_acpi.handle); |
956 | if (ACPI_FAILURE(status)) { | 884 | if (ACPI_FAILURE(status)) { |
957 | printk(MY_INFO "Unable to get notification device\n"); | 885 | printk(MY_INFO "Unable to get notification device\n"); |
958 | return -ENODEV; | 886 | return -ENODEV; |
959 | } | 887 | } |
960 | 888 | ||
961 | toshiba_acpi.handle = handle; | ||
962 | |||
963 | status = acpi_evaluate_object(handle, "ENAB", NULL, NULL); | ||
964 | if (ACPI_FAILURE(status)) { | ||
965 | printk(MY_INFO "Unable to enable hotkeys\n"); | ||
966 | return -ENODEV; | ||
967 | } | ||
968 | |||
969 | status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY, | ||
970 | toshiba_acpi_notify, NULL); | ||
971 | if (ACPI_FAILURE(status)) { | ||
972 | printk(MY_INFO "Unable to install hotkey notification\n"); | ||
973 | return -ENODEV; | ||
974 | } | ||
975 | |||
976 | toshiba_acpi.hotkey_dev = input_allocate_device(); | 889 | toshiba_acpi.hotkey_dev = input_allocate_device(); |
977 | if (!toshiba_acpi.hotkey_dev) { | 890 | if (!toshiba_acpi.hotkey_dev) { |
978 | printk(MY_INFO "Unable to register input device\n"); | 891 | printk(MY_INFO "Unable to register input device\n"); |
@@ -982,27 +895,54 @@ static int toshiba_acpi_setup_keyboard(char *device) | |||
982 | toshiba_acpi.hotkey_dev->name = "Toshiba input device"; | 895 | toshiba_acpi.hotkey_dev->name = "Toshiba input device"; |
983 | toshiba_acpi.hotkey_dev->phys = device; | 896 | toshiba_acpi.hotkey_dev->phys = device; |
984 | toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; | 897 | toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST; |
985 | toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode; | ||
986 | toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode; | ||
987 | 898 | ||
988 | for (key = toshiba_acpi_keymap; key->type != KE_END; key++) { | 899 | error = sparse_keymap_setup(toshiba_acpi.hotkey_dev, |
989 | set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit); | 900 | toshiba_acpi_keymap, NULL); |
990 | set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit); | 901 | if (error) |
902 | goto err_free_dev; | ||
903 | |||
904 | status = acpi_install_notify_handler(toshiba_acpi.handle, | ||
905 | ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL); | ||
906 | if (ACPI_FAILURE(status)) { | ||
907 | printk(MY_INFO "Unable to install hotkey notification\n"); | ||
908 | error = -ENODEV; | ||
909 | goto err_free_keymap; | ||
910 | } | ||
911 | |||
912 | status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL); | ||
913 | if (ACPI_FAILURE(status)) { | ||
914 | printk(MY_INFO "Unable to enable hotkeys\n"); | ||
915 | error = -ENODEV; | ||
916 | goto err_remove_notify; | ||
991 | } | 917 | } |
992 | 918 | ||
993 | result = input_register_device(toshiba_acpi.hotkey_dev); | 919 | error = input_register_device(toshiba_acpi.hotkey_dev); |
994 | if (result) { | 920 | if (error) { |
995 | printk(MY_INFO "Unable to register input device\n"); | 921 | printk(MY_INFO "Unable to register input device\n"); |
996 | return result; | 922 | goto err_remove_notify; |
997 | } | 923 | } |
998 | 924 | ||
999 | return 0; | 925 | return 0; |
926 | |||
927 | err_remove_notify: | ||
928 | acpi_remove_notify_handler(toshiba_acpi.handle, | ||
929 | ACPI_DEVICE_NOTIFY, toshiba_acpi_notify); | ||
930 | err_free_keymap: | ||
931 | sparse_keymap_free(toshiba_acpi.hotkey_dev); | ||
932 | err_free_dev: | ||
933 | input_free_device(toshiba_acpi.hotkey_dev); | ||
934 | toshiba_acpi.hotkey_dev = NULL; | ||
935 | return error; | ||
1000 | } | 936 | } |
1001 | 937 | ||
1002 | static void toshiba_acpi_exit(void) | 938 | static void toshiba_acpi_exit(void) |
1003 | { | 939 | { |
1004 | if (toshiba_acpi.hotkey_dev) | 940 | if (toshiba_acpi.hotkey_dev) { |
941 | acpi_remove_notify_handler(toshiba_acpi.handle, | ||
942 | ACPI_DEVICE_NOTIFY, toshiba_acpi_notify); | ||
943 | sparse_keymap_free(toshiba_acpi.hotkey_dev); | ||
1005 | input_unregister_device(toshiba_acpi.hotkey_dev); | 944 | input_unregister_device(toshiba_acpi.hotkey_dev); |
945 | } | ||
1006 | 946 | ||
1007 | if (toshiba_acpi.bt_rfk) { | 947 | if (toshiba_acpi.bt_rfk) { |
1008 | rfkill_unregister(toshiba_acpi.bt_rfk); | 948 | rfkill_unregister(toshiba_acpi.bt_rfk); |
@@ -1017,9 +957,6 @@ static void toshiba_acpi_exit(void) | |||
1017 | if (toshiba_proc_dir) | 957 | if (toshiba_proc_dir) |
1018 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | 958 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); |
1019 | 959 | ||
1020 | acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY, | ||
1021 | toshiba_acpi_notify); | ||
1022 | |||
1023 | if (toshiba_acpi.illumination_installed) | 960 | if (toshiba_acpi.illumination_installed) |
1024 | led_classdev_unregister(&toshiba_led); | 961 | led_classdev_unregister(&toshiba_led); |
1025 | 962 | ||