aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/Kconfig17
-rw-r--r--drivers/platform/x86/acer-wmi.c4
-rw-r--r--drivers/platform/x86/asus-laptop.c179
-rw-r--r--drivers/platform/x86/asus_acpi.c16
-rw-r--r--drivers/platform/x86/eeepc-laptop.c168
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c25
-rw-r--r--drivers/platform/x86/hp-wmi.c6
-rw-r--r--drivers/platform/x86/panasonic-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c8
-rw-r--r--drivers/platform/x86/wmi.c2
10 files changed, 370 insertions, 57 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1a266d4ab5f1..3608081bc3e0 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -15,8 +15,7 @@ menuconfig X86_PLATFORM_DEVICES
15if X86_PLATFORM_DEVICES 15if X86_PLATFORM_DEVICES
16 16
17config ACER_WMI 17config ACER_WMI
18 tristate "Acer WMI Laptop Extras (EXPERIMENTAL)" 18 tristate "Acer WMI Laptop Extras"
19 depends on EXPERIMENTAL
20 depends on ACPI 19 depends on ACPI
21 depends on LEDS_CLASS 20 depends on LEDS_CLASS
22 depends on NEW_LEDS 21 depends on NEW_LEDS
@@ -39,9 +38,10 @@ config ASUS_LAPTOP
39 tristate "Asus Laptop Extras (EXPERIMENTAL)" 38 tristate "Asus Laptop Extras (EXPERIMENTAL)"
40 depends on ACPI 39 depends on ACPI
41 depends on EXPERIMENTAL && !ACPI_ASUS 40 depends on EXPERIMENTAL && !ACPI_ASUS
42 depends on LEDS_CLASS 41 select LEDS_CLASS
43 depends on NEW_LEDS 42 select NEW_LEDS
44 depends on BACKLIGHT_CLASS_DEVICE 43 select BACKLIGHT_CLASS_DEVICE
44 depends on INPUT
45 ---help--- 45 ---help---
46 This is the new Linux driver for Asus laptops. It may also support some 46 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 47 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
@@ -61,6 +61,7 @@ config DELL_LAPTOP
61 depends on EXPERIMENTAL 61 depends on EXPERIMENTAL
62 depends on BACKLIGHT_CLASS_DEVICE 62 depends on BACKLIGHT_CLASS_DEVICE
63 depends on RFKILL 63 depends on RFKILL
64 depends on POWER_SUPPLY
64 default n 65 default n
65 ---help--- 66 ---help---
66 This driver adds support for rfkill and backlight control to Dell 67 This driver adds support for rfkill and backlight control to Dell
@@ -183,11 +184,11 @@ config SONYPI_COMPAT
183config THINKPAD_ACPI 184config THINKPAD_ACPI
184 tristate "ThinkPad ACPI Laptop Extras" 185 tristate "ThinkPad ACPI Laptop Extras"
185 depends on ACPI 186 depends on ACPI
187 depends on INPUT
186 select BACKLIGHT_LCD_SUPPORT 188 select BACKLIGHT_LCD_SUPPORT
187 select BACKLIGHT_CLASS_DEVICE 189 select BACKLIGHT_CLASS_DEVICE
188 select HWMON 190 select HWMON
189 select NVRAM 191 select NVRAM
190 select INPUT
191 select NEW_LEDS 192 select NEW_LEDS
192 select LEDS_CLASS 193 select LEDS_CLASS
193 select NET 194 select NET
@@ -300,6 +301,7 @@ config INTEL_MENLOW
300config EEEPC_LAPTOP 301config EEEPC_LAPTOP
301 tristate "Eee PC Hotkey Driver (EXPERIMENTAL)" 302 tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
302 depends on ACPI 303 depends on ACPI
304 depends on INPUT
303 depends on EXPERIMENTAL 305 depends on EXPERIMENTAL
304 select BACKLIGHT_CLASS_DEVICE 306 select BACKLIGHT_CLASS_DEVICE
305 select HWMON 307 select HWMON
@@ -312,9 +314,8 @@ config EEEPC_LAPTOP
312 314
313 315
314config ACPI_WMI 316config ACPI_WMI
315 tristate "WMI (EXPERIMENTAL)" 317 tristate "WMI"
316 depends on ACPI 318 depends on ACPI
317 depends on EXPERIMENTAL
318 help 319 help
319 This driver adds support for the ACPI-WMI (Windows Management 320 This driver adds support for the ACPI-WMI (Windows Management
320 Instrumentation) mapper device (PNP0C14) found on some systems. 321 Instrumentation) mapper device (PNP0C14) found on some systems.
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 94c9f911824e..a6a42e8c060b 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1026,7 +1026,7 @@ static void acer_rfkill_exit(void)
1026 kfree(wireless_rfkill->data); 1026 kfree(wireless_rfkill->data);
1027 rfkill_unregister(wireless_rfkill); 1027 rfkill_unregister(wireless_rfkill);
1028 if (has_cap(ACER_CAP_BLUETOOTH)) { 1028 if (has_cap(ACER_CAP_BLUETOOTH)) {
1029 kfree(wireless_rfkill->data); 1029 kfree(bluetooth_rfkill->data);
1030 rfkill_unregister(bluetooth_rfkill); 1030 rfkill_unregister(bluetooth_rfkill);
1031 } 1031 }
1032 return; 1032 return;
@@ -1297,7 +1297,7 @@ static int __init acer_wmi_init(void)
1297 1297
1298 set_quirks(); 1298 set_quirks();
1299 1299
1300 if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { 1300 if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
1301 interface->capability &= ~ACER_CAP_BRIGHTNESS; 1301 interface->capability &= ~ACER_CAP_BRIGHTNESS;
1302 printk(ACER_INFO "Brightness must be controlled by " 1302 printk(ACER_INFO "Brightness must be controlled by "
1303 "generic video driver\n"); 1303 "generic video driver\n");
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 8fb8b3591048..eeafc6c0160d 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");
250ASUS_LED(pled, "phone"); 253ASUS_LED(pled, "phone");
251ASUS_LED(gled, "gaming"); 254ASUS_LED(gled, "gaming");
252 255
256struct key_entry {
257 char type;
258 u8 code;
259 u16 keycode;
260};
261
262enum { KE_KEY, KE_END };
263
264static 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,69 @@ 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 */
760static 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
771static 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
782static 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
794static 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
723static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) 815static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
724{ 816{
817 static struct key_entry *key;
818 u16 count;
819
725 /* TODO Find a better way to handle events count. */ 820 /* TODO Find a better way to handle events count. */
726 if (!hotk) 821 if (!hotk)
727 return; 822 return;
@@ -738,10 +833,26 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
738 lcd_blank(FB_BLANK_POWERDOWN); 833 lcd_blank(FB_BLANK_POWERDOWN);
739 } 834 }
740 835
741 acpi_bus_generate_proc_event(hotk->device, event, 836 count = hotk->event_count[event % 128]++;
742 hotk->event_count[event % 128]++); 837 acpi_bus_generate_proc_event(hotk->device, event, count);
743 838 acpi_bus_generate_netlink_event(hotk->device->pnp.device_class,
744 return; 839 dev_name(&hotk->device->dev), event,
840 count);
841
842 if (hotk->inputdev) {
843 key = asus_get_entry_by_scancode(event);
844 if (!key)
845 return ;
846
847 switch (key->type) {
848 case KE_KEY:
849 input_report_key(hotk->inputdev, key->keycode, 1);
850 input_sync(hotk->inputdev);
851 input_report_key(hotk->inputdev, key->keycode, 0);
852 input_sync(hotk->inputdev);
853 break;
854 }
855 }
745} 856}
746 857
747#define ASUS_CREATE_DEVICE_ATTR(_name) \ 858#define ASUS_CREATE_DEVICE_ATTR(_name) \
@@ -959,6 +1070,38 @@ static int asus_hotk_get_info(void)
959 return AE_OK; 1070 return AE_OK;
960} 1071}
961 1072
1073static int asus_input_init(void)
1074{
1075 const struct key_entry *key;
1076 int result;
1077
1078 hotk->inputdev = input_allocate_device();
1079 if (!hotk->inputdev) {
1080 printk(ASUS_INFO "Unable to allocate input device\n");
1081 return 0;
1082 }
1083 hotk->inputdev->name = "Asus Laptop extra buttons";
1084 hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
1085 hotk->inputdev->id.bustype = BUS_HOST;
1086 hotk->inputdev->getkeycode = asus_getkeycode;
1087 hotk->inputdev->setkeycode = asus_setkeycode;
1088
1089 for (key = asus_keymap; key->type != KE_END; key++) {
1090 switch (key->type) {
1091 case KE_KEY:
1092 set_bit(EV_KEY, hotk->inputdev->evbit);
1093 set_bit(key->keycode, hotk->inputdev->keybit);
1094 break;
1095 }
1096 }
1097 result = input_register_device(hotk->inputdev);
1098 if (result) {
1099 printk(ASUS_INFO "Unable to register input device\n");
1100 input_free_device(hotk->inputdev);
1101 }
1102 return result;
1103}
1104
962static int asus_hotk_check(void) 1105static int asus_hotk_check(void)
963{ 1106{
964 int result = 0; 1107 int result = 0;
@@ -1044,7 +1187,7 @@ static int asus_hotk_add(struct acpi_device *device)
1044 /* GPS is on by default */ 1187 /* GPS is on by default */
1045 write_status(NULL, 1, GPS_ON); 1188 write_status(NULL, 1, GPS_ON);
1046 1189
1047 end: 1190end:
1048 if (result) { 1191 if (result) {
1049 kfree(hotk->name); 1192 kfree(hotk->name);
1050 kfree(hotk); 1193 kfree(hotk);
@@ -1091,10 +1234,17 @@ static void asus_led_exit(void)
1091 ASUS_LED_UNREGISTER(gled); 1234 ASUS_LED_UNREGISTER(gled);
1092} 1235}
1093 1236
1237static void asus_input_exit(void)
1238{
1239 if (hotk->inputdev)
1240 input_unregister_device(hotk->inputdev);
1241}
1242
1094static void __exit asus_laptop_exit(void) 1243static void __exit asus_laptop_exit(void)
1095{ 1244{
1096 asus_backlight_exit(); 1245 asus_backlight_exit();
1097 asus_led_exit(); 1246 asus_led_exit();
1247 asus_input_exit();
1098 1248
1099 acpi_bus_unregister_driver(&asus_hotk_driver); 1249 acpi_bus_unregister_driver(&asus_hotk_driver);
1100 sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); 1250 sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);
@@ -1216,6 +1366,10 @@ static int __init asus_laptop_init(void)
1216 printk(ASUS_INFO "Brightness ignored, must be controlled by " 1366 printk(ASUS_INFO "Brightness ignored, must be controlled by "
1217 "ACPI video driver\n"); 1367 "ACPI video driver\n");
1218 1368
1369 result = asus_input_init();
1370 if (result)
1371 goto fail_input;
1372
1219 result = asus_led_init(dev); 1373 result = asus_led_init(dev);
1220 if (result) 1374 if (result)
1221 goto fail_led; 1375 goto fail_led;
@@ -1242,22 +1396,25 @@ static int __init asus_laptop_init(void)
1242 1396
1243 return 0; 1397 return 0;
1244 1398
1245 fail_sysfs: 1399fail_sysfs:
1246 platform_device_del(asuspf_device); 1400 platform_device_del(asuspf_device);
1247 1401
1248 fail_platform_device2: 1402fail_platform_device2:
1249 platform_device_put(asuspf_device); 1403 platform_device_put(asuspf_device);
1250 1404
1251 fail_platform_device1: 1405fail_platform_device1:
1252 platform_driver_unregister(&asuspf_driver); 1406 platform_driver_unregister(&asuspf_driver);
1253 1407
1254 fail_platform_driver: 1408fail_platform_driver:
1255 asus_led_exit(); 1409 asus_led_exit();
1256 1410
1257 fail_led: 1411fail_led:
1412 asus_input_exit();
1413
1414fail_input:
1258 asus_backlight_exit(); 1415 asus_backlight_exit();
1259 1416
1260 fail_backlight: 1417fail_backlight:
1261 1418
1262 return result; 1419 return result;
1263} 1420}
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..6f54fd1757cd 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,18 +515,59 @@ static int eeepc_hotk_check(void)
510static void notify_brn(void) 515static 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
522static 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
516static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) 557static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
517{ 558{
518 static struct key_entry *key; 559 static struct key_entry *key;
560 u16 count;
561
519 if (!ehotk) 562 if (!ehotk)
520 return; 563 return;
521 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) 564 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
522 notify_brn(); 565 notify_brn();
523 acpi_bus_generate_proc_event(ehotk->device, event, 566 count = ehotk->event_count[event % 128]++;
524 ehotk->event_count[event % 128]++); 567 acpi_bus_generate_proc_event(ehotk->device, event, count);
568 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
569 dev_name(&ehotk->device->dev), event,
570 count);
525 if (ehotk->inputdev) { 571 if (ehotk->inputdev) {
526 key = eepc_get_entry_by_scancode(event); 572 key = eepc_get_entry_by_scancode(event);
527 if (key) { 573 if (key) {
@@ -539,6 +585,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
539 } 585 }
540} 586}
541 587
588static int eeepc_register_rfkill_notifier(char *node)
589{
590 acpi_status status = AE_OK;
591 acpi_handle handle;
592
593 status = acpi_get_handle(NULL, node, &handle);
594
595 if (ACPI_SUCCESS(status)) {
596 status = acpi_install_notify_handler(handle,
597 ACPI_SYSTEM_NOTIFY,
598 eeepc_rfkill_notify,
599 NULL);
600 if (ACPI_FAILURE(status))
601 printk(EEEPC_WARNING
602 "Failed to register notify on %s\n", node);
603 } else
604 return -ENODEV;
605
606 return 0;
607}
608
609static void eeepc_unregister_rfkill_notifier(char *node)
610{
611 acpi_status status = AE_OK;
612 acpi_handle handle;
613
614 status = acpi_get_handle(NULL, node, &handle);
615
616 if (ACPI_SUCCESS(status)) {
617 status = acpi_remove_notify_handler(handle,
618 ACPI_SYSTEM_NOTIFY,
619 eeepc_rfkill_notify);
620 if (ACPI_FAILURE(status))
621 printk(EEEPC_ERR
622 "Error removing rfkill notify handler %s\n",
623 node);
624 }
625}
626
542static int eeepc_hotk_add(struct acpi_device *device) 627static int eeepc_hotk_add(struct acpi_device *device)
543{ 628{
544 acpi_status status = AE_OK; 629 acpi_status status = AE_OK;
@@ -558,7 +643,7 @@ static int eeepc_hotk_add(struct acpi_device *device)
558 ehotk->device = device; 643 ehotk->device = device;
559 result = eeepc_hotk_check(); 644 result = eeepc_hotk_check();
560 if (result) 645 if (result)
561 goto end; 646 goto ehotk_fail;
562 status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, 647 status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
563 eeepc_hotk_notify, ehotk); 648 eeepc_hotk_notify, ehotk);
564 if (ACPI_FAILURE(status)) 649 if (ACPI_FAILURE(status))
@@ -569,18 +654,25 @@ static int eeepc_hotk_add(struct acpi_device *device)
569 RFKILL_TYPE_WLAN); 654 RFKILL_TYPE_WLAN);
570 655
571 if (!ehotk->eeepc_wlan_rfkill) 656 if (!ehotk->eeepc_wlan_rfkill)
572 goto end; 657 goto wlan_fail;
573 658
574 ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; 659 ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan";
575 ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; 660 ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set;
576 ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; 661 ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state;
577 if (get_acpi(CM_ASL_WLAN) == 1) 662 if (get_acpi(CM_ASL_WLAN) == 1) {
578 ehotk->eeepc_wlan_rfkill->state = 663 ehotk->eeepc_wlan_rfkill->state =
579 RFKILL_STATE_UNBLOCKED; 664 RFKILL_STATE_UNBLOCKED;
580 else 665 rfkill_set_default(RFKILL_TYPE_WLAN,
666 RFKILL_STATE_UNBLOCKED);
667 } else {
581 ehotk->eeepc_wlan_rfkill->state = 668 ehotk->eeepc_wlan_rfkill->state =
582 RFKILL_STATE_SOFT_BLOCKED; 669 RFKILL_STATE_SOFT_BLOCKED;
583 rfkill_register(ehotk->eeepc_wlan_rfkill); 670 rfkill_set_default(RFKILL_TYPE_WLAN,
671 RFKILL_STATE_SOFT_BLOCKED);
672 }
673 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
674 if (result)
675 goto wlan_fail;
584 } 676 }
585 677
586 if (get_acpi(CM_ASL_BLUETOOTH) != -1) { 678 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
@@ -588,27 +680,47 @@ static int eeepc_hotk_add(struct acpi_device *device)
588 rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); 680 rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH);
589 681
590 if (!ehotk->eeepc_bluetooth_rfkill) 682 if (!ehotk->eeepc_bluetooth_rfkill)
591 goto end; 683 goto bluetooth_fail;
592 684
593 ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; 685 ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth";
594 ehotk->eeepc_bluetooth_rfkill->toggle_radio = 686 ehotk->eeepc_bluetooth_rfkill->toggle_radio =
595 eeepc_bluetooth_rfkill_set; 687 eeepc_bluetooth_rfkill_set;
596 ehotk->eeepc_bluetooth_rfkill->get_state = 688 ehotk->eeepc_bluetooth_rfkill->get_state =
597 eeepc_bluetooth_rfkill_state; 689 eeepc_bluetooth_rfkill_state;
598 if (get_acpi(CM_ASL_BLUETOOTH) == 1) 690 if (get_acpi(CM_ASL_BLUETOOTH) == 1) {
599 ehotk->eeepc_bluetooth_rfkill->state = 691 ehotk->eeepc_bluetooth_rfkill->state =
600 RFKILL_STATE_UNBLOCKED; 692 RFKILL_STATE_UNBLOCKED;
601 else 693 rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
694 RFKILL_STATE_UNBLOCKED);
695 } else {
602 ehotk->eeepc_bluetooth_rfkill->state = 696 ehotk->eeepc_bluetooth_rfkill->state =
603 RFKILL_STATE_SOFT_BLOCKED; 697 RFKILL_STATE_SOFT_BLOCKED;
604 rfkill_register(ehotk->eeepc_bluetooth_rfkill); 698 rfkill_set_default(RFKILL_TYPE_BLUETOOTH,
605 } 699 RFKILL_STATE_SOFT_BLOCKED);
700 }
606 701
607 end: 702 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
608 if (result) { 703 if (result)
609 kfree(ehotk); 704 goto bluetooth_fail;
610 ehotk = NULL;
611 } 705 }
706
707 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
708 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
709
710 return 0;
711
712 bluetooth_fail:
713 if (ehotk->eeepc_bluetooth_rfkill)
714 rfkill_free(ehotk->eeepc_bluetooth_rfkill);
715 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
716 ehotk->eeepc_wlan_rfkill = NULL;
717 wlan_fail:
718 if (ehotk->eeepc_wlan_rfkill)
719 rfkill_free(ehotk->eeepc_wlan_rfkill);
720 ehotk_fail:
721 kfree(ehotk);
722 ehotk = NULL;
723
612 return result; 724 return result;
613} 725}
614 726
@@ -622,6 +734,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type)
622 eeepc_hotk_notify); 734 eeepc_hotk_notify);
623 if (ACPI_FAILURE(status)) 735 if (ACPI_FAILURE(status))
624 printk(EEEPC_ERR "Error removing notify handler\n"); 736 printk(EEEPC_ERR "Error removing notify handler\n");
737
738 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
739 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
740
625 kfree(ehotk); 741 kfree(ehotk);
626 return 0; 742 return 0;
627} 743}
@@ -737,13 +853,21 @@ static void eeepc_backlight_exit(void)
737{ 853{
738 if (eeepc_backlight_device) 854 if (eeepc_backlight_device)
739 backlight_device_unregister(eeepc_backlight_device); 855 backlight_device_unregister(eeepc_backlight_device);
740 if (ehotk->inputdev) 856 eeepc_backlight_device = NULL;
741 input_unregister_device(ehotk->inputdev); 857}
858
859static void eeepc_rfkill_exit(void)
860{
742 if (ehotk->eeepc_wlan_rfkill) 861 if (ehotk->eeepc_wlan_rfkill)
743 rfkill_unregister(ehotk->eeepc_wlan_rfkill); 862 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
744 if (ehotk->eeepc_bluetooth_rfkill) 863 if (ehotk->eeepc_bluetooth_rfkill)
745 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); 864 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill);
746 eeepc_backlight_device = NULL; 865}
866
867static void eeepc_input_exit(void)
868{
869 if (ehotk->inputdev)
870 input_unregister_device(ehotk->inputdev);
747} 871}
748 872
749static void eeepc_hwmon_exit(void) 873static void eeepc_hwmon_exit(void)
@@ -762,6 +886,8 @@ static void eeepc_hwmon_exit(void)
762static void __exit eeepc_laptop_exit(void) 886static void __exit eeepc_laptop_exit(void)
763{ 887{
764 eeepc_backlight_exit(); 888 eeepc_backlight_exit();
889 eeepc_rfkill_exit();
890 eeepc_input_exit();
765 eeepc_hwmon_exit(); 891 eeepc_hwmon_exit();
766 acpi_bus_unregister_driver(&eeepc_hotk_driver); 892 acpi_bus_unregister_driver(&eeepc_hotk_driver);
767 sysfs_remove_group(&platform_device->dev.kobj, 893 sysfs_remove_group(&platform_device->dev.kobj,
@@ -865,6 +991,8 @@ fail_platform_driver:
865fail_hwmon: 991fail_hwmon:
866 eeepc_backlight_exit(); 992 eeepc_backlight_exit();
867fail_backlight: 993fail_backlight:
994 eeepc_input_exit();
995 eeepc_rfkill_exit();
868 return result; 996 return result;
869} 997}
870 998
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 65dc41540c62..45940f31fe9e 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -166,6 +166,7 @@ struct fujitsu_hotkey_t {
166 struct platform_device *pf_device; 166 struct platform_device *pf_device;
167 struct kfifo *fifo; 167 struct kfifo *fifo;
168 spinlock_t fifo_lock; 168 spinlock_t fifo_lock;
169 int rfkill_supported;
169 int rfkill_state; 170 int rfkill_state;
170 int logolamp_registered; 171 int logolamp_registered;
171 int kblamps_registered; 172 int kblamps_registered;
@@ -526,7 +527,7 @@ static ssize_t
526show_lid_state(struct device *dev, 527show_lid_state(struct device *dev,
527 struct device_attribute *attr, char *buf) 528 struct device_attribute *attr, char *buf)
528{ 529{
529 if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD) 530 if (!(fujitsu_hotkey->rfkill_supported & 0x100))
530 return sprintf(buf, "unknown\n"); 531 return sprintf(buf, "unknown\n");
531 if (fujitsu_hotkey->rfkill_state & 0x100) 532 if (fujitsu_hotkey->rfkill_state & 0x100)
532 return sprintf(buf, "open\n"); 533 return sprintf(buf, "open\n");
@@ -538,7 +539,7 @@ static ssize_t
538show_dock_state(struct device *dev, 539show_dock_state(struct device *dev,
539 struct device_attribute *attr, char *buf) 540 struct device_attribute *attr, char *buf)
540{ 541{
541 if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD) 542 if (!(fujitsu_hotkey->rfkill_supported & 0x200))
542 return sprintf(buf, "unknown\n"); 543 return sprintf(buf, "unknown\n");
543 if (fujitsu_hotkey->rfkill_state & 0x200) 544 if (fujitsu_hotkey->rfkill_state & 0x200)
544 return sprintf(buf, "docked\n"); 545 return sprintf(buf, "docked\n");
@@ -550,7 +551,7 @@ static ssize_t
550show_radios_state(struct device *dev, 551show_radios_state(struct device *dev,
551 struct device_attribute *attr, char *buf) 552 struct device_attribute *attr, char *buf)
552{ 553{
553 if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD) 554 if (!(fujitsu_hotkey->rfkill_supported & 0x20))
554 return sprintf(buf, "unknown\n"); 555 return sprintf(buf, "unknown\n");
555 if (fujitsu_hotkey->rfkill_state & 0x20) 556 if (fujitsu_hotkey->rfkill_state & 0x20)
556 return sprintf(buf, "on\n"); 557 return sprintf(buf, "on\n");
@@ -928,8 +929,17 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
928 ; /* No action, result is discarded */ 929 ; /* No action, result is discarded */
929 vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i); 930 vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
930 931
931 fujitsu_hotkey->rfkill_state = 932 fujitsu_hotkey->rfkill_supported =
932 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); 933 call_fext_func(FUNC_RFKILL, 0x0, 0x0, 0x0);
934
935 /* Make sure our bitmask of supported functions is cleared if the
936 RFKILL function block is not implemented, like on the S7020. */
937 if (fujitsu_hotkey->rfkill_supported == UNSUPPORTED_CMD)
938 fujitsu_hotkey->rfkill_supported = 0;
939
940 if (fujitsu_hotkey->rfkill_supported)
941 fujitsu_hotkey->rfkill_state =
942 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
933 943
934 /* Suspect this is a keymap of the application panel, print it */ 944 /* Suspect this is a keymap of the application panel, print it */
935 printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n", 945 printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n",
@@ -1005,8 +1015,9 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
1005 1015
1006 input = fujitsu_hotkey->input; 1016 input = fujitsu_hotkey->input;
1007 1017
1008 fujitsu_hotkey->rfkill_state = 1018 if (fujitsu_hotkey->rfkill_supported)
1009 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0); 1019 fujitsu_hotkey->rfkill_state =
1020 call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
1010 1021
1011 switch (event) { 1022 switch (event) {
1012 case ACPI_FUJITSU_NOTIFY_CODE1: 1023 case ACPI_FUJITSU_NOTIFY_CODE1:
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;
465register_wwan_err: 465register_wwan_err:
466 rfkill_unregister(bluetooth_rfkill); 466 if (bluetooth_rfkill)
467 rfkill_unregister(bluetooth_rfkill);
467register_bluetooth_error: 468register_bluetooth_error:
468 rfkill_unregister(wifi_rfkill); 469 if (wifi_rfkill)
470 rfkill_unregister(wifi_rfkill);
469add_sysfs_error: 471add_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));
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index bcbc05107ba8..d2433204a40c 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -7532,7 +7532,7 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
7532 * if it is not there yet. 7532 * if it is not there yet.
7533 */ 7533 */
7534#define IBM_BIOS_MODULE_ALIAS(__type) \ 7534#define IBM_BIOS_MODULE_ALIAS(__type) \
7535 MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") 7535 MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*")
7536 7536
7537/* Non-ancient thinkpads */ 7537/* Non-ancient thinkpads */
7538MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); 7538MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*");
@@ -7541,9 +7541,9 @@ MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*");
7541/* Ancient thinkpad BIOSes have to be identified by 7541/* Ancient thinkpad BIOSes have to be identified by
7542 * BIOS type or model number, and there are far less 7542 * BIOS type or model number, and there are far less
7543 * BIOS types than model numbers... */ 7543 * BIOS types than model numbers... */
7544IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); 7544IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]");
7545IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); 7545IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]");
7546IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); 7546IBM_BIOS_MODULE_ALIAS("K[UX-Z]");
7547 7547
7548MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); 7548MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh");
7549MODULE_DESCRIPTION(TPACPI_DESC); 7549MODULE_DESCRIPTION(TPACPI_DESC);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 8a8b377712c9..2f269e117b8f 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -708,7 +708,7 @@ static int __init acpi_wmi_add(struct acpi_device *device)
708 708
709static int __init acpi_wmi_init(void) 709static int __init acpi_wmi_init(void)
710{ 710{
711 acpi_status result; 711 int result;
712 712
713 INIT_LIST_HEAD(&wmi_blocks.list); 713 INIT_LIST_HEAD(&wmi_blocks.list);
714 714