diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/asus-laptop.c | 176 | ||||
-rw-r--r-- | drivers/platform/x86/asus_acpi.c | 16 | ||||
-rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 164 | ||||
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 6 | ||||
-rw-r--r-- | drivers/platform/x86/panasonic-laptop.c | 2 |
6 files changed, 330 insertions, 35 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1a266d4ab5f1..94363115a42a 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
@@ -42,6 +42,7 @@ config ASUS_LAPTOP | |||
42 | depends on LEDS_CLASS | 42 | depends on LEDS_CLASS |
43 | depends on NEW_LEDS | 43 | depends on NEW_LEDS |
44 | depends on BACKLIGHT_CLASS_DEVICE | 44 | depends on BACKLIGHT_CLASS_DEVICE |
45 | depends on INPUT | ||
45 | ---help--- | 46 | ---help--- |
46 | This is the new Linux driver for Asus laptops. It may also support some | 47 | This is the new Linux driver for Asus laptops. It may also support some |
47 | MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate | 48 | MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate |
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 8fb8b3591048..56af6cf385b0 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <acpi/acpi_drivers.h> | 46 | #include <acpi/acpi_drivers.h> |
47 | #include <acpi/acpi_bus.h> | 47 | #include <acpi/acpi_bus.h> |
48 | #include <asm/uaccess.h> | 48 | #include <asm/uaccess.h> |
49 | #include <linux/input.h> | ||
49 | 50 | ||
50 | #define ASUS_LAPTOP_VERSION "0.42" | 51 | #define ASUS_LAPTOP_VERSION "0.42" |
51 | 52 | ||
@@ -181,6 +182,8 @@ struct asus_hotk { | |||
181 | u8 light_level; //light sensor level | 182 | u8 light_level; //light sensor level |
182 | u8 light_switch; //light sensor switch value | 183 | u8 light_switch; //light sensor switch value |
183 | u16 event_count[128]; //count for each event TODO make this better | 184 | u16 event_count[128]; //count for each event TODO make this better |
185 | struct input_dev *inputdev; | ||
186 | u16 *keycode_map; | ||
184 | }; | 187 | }; |
185 | 188 | ||
186 | /* | 189 | /* |
@@ -250,6 +253,37 @@ ASUS_LED(rled, "record"); | |||
250 | ASUS_LED(pled, "phone"); | 253 | ASUS_LED(pled, "phone"); |
251 | ASUS_LED(gled, "gaming"); | 254 | ASUS_LED(gled, "gaming"); |
252 | 255 | ||
256 | struct key_entry { | ||
257 | char type; | ||
258 | u8 code; | ||
259 | u16 keycode; | ||
260 | }; | ||
261 | |||
262 | enum { KE_KEY, KE_END }; | ||
263 | |||
264 | static struct key_entry asus_keymap[] = { | ||
265 | {KE_KEY, 0x30, KEY_VOLUMEUP}, | ||
266 | {KE_KEY, 0x31, KEY_VOLUMEDOWN}, | ||
267 | {KE_KEY, 0x32, KEY_MUTE}, | ||
268 | {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE}, | ||
269 | {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE}, | ||
270 | {KE_KEY, 0x40, KEY_PREVIOUSSONG}, | ||
271 | {KE_KEY, 0x41, KEY_NEXTSONG}, | ||
272 | {KE_KEY, 0x43, KEY_STOP}, | ||
273 | {KE_KEY, 0x45, KEY_PLAYPAUSE}, | ||
274 | {KE_KEY, 0x50, KEY_EMAIL}, | ||
275 | {KE_KEY, 0x51, KEY_WWW}, | ||
276 | {KE_KEY, 0x5C, BTN_EXTRA}, /* Performance */ | ||
277 | {KE_KEY, 0x5D, KEY_WLAN}, | ||
278 | {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, | ||
279 | {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ | ||
280 | {KE_KEY, 0x82, KEY_CAMERA}, | ||
281 | {KE_KEY, 0x8A, KEY_TV}, | ||
282 | {KE_KEY, 0x95, KEY_MEDIA}, | ||
283 | {KE_KEY, 0x99, KEY_PHONE}, | ||
284 | {KE_END, 0}, | ||
285 | }; | ||
286 | |||
253 | /* | 287 | /* |
254 | * This function evaluates an ACPI method, given an int as parameter, the | 288 | * This function evaluates an ACPI method, given an int as parameter, the |
255 | * method is searched within the scope of the handle, can be NULL. The output | 289 | * method is searched within the scope of the handle, can be NULL. The output |
@@ -720,8 +754,68 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, | |||
720 | return store_status(buf, count, NULL, GPS_ON); | 754 | return store_status(buf, count, NULL, GPS_ON); |
721 | } | 755 | } |
722 | 756 | ||
757 | /* | ||
758 | * Hotkey functions | ||
759 | */ | ||
760 | static struct key_entry *asus_get_entry_by_scancode(int code) | ||
761 | { | ||
762 | struct key_entry *key; | ||
763 | |||
764 | for (key = asus_keymap; key->type != KE_END; key++) | ||
765 | if (code == key->code) | ||
766 | return key; | ||
767 | |||
768 | return NULL; | ||
769 | } | ||
770 | |||
771 | static struct key_entry *asus_get_entry_by_keycode(int code) | ||
772 | { | ||
773 | struct key_entry *key; | ||
774 | |||
775 | for (key = asus_keymap; key->type != KE_END; key++) | ||
776 | if (code == key->keycode && key->type == KE_KEY) | ||
777 | return key; | ||
778 | |||
779 | return NULL; | ||
780 | } | ||
781 | |||
782 | static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) | ||
783 | { | ||
784 | struct key_entry *key = asus_get_entry_by_scancode(scancode); | ||
785 | |||
786 | if (key && key->type == KE_KEY) { | ||
787 | *keycode = key->keycode; | ||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | return -EINVAL; | ||
792 | } | ||
793 | |||
794 | static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) | ||
795 | { | ||
796 | struct key_entry *key; | ||
797 | int old_keycode; | ||
798 | |||
799 | if (keycode < 0 || keycode > KEY_MAX) | ||
800 | return -EINVAL; | ||
801 | |||
802 | key = asus_get_entry_by_scancode(scancode); | ||
803 | if (key && key->type == KE_KEY) { | ||
804 | old_keycode = key->keycode; | ||
805 | key->keycode = keycode; | ||
806 | set_bit(keycode, dev->keybit); | ||
807 | if (!asus_get_entry_by_keycode(old_keycode)) | ||
808 | clear_bit(old_keycode, dev->keybit); | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | return -EINVAL; | ||
813 | } | ||
814 | |||
723 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | 815 | static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) |
724 | { | 816 | { |
817 | static struct key_entry *key; | ||
818 | |||
725 | /* TODO Find a better way to handle events count. */ | 819 | /* TODO Find a better way to handle events count. */ |
726 | if (!hotk) | 820 | if (!hotk) |
727 | return; | 821 | return; |
@@ -738,10 +832,24 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
738 | lcd_blank(FB_BLANK_POWERDOWN); | 832 | lcd_blank(FB_BLANK_POWERDOWN); |
739 | } | 833 | } |
740 | 834 | ||
741 | acpi_bus_generate_proc_event(hotk->device, event, | 835 | acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, |
742 | hotk->event_count[event % 128]++); | 836 | dev_name(&hotk->device->dev), event, |
743 | 837 | hotk->event_count[event % 128]++); | |
744 | return; | 838 | |
839 | if (hotk->inputdev) { | ||
840 | key = asus_get_entry_by_scancode(event); | ||
841 | if (!key) | ||
842 | return ; | ||
843 | |||
844 | switch (key->type) { | ||
845 | case KE_KEY: | ||
846 | input_report_key(hotk->inputdev, key->keycode, 1); | ||
847 | input_sync(hotk->inputdev); | ||
848 | input_report_key(hotk->inputdev, key->keycode, 0); | ||
849 | input_sync(hotk->inputdev); | ||
850 | break; | ||
851 | } | ||
852 | } | ||
745 | } | 853 | } |
746 | 854 | ||
747 | #define ASUS_CREATE_DEVICE_ATTR(_name) \ | 855 | #define ASUS_CREATE_DEVICE_ATTR(_name) \ |
@@ -959,6 +1067,38 @@ static int asus_hotk_get_info(void) | |||
959 | return AE_OK; | 1067 | return AE_OK; |
960 | } | 1068 | } |
961 | 1069 | ||
1070 | static int asus_input_init(void) | ||
1071 | { | ||
1072 | const struct key_entry *key; | ||
1073 | int result; | ||
1074 | |||
1075 | hotk->inputdev = input_allocate_device(); | ||
1076 | if (!hotk->inputdev) { | ||
1077 | printk(ASUS_INFO "Unable to allocate input device\n"); | ||
1078 | return 0; | ||
1079 | } | ||
1080 | hotk->inputdev->name = "Asus Laptop extra buttons"; | ||
1081 | hotk->inputdev->phys = ASUS_HOTK_FILE "/input0"; | ||
1082 | hotk->inputdev->id.bustype = BUS_HOST; | ||
1083 | hotk->inputdev->getkeycode = asus_getkeycode; | ||
1084 | hotk->inputdev->setkeycode = asus_setkeycode; | ||
1085 | |||
1086 | for (key = asus_keymap; key->type != KE_END; key++) { | ||
1087 | switch (key->type) { | ||
1088 | case KE_KEY: | ||
1089 | set_bit(EV_KEY, hotk->inputdev->evbit); | ||
1090 | set_bit(key->keycode, hotk->inputdev->keybit); | ||
1091 | break; | ||
1092 | } | ||
1093 | } | ||
1094 | result = input_register_device(hotk->inputdev); | ||
1095 | if (result) { | ||
1096 | printk(ASUS_INFO "Unable to register input device\n"); | ||
1097 | input_free_device(hotk->inputdev); | ||
1098 | } | ||
1099 | return result; | ||
1100 | } | ||
1101 | |||
962 | static int asus_hotk_check(void) | 1102 | static int asus_hotk_check(void) |
963 | { | 1103 | { |
964 | int result = 0; | 1104 | int result = 0; |
@@ -1044,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device) | |||
1044 | /* GPS is on by default */ | 1184 | /* GPS is on by default */ |
1045 | write_status(NULL, 1, GPS_ON); | 1185 | write_status(NULL, 1, GPS_ON); |
1046 | 1186 | ||
1047 | end: | 1187 | end: |
1048 | if (result) { | 1188 | if (result) { |
1049 | kfree(hotk->name); | 1189 | kfree(hotk->name); |
1050 | kfree(hotk); | 1190 | kfree(hotk); |
@@ -1091,10 +1231,17 @@ static void asus_led_exit(void) | |||
1091 | ASUS_LED_UNREGISTER(gled); | 1231 | ASUS_LED_UNREGISTER(gled); |
1092 | } | 1232 | } |
1093 | 1233 | ||
1234 | static void asus_input_exit(void) | ||
1235 | { | ||
1236 | if (hotk->inputdev) | ||
1237 | input_unregister_device(hotk->inputdev); | ||
1238 | } | ||
1239 | |||
1094 | static void __exit asus_laptop_exit(void) | 1240 | static void __exit asus_laptop_exit(void) |
1095 | { | 1241 | { |
1096 | asus_backlight_exit(); | 1242 | asus_backlight_exit(); |
1097 | asus_led_exit(); | 1243 | asus_led_exit(); |
1244 | asus_input_exit(); | ||
1098 | 1245 | ||
1099 | acpi_bus_unregister_driver(&asus_hotk_driver); | 1246 | acpi_bus_unregister_driver(&asus_hotk_driver); |
1100 | sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); | 1247 | sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); |
@@ -1216,6 +1363,10 @@ static int __init asus_laptop_init(void) | |||
1216 | printk(ASUS_INFO "Brightness ignored, must be controlled by " | 1363 | printk(ASUS_INFO "Brightness ignored, must be controlled by " |
1217 | "ACPI video driver\n"); | 1364 | "ACPI video driver\n"); |
1218 | 1365 | ||
1366 | result = asus_input_init(); | ||
1367 | if (result) | ||
1368 | goto fail_input; | ||
1369 | |||
1219 | result = asus_led_init(dev); | 1370 | result = asus_led_init(dev); |
1220 | if (result) | 1371 | if (result) |
1221 | goto fail_led; | 1372 | goto fail_led; |
@@ -1242,22 +1393,25 @@ static int __init asus_laptop_init(void) | |||
1242 | 1393 | ||
1243 | return 0; | 1394 | return 0; |
1244 | 1395 | ||
1245 | fail_sysfs: | 1396 | fail_sysfs: |
1246 | platform_device_del(asuspf_device); | 1397 | platform_device_del(asuspf_device); |
1247 | 1398 | ||
1248 | fail_platform_device2: | 1399 | fail_platform_device2: |
1249 | platform_device_put(asuspf_device); | 1400 | platform_device_put(asuspf_device); |
1250 | 1401 | ||
1251 | fail_platform_device1: | 1402 | fail_platform_device1: |
1252 | platform_driver_unregister(&asuspf_driver); | 1403 | platform_driver_unregister(&asuspf_driver); |
1253 | 1404 | ||
1254 | fail_platform_driver: | 1405 | fail_platform_driver: |
1255 | asus_led_exit(); | 1406 | asus_led_exit(); |
1256 | 1407 | ||
1257 | fail_led: | 1408 | fail_led: |
1409 | asus_input_exit(); | ||
1410 | |||
1411 | fail_input: | ||
1258 | asus_backlight_exit(); | 1412 | asus_backlight_exit(); |
1259 | 1413 | ||
1260 | fail_backlight: | 1414 | fail_backlight: |
1261 | 1415 | ||
1262 | return result; | 1416 | return result; |
1263 | } | 1417 | } |
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 1e74988c7b2d..d63f26e666a4 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c | |||
@@ -143,6 +143,7 @@ struct asus_hotk { | |||
143 | S1300N, S5200N*/ | 143 | S1300N, S5200N*/ |
144 | A4S, /* Z81sp */ | 144 | A4S, /* Z81sp */ |
145 | F3Sa, /* (Centrino) */ | 145 | F3Sa, /* (Centrino) */ |
146 | R1F, | ||
146 | END_MODEL | 147 | END_MODEL |
147 | } model; /* Models currently supported */ | 148 | } model; /* Models currently supported */ |
148 | u16 event_count[128]; /* Count for each event TODO make this better */ | 149 | u16 event_count[128]; /* Count for each event TODO make this better */ |
@@ -420,7 +421,18 @@ static struct model_data model_conf[END_MODEL] = { | |||
420 | .display_get = "\\ADVG", | 421 | .display_get = "\\ADVG", |
421 | .display_set = "SDSP", | 422 | .display_set = "SDSP", |
422 | }, | 423 | }, |
423 | 424 | { | |
425 | .name = "R1F", | ||
426 | .mt_bt_switch = "BLED", | ||
427 | .mt_mled = "MLED", | ||
428 | .mt_wled = "WLED", | ||
429 | .mt_lcd_switch = "\\Q10", | ||
430 | .lcd_status = "\\GP06", | ||
431 | .brightness_set = "SPLV", | ||
432 | .brightness_get = "GPLV", | ||
433 | .display_set = "SDSP", | ||
434 | .display_get = "\\INFB" | ||
435 | } | ||
424 | }; | 436 | }; |
425 | 437 | ||
426 | /* procdir we use */ | 438 | /* procdir we use */ |
@@ -1165,6 +1177,8 @@ static int asus_model_match(char *model) | |||
1165 | return W3V; | 1177 | return W3V; |
1166 | else if (strncmp(model, "W5A", 3) == 0) | 1178 | else if (strncmp(model, "W5A", 3) == 0) |
1167 | return W5A; | 1179 | return W5A; |
1180 | else if (strncmp(model, "R1F", 3) == 0) | ||
1181 | return R1F; | ||
1168 | else if (strncmp(model, "A4S", 3) == 0) | 1182 | else if (strncmp(model, "A4S", 3) == 0) |
1169 | return A4S; | 1183 | return A4S; |
1170 | else if (strncmp(model, "F3Sa", 4) == 0) | 1184 | else if (strncmp(model, "F3Sa", 4) == 0) |
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9d93cb971e59..786ed8661cb0 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
32 | #include <linux/rfkill.h> | 32 | #include <linux/rfkill.h> |
33 | #include <linux/pci.h> | ||
33 | 34 | ||
34 | #define EEEPC_LAPTOP_VERSION "0.1" | 35 | #define EEEPC_LAPTOP_VERSION "0.1" |
35 | 36 | ||
@@ -161,6 +162,10 @@ static struct key_entry eeepc_keymap[] = { | |||
161 | {KE_KEY, 0x13, KEY_MUTE }, | 162 | {KE_KEY, 0x13, KEY_MUTE }, |
162 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, | 163 | {KE_KEY, 0x14, KEY_VOLUMEDOWN }, |
163 | {KE_KEY, 0x15, KEY_VOLUMEUP }, | 164 | {KE_KEY, 0x15, KEY_VOLUMEUP }, |
165 | {KE_KEY, 0x1a, KEY_COFFEE }, | ||
166 | {KE_KEY, 0x1b, KEY_ZOOM }, | ||
167 | {KE_KEY, 0x1c, KEY_PROG2 }, | ||
168 | {KE_KEY, 0x1d, KEY_PROG3 }, | ||
164 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, | 169 | {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, |
165 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, | 170 | {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, |
166 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, | 171 | {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, |
@@ -510,7 +515,43 @@ static int eeepc_hotk_check(void) | |||
510 | static void notify_brn(void) | 515 | static void notify_brn(void) |
511 | { | 516 | { |
512 | struct backlight_device *bd = eeepc_backlight_device; | 517 | struct backlight_device *bd = eeepc_backlight_device; |
513 | bd->props.brightness = read_brightness(bd); | 518 | if (bd) |
519 | bd->props.brightness = read_brightness(bd); | ||
520 | } | ||
521 | |||
522 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | ||
523 | { | ||
524 | struct pci_dev *dev; | ||
525 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
526 | |||
527 | if (event != ACPI_NOTIFY_BUS_CHECK) | ||
528 | return; | ||
529 | |||
530 | if (!bus) { | ||
531 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | ||
532 | return; | ||
533 | } | ||
534 | |||
535 | if (get_acpi(CM_ASL_WLAN) == 1) { | ||
536 | dev = pci_get_slot(bus, 0); | ||
537 | if (dev) { | ||
538 | /* Device already present */ | ||
539 | pci_dev_put(dev); | ||
540 | return; | ||
541 | } | ||
542 | dev = pci_scan_single_device(bus, 0); | ||
543 | if (dev) { | ||
544 | pci_bus_assign_resources(bus); | ||
545 | if (pci_bus_add_device(dev)) | ||
546 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | ||
547 | } | ||
548 | } else { | ||
549 | dev = pci_get_slot(bus, 0); | ||
550 | if (dev) { | ||
551 | pci_remove_bus_device(dev); | ||
552 | pci_dev_put(dev); | ||
553 | } | ||
554 | } | ||
514 | } | 555 | } |
515 | 556 | ||
516 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | 557 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) |
@@ -520,8 +561,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
520 | return; | 561 | return; |
521 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | 562 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) |
522 | notify_brn(); | 563 | notify_brn(); |
523 | acpi_bus_generate_proc_event(ehotk->device, event, | 564 | acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, |
524 | ehotk->event_count[event % 128]++); | 565 | dev_name(&ehotk->device->dev), event, |
566 | ehotk->event_count[event % 128]++); | ||
525 | if (ehotk->inputdev) { | 567 | if (ehotk->inputdev) { |
526 | key = eepc_get_entry_by_scancode(event); | 568 | key = eepc_get_entry_by_scancode(event); |
527 | if (key) { | 569 | if (key) { |
@@ -539,6 +581,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
539 | } | 581 | } |
540 | } | 582 | } |
541 | 583 | ||
584 | static int eeepc_register_rfkill_notifier(char *node) | ||
585 | { | ||
586 | acpi_status status = AE_OK; | ||
587 | acpi_handle handle; | ||
588 | |||
589 | status = acpi_get_handle(NULL, node, &handle); | ||
590 | |||
591 | if (ACPI_SUCCESS(status)) { | ||
592 | status = acpi_install_notify_handler(handle, | ||
593 | ACPI_SYSTEM_NOTIFY, | ||
594 | eeepc_rfkill_notify, | ||
595 | NULL); | ||
596 | if (ACPI_FAILURE(status)) | ||
597 | printk(EEEPC_WARNING | ||
598 | "Failed to register notify on %s\n", node); | ||
599 | } else | ||
600 | return -ENODEV; | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static void eeepc_unregister_rfkill_notifier(char *node) | ||
606 | { | ||
607 | acpi_status status = AE_OK; | ||
608 | acpi_handle handle; | ||
609 | |||
610 | status = acpi_get_handle(NULL, node, &handle); | ||
611 | |||
612 | if (ACPI_SUCCESS(status)) { | ||
613 | status = acpi_remove_notify_handler(handle, | ||
614 | ACPI_SYSTEM_NOTIFY, | ||
615 | eeepc_rfkill_notify); | ||
616 | if (ACPI_FAILURE(status)) | ||
617 | printk(EEEPC_ERR | ||
618 | "Error removing rfkill notify handler %s\n", | ||
619 | node); | ||
620 | } | ||
621 | } | ||
622 | |||
542 | static int eeepc_hotk_add(struct acpi_device *device) | 623 | static int eeepc_hotk_add(struct acpi_device *device) |
543 | { | 624 | { |
544 | acpi_status status = AE_OK; | 625 | acpi_status status = AE_OK; |
@@ -558,7 +639,7 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
558 | ehotk->device = device; | 639 | ehotk->device = device; |
559 | result = eeepc_hotk_check(); | 640 | result = eeepc_hotk_check(); |
560 | if (result) | 641 | if (result) |
561 | goto end; | 642 | goto ehotk_fail; |
562 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | 643 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, |
563 | eeepc_hotk_notify, ehotk); | 644 | eeepc_hotk_notify, ehotk); |
564 | if (ACPI_FAILURE(status)) | 645 | if (ACPI_FAILURE(status)) |
@@ -569,18 +650,25 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
569 | RFKILL_TYPE_WLAN); | 650 | RFKILL_TYPE_WLAN); |
570 | 651 | ||
571 | if (!ehotk->eeepc_wlan_rfkill) | 652 | if (!ehotk->eeepc_wlan_rfkill) |
572 | goto end; | 653 | goto wlan_fail; |
573 | 654 | ||
574 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; | 655 | ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; |
575 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; | 656 | ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; |
576 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; | 657 | ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; |
577 | if (get_acpi(CM_ASL_WLAN) == 1) | 658 | if (get_acpi(CM_ASL_WLAN) == 1) { |
578 | ehotk->eeepc_wlan_rfkill->state = | 659 | ehotk->eeepc_wlan_rfkill->state = |
579 | RFKILL_STATE_UNBLOCKED; | 660 | RFKILL_STATE_UNBLOCKED; |
580 | else | 661 | rfkill_set_default(RFKILL_TYPE_WLAN, |
662 | RFKILL_STATE_UNBLOCKED); | ||
663 | } else { | ||
581 | ehotk->eeepc_wlan_rfkill->state = | 664 | ehotk->eeepc_wlan_rfkill->state = |
582 | RFKILL_STATE_SOFT_BLOCKED; | 665 | RFKILL_STATE_SOFT_BLOCKED; |
583 | rfkill_register(ehotk->eeepc_wlan_rfkill); | 666 | rfkill_set_default(RFKILL_TYPE_WLAN, |
667 | RFKILL_STATE_SOFT_BLOCKED); | ||
668 | } | ||
669 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
670 | if (result) | ||
671 | goto wlan_fail; | ||
584 | } | 672 | } |
585 | 673 | ||
586 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | 674 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { |
@@ -588,27 +676,47 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
588 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); | 676 | rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); |
589 | 677 | ||
590 | if (!ehotk->eeepc_bluetooth_rfkill) | 678 | if (!ehotk->eeepc_bluetooth_rfkill) |
591 | goto end; | 679 | goto bluetooth_fail; |
592 | 680 | ||
593 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; | 681 | ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; |
594 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = | 682 | ehotk->eeepc_bluetooth_rfkill->toggle_radio = |
595 | eeepc_bluetooth_rfkill_set; | 683 | eeepc_bluetooth_rfkill_set; |
596 | ehotk->eeepc_bluetooth_rfkill->get_state = | 684 | ehotk->eeepc_bluetooth_rfkill->get_state = |
597 | eeepc_bluetooth_rfkill_state; | 685 | eeepc_bluetooth_rfkill_state; |
598 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) | 686 | if (get_acpi(CM_ASL_BLUETOOTH) == 1) { |
599 | ehotk->eeepc_bluetooth_rfkill->state = | 687 | ehotk->eeepc_bluetooth_rfkill->state = |
600 | RFKILL_STATE_UNBLOCKED; | 688 | RFKILL_STATE_UNBLOCKED; |
601 | else | 689 | rfkill_set_default(RFKILL_TYPE_BLUETOOTH, |
690 | RFKILL_STATE_UNBLOCKED); | ||
691 | } else { | ||
602 | ehotk->eeepc_bluetooth_rfkill->state = | 692 | ehotk->eeepc_bluetooth_rfkill->state = |
603 | RFKILL_STATE_SOFT_BLOCKED; | 693 | RFKILL_STATE_SOFT_BLOCKED; |
604 | rfkill_register(ehotk->eeepc_bluetooth_rfkill); | 694 | rfkill_set_default(RFKILL_TYPE_BLUETOOTH, |
605 | } | 695 | RFKILL_STATE_SOFT_BLOCKED); |
696 | } | ||
606 | 697 | ||
607 | end: | 698 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); |
608 | if (result) { | 699 | if (result) |
609 | kfree(ehotk); | 700 | goto bluetooth_fail; |
610 | ehotk = NULL; | ||
611 | } | 701 | } |
702 | |||
703 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
704 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
705 | |||
706 | return 0; | ||
707 | |||
708 | bluetooth_fail: | ||
709 | if (ehotk->eeepc_bluetooth_rfkill) | ||
710 | rfkill_free(ehotk->eeepc_bluetooth_rfkill); | ||
711 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
712 | ehotk->eeepc_wlan_rfkill = NULL; | ||
713 | wlan_fail: | ||
714 | if (ehotk->eeepc_wlan_rfkill) | ||
715 | rfkill_free(ehotk->eeepc_wlan_rfkill); | ||
716 | ehotk_fail: | ||
717 | kfree(ehotk); | ||
718 | ehotk = NULL; | ||
719 | |||
612 | return result; | 720 | return result; |
613 | } | 721 | } |
614 | 722 | ||
@@ -622,6 +730,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
622 | eeepc_hotk_notify); | 730 | eeepc_hotk_notify); |
623 | if (ACPI_FAILURE(status)) | 731 | if (ACPI_FAILURE(status)) |
624 | printk(EEEPC_ERR "Error removing notify handler\n"); | 732 | printk(EEEPC_ERR "Error removing notify handler\n"); |
733 | |||
734 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
735 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
736 | |||
625 | kfree(ehotk); | 737 | kfree(ehotk); |
626 | return 0; | 738 | return 0; |
627 | } | 739 | } |
@@ -737,13 +849,21 @@ static void eeepc_backlight_exit(void) | |||
737 | { | 849 | { |
738 | if (eeepc_backlight_device) | 850 | if (eeepc_backlight_device) |
739 | backlight_device_unregister(eeepc_backlight_device); | 851 | backlight_device_unregister(eeepc_backlight_device); |
740 | if (ehotk->inputdev) | 852 | eeepc_backlight_device = NULL; |
741 | input_unregister_device(ehotk->inputdev); | 853 | } |
854 | |||
855 | static void eeepc_rfkill_exit(void) | ||
856 | { | ||
742 | if (ehotk->eeepc_wlan_rfkill) | 857 | if (ehotk->eeepc_wlan_rfkill) |
743 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 858 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); |
744 | if (ehotk->eeepc_bluetooth_rfkill) | 859 | if (ehotk->eeepc_bluetooth_rfkill) |
745 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 860 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); |
746 | eeepc_backlight_device = NULL; | 861 | } |
862 | |||
863 | static void eeepc_input_exit(void) | ||
864 | { | ||
865 | if (ehotk->inputdev) | ||
866 | input_unregister_device(ehotk->inputdev); | ||
747 | } | 867 | } |
748 | 868 | ||
749 | static void eeepc_hwmon_exit(void) | 869 | static void eeepc_hwmon_exit(void) |
@@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void) | |||
762 | static void __exit eeepc_laptop_exit(void) | 882 | static void __exit eeepc_laptop_exit(void) |
763 | { | 883 | { |
764 | eeepc_backlight_exit(); | 884 | eeepc_backlight_exit(); |
885 | eeepc_rfkill_exit(); | ||
886 | eeepc_input_exit(); | ||
765 | eeepc_hwmon_exit(); | 887 | eeepc_hwmon_exit(); |
766 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 888 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
767 | sysfs_remove_group(&platform_device->dev.kobj, | 889 | sysfs_remove_group(&platform_device->dev.kobj, |
@@ -865,6 +987,8 @@ fail_platform_driver: | |||
865 | fail_hwmon: | 987 | fail_hwmon: |
866 | eeepc_backlight_exit(); | 988 | eeepc_backlight_exit(); |
867 | fail_backlight: | 989 | fail_backlight: |
990 | eeepc_input_exit(); | ||
991 | eeepc_rfkill_exit(); | ||
868 | return result; | 992 | return result; |
869 | } | 993 | } |
870 | 994 | ||
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index de91ddab0a86..f41135f2fb29 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -463,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) | |||
463 | 463 | ||
464 | return 0; | 464 | return 0; |
465 | register_wwan_err: | 465 | register_wwan_err: |
466 | rfkill_unregister(bluetooth_rfkill); | 466 | if (bluetooth_rfkill) |
467 | rfkill_unregister(bluetooth_rfkill); | ||
467 | register_bluetooth_error: | 468 | register_bluetooth_error: |
468 | rfkill_unregister(wifi_rfkill); | 469 | if (wifi_rfkill) |
470 | rfkill_unregister(wifi_rfkill); | ||
469 | add_sysfs_error: | 471 | add_sysfs_error: |
470 | cleanup_sysfs(device); | 472 | cleanup_sysfs(device); |
471 | return err; | 473 | return err; |
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index f30db367c82e..c47a44dcb702 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c | |||
@@ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) | |||
507 | 507 | ||
508 | hkey_num = result & 0xf; | 508 | hkey_num = result & 0xf; |
509 | 509 | ||
510 | if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) { | 510 | if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) { |
511 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, | 511 | ACPI_DEBUG_PRINT((ACPI_DB_ERROR, |
512 | "hotkey number out of range: %d\n", | 512 | "hotkey number out of range: %d\n", |
513 | hkey_num)); | 513 | hkey_num)); |