aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-02-12 07:08:57 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-12 07:08:57 -0500
commit871cafcc962fa1655c44b4f0e54d4c5cc14e273c (patch)
treefdb7bc65d2606c85b7be6c33ba0dfd5b4e472245 /drivers/platform
parentcf2592f59c0e8ed4308adbdb2e0a88655379d579 (diff)
parentb578f3fcca1e78624dfb5f358776e63711d7fda2 (diff)
Merge branch 'linus' into core/softlockup
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig24
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/asus-laptop.c176
-rw-r--r--drivers/platform/x86/asus_acpi.c16
-rw-r--r--drivers/platform/x86/dell-laptop.c436
-rw-r--r--drivers/platform/x86/eeepc-laptop.c168
-rw-r--r--drivers/platform/x86/hp-wmi.c12
-rw-r--r--drivers/platform/x86/panasonic-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c910
9 files changed, 1556 insertions, 189 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e65448e99b48..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
@@ -54,6 +55,18 @@ config ASUS_LAPTOP
54 55
55 If you have an ACPI-compatible ASUS laptop, say Y or M here. 56 If you have an ACPI-compatible ASUS laptop, say Y or M here.
56 57
58config DELL_LAPTOP
59 tristate "Dell Laptop Extras (EXPERIMENTAL)"
60 depends on X86
61 depends on DCDBAS
62 depends on EXPERIMENTAL
63 depends on BACKLIGHT_CLASS_DEVICE
64 depends on RFKILL
65 default n
66 ---help---
67 This driver adds support for rfkill and backlight control to Dell
68 laptops.
69
57config FUJITSU_LAPTOP 70config FUJITSU_LAPTOP
58 tristate "Fujitsu Laptop Extras" 71 tristate "Fujitsu Laptop Extras"
59 depends on ACPI 72 depends on ACPI
@@ -192,6 +205,17 @@ config THINKPAD_ACPI
192 205
193 If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. 206 If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
194 207
208config THINKPAD_ACPI_DEBUGFACILITIES
209 bool "Maintainer debug facilities"
210 depends on THINKPAD_ACPI
211 default n
212 ---help---
213 Enables extra stuff in the thinkpad-acpi which is completely useless
214 for normal use. Read the driver source to find out what it does.
215
216 Say N here, unless you were told by a kernel maintainer to do
217 otherwise.
218
195config THINKPAD_ACPI_DEBUG 219config THINKPAD_ACPI_DEBUG
196 bool "Verbose debug mode" 220 bool "Verbose debug mode"
197 depends on THINKPAD_ACPI 221 depends on THINKPAD_ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 1e9de2ae0de5..e29065120be9 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o
6obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o 6obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o
7obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o 7obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
8obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o 8obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
9obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
9obj-$(CONFIG_ACER_WMI) += acer-wmi.o 10obj-$(CONFIG_ACER_WMI) += acer-wmi.o
10obj-$(CONFIG_HP_WMI) += hp-wmi.o 11obj-$(CONFIG_HP_WMI) += hp-wmi.o
11obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o 12obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
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");
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,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 */
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
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
1070static 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
962static int asus_hotk_check(void) 1102static 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: 1187end:
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
1234static void asus_input_exit(void)
1235{
1236 if (hotk->inputdev)
1237 input_unregister_device(hotk->inputdev);
1238}
1239
1094static void __exit asus_laptop_exit(void) 1240static 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: 1396fail_sysfs:
1246 platform_device_del(asuspf_device); 1397 platform_device_del(asuspf_device);
1247 1398
1248 fail_platform_device2: 1399fail_platform_device2:
1249 platform_device_put(asuspf_device); 1400 platform_device_put(asuspf_device);
1250 1401
1251 fail_platform_device1: 1402fail_platform_device1:
1252 platform_driver_unregister(&asuspf_driver); 1403 platform_driver_unregister(&asuspf_driver);
1253 1404
1254 fail_platform_driver: 1405fail_platform_driver:
1255 asus_led_exit(); 1406 asus_led_exit();
1256 1407
1257 fail_led: 1408fail_led:
1409 asus_input_exit();
1410
1411fail_input:
1258 asus_backlight_exit(); 1412 asus_backlight_exit();
1259 1413
1260 fail_backlight: 1414fail_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/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
new file mode 100644
index 000000000000..16e11c2ee19a
--- /dev/null
+++ b/drivers/platform/x86/dell-laptop.c
@@ -0,0 +1,436 @@
1/*
2 * Driver for Dell laptop extras
3 *
4 * Copyright (c) Red Hat <mjg@redhat.com>
5 *
6 * Based on documentation in the libsmbios package, Copyright (C) 2005 Dell
7 * Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/platform_device.h>
18#include <linux/backlight.h>
19#include <linux/err.h>
20#include <linux/dmi.h>
21#include <linux/io.h>
22#include <linux/rfkill.h>
23#include <linux/power_supply.h>
24#include <linux/acpi.h>
25#include "../../firmware/dcdbas.h"
26
27#define BRIGHTNESS_TOKEN 0x7d
28
29/* This structure will be modified by the firmware when we enter
30 * system management mode, hence the volatiles */
31
32struct calling_interface_buffer {
33 u16 class;
34 u16 select;
35 volatile u32 input[4];
36 volatile u32 output[4];
37} __packed;
38
39struct calling_interface_token {
40 u16 tokenID;
41 u16 location;
42 union {
43 u16 value;
44 u16 stringlength;
45 };
46};
47
48struct calling_interface_structure {
49 struct dmi_header header;
50 u16 cmdIOAddress;
51 u8 cmdIOCode;
52 u32 supportedCmds;
53 struct calling_interface_token tokens[];
54} __packed;
55
56static int da_command_address;
57static int da_command_code;
58static int da_num_tokens;
59static struct calling_interface_token *da_tokens;
60
61static struct backlight_device *dell_backlight_device;
62static struct rfkill *wifi_rfkill;
63static struct rfkill *bluetooth_rfkill;
64static struct rfkill *wwan_rfkill;
65
66static const struct dmi_system_id __initdata dell_device_table[] = {
67 {
68 .ident = "Dell laptop",
69 .matches = {
70 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
71 DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
72 },
73 },
74 { }
75};
76
77static void parse_da_table(const struct dmi_header *dm)
78{
79 /* Final token is a terminator, so we don't want to copy it */
80 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
81 struct calling_interface_structure *table =
82 container_of(dm, struct calling_interface_structure, header);
83
84 /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least
85 6 bytes of entry */
86
87 if (dm->length < 17)
88 return;
89
90 da_command_address = table->cmdIOAddress;
91 da_command_code = table->cmdIOCode;
92
93 da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
94 sizeof(struct calling_interface_token),
95 GFP_KERNEL);
96
97 if (!da_tokens)
98 return;
99
100 memcpy(da_tokens+da_num_tokens, table->tokens,
101 sizeof(struct calling_interface_token) * tokens);
102
103 da_num_tokens += tokens;
104}
105
106static void find_tokens(const struct dmi_header *dm)
107{
108 switch (dm->type) {
109 case 0xd4: /* Indexed IO */
110 break;
111 case 0xd5: /* Protected Area Type 1 */
112 break;
113 case 0xd6: /* Protected Area Type 2 */
114 break;
115 case 0xda: /* Calling interface */
116 parse_da_table(dm);
117 break;
118 }
119}
120
121static int find_token_location(int tokenid)
122{
123 int i;
124 for (i = 0; i < da_num_tokens; i++) {
125 if (da_tokens[i].tokenID == tokenid)
126 return da_tokens[i].location;
127 }
128
129 return -1;
130}
131
132static struct calling_interface_buffer *
133dell_send_request(struct calling_interface_buffer *buffer, int class,
134 int select)
135{
136 struct smi_cmd command;
137
138 command.magic = SMI_CMD_MAGIC;
139 command.command_address = da_command_address;
140 command.command_code = da_command_code;
141 command.ebx = virt_to_phys(buffer);
142 command.ecx = 0x42534931;
143
144 buffer->class = class;
145 buffer->select = select;
146
147 dcdbas_smi_request(&command);
148
149 return buffer;
150}
151
152/* Derived from information in DellWirelessCtl.cpp:
153 Class 17, select 11 is radio control. It returns an array of 32-bit values.
154
155 result[0]: return code
156 result[1]:
157 Bit 0: Hardware switch supported
158 Bit 1: Wifi locator supported
159 Bit 2: Wifi is supported
160 Bit 3: Bluetooth is supported
161 Bit 4: WWAN is supported
162 Bit 5: Wireless keyboard supported
163 Bits 6-7: Reserved
164 Bit 8: Wifi is installed
165 Bit 9: Bluetooth is installed
166 Bit 10: WWAN is installed
167 Bits 11-15: Reserved
168 Bit 16: Hardware switch is on
169 Bit 17: Wifi is blocked
170 Bit 18: Bluetooth is blocked
171 Bit 19: WWAN is blocked
172 Bits 20-31: Reserved
173 result[2]: NVRAM size in bytes
174 result[3]: NVRAM format version number
175*/
176
177static int dell_rfkill_set(int radio, enum rfkill_state state)
178{
179 struct calling_interface_buffer buffer;
180 int disable = (state == RFKILL_STATE_UNBLOCKED) ? 0 : 1;
181
182 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
183 buffer.input[0] = (1 | (radio<<8) | (disable << 16));
184 dell_send_request(&buffer, 17, 11);
185
186 return 0;
187}
188
189static int dell_wifi_set(void *data, enum rfkill_state state)
190{
191 return dell_rfkill_set(1, state);
192}
193
194static int dell_bluetooth_set(void *data, enum rfkill_state state)
195{
196 return dell_rfkill_set(2, state);
197}
198
199static int dell_wwan_set(void *data, enum rfkill_state state)
200{
201 return dell_rfkill_set(3, state);
202}
203
204static int dell_rfkill_get(int bit, enum rfkill_state *state)
205{
206 struct calling_interface_buffer buffer;
207 int status;
208 int new_state = RFKILL_STATE_HARD_BLOCKED;
209
210 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
211 dell_send_request(&buffer, 17, 11);
212 status = buffer.output[1];
213
214 if (status & (1<<16))
215 new_state = RFKILL_STATE_SOFT_BLOCKED;
216
217 if (status & (1<<bit))
218 *state = new_state;
219 else
220 *state = RFKILL_STATE_UNBLOCKED;
221
222 return 0;
223}
224
225static int dell_wifi_get(void *data, enum rfkill_state *state)
226{
227 return dell_rfkill_get(17, state);
228}
229
230static int dell_bluetooth_get(void *data, enum rfkill_state *state)
231{
232 return dell_rfkill_get(18, state);
233}
234
235static int dell_wwan_get(void *data, enum rfkill_state *state)
236{
237 return dell_rfkill_get(19, state);
238}
239
240static int dell_setup_rfkill(void)
241{
242 struct calling_interface_buffer buffer;
243 int status;
244 int ret;
245
246 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
247 dell_send_request(&buffer, 17, 11);
248 status = buffer.output[1];
249
250 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
251 wifi_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WLAN);
252 if (!wifi_rfkill)
253 goto err_wifi;
254 wifi_rfkill->name = "dell-wifi";
255 wifi_rfkill->toggle_radio = dell_wifi_set;
256 wifi_rfkill->get_state = dell_wifi_get;
257 ret = rfkill_register(wifi_rfkill);
258 if (ret)
259 goto err_wifi;
260 }
261
262 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
263 bluetooth_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_BLUETOOTH);
264 if (!bluetooth_rfkill)
265 goto err_bluetooth;
266 bluetooth_rfkill->name = "dell-bluetooth";
267 bluetooth_rfkill->toggle_radio = dell_bluetooth_set;
268 bluetooth_rfkill->get_state = dell_bluetooth_get;
269 ret = rfkill_register(bluetooth_rfkill);
270 if (ret)
271 goto err_bluetooth;
272 }
273
274 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
275 wwan_rfkill = rfkill_allocate(NULL, RFKILL_TYPE_WWAN);
276 if (!wwan_rfkill)
277 goto err_wwan;
278 wwan_rfkill->name = "dell-wwan";
279 wwan_rfkill->toggle_radio = dell_wwan_set;
280 wwan_rfkill->get_state = dell_wwan_get;
281 ret = rfkill_register(wwan_rfkill);
282 if (ret)
283 goto err_wwan;
284 }
285
286 return 0;
287err_wwan:
288 if (wwan_rfkill)
289 rfkill_free(wwan_rfkill);
290 if (bluetooth_rfkill) {
291 rfkill_unregister(bluetooth_rfkill);
292 bluetooth_rfkill = NULL;
293 }
294err_bluetooth:
295 if (bluetooth_rfkill)
296 rfkill_free(bluetooth_rfkill);
297 if (wifi_rfkill) {
298 rfkill_unregister(wifi_rfkill);
299 wifi_rfkill = NULL;
300 }
301err_wifi:
302 if (wifi_rfkill)
303 rfkill_free(wifi_rfkill);
304
305 return ret;
306}
307
308static int dell_send_intensity(struct backlight_device *bd)
309{
310 struct calling_interface_buffer buffer;
311
312 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
313 buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
314 buffer.input[1] = bd->props.brightness;
315
316 if (buffer.input[0] == -1)
317 return -ENODEV;
318
319 if (power_supply_is_system_supplied() > 0)
320 dell_send_request(&buffer, 1, 2);
321 else
322 dell_send_request(&buffer, 1, 1);
323
324 return 0;
325}
326
327static int dell_get_intensity(struct backlight_device *bd)
328{
329 struct calling_interface_buffer buffer;
330
331 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
332 buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
333
334 if (buffer.input[0] == -1)
335 return -ENODEV;
336
337 if (power_supply_is_system_supplied() > 0)
338 dell_send_request(&buffer, 0, 2);
339 else
340 dell_send_request(&buffer, 0, 1);
341
342 return buffer.output[1];
343}
344
345static struct backlight_ops dell_ops = {
346 .get_brightness = dell_get_intensity,
347 .update_status = dell_send_intensity,
348};
349
350static int __init dell_init(void)
351{
352 struct calling_interface_buffer buffer;
353 int max_intensity = 0;
354 int ret;
355
356 if (!dmi_check_system(dell_device_table))
357 return -ENODEV;
358
359 dmi_walk(find_tokens);
360
361 if (!da_tokens) {
362 printk(KERN_INFO "dell-laptop: Unable to find dmi tokens\n");
363 return -ENODEV;
364 }
365
366 ret = dell_setup_rfkill();
367
368 if (ret) {
369 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n");
370 goto out;
371 }
372
373#ifdef CONFIG_ACPI
374 /* In the event of an ACPI backlight being available, don't
375 * register the platform controller.
376 */
377 if (acpi_video_backlight_support())
378 return 0;
379#endif
380
381 memset(&buffer, 0, sizeof(struct calling_interface_buffer));
382 buffer.input[0] = find_token_location(BRIGHTNESS_TOKEN);
383
384 if (buffer.input[0] != -1) {
385 dell_send_request(&buffer, 0, 2);
386 max_intensity = buffer.output[3];
387 }
388
389 if (max_intensity) {
390 dell_backlight_device = backlight_device_register(
391 "dell_backlight",
392 NULL, NULL,
393 &dell_ops);
394
395 if (IS_ERR(dell_backlight_device)) {
396 ret = PTR_ERR(dell_backlight_device);
397 dell_backlight_device = NULL;
398 goto out;
399 }
400
401 dell_backlight_device->props.max_brightness = max_intensity;
402 dell_backlight_device->props.brightness =
403 dell_get_intensity(dell_backlight_device);
404 backlight_update_status(dell_backlight_device);
405 }
406
407 return 0;
408out:
409 if (wifi_rfkill)
410 rfkill_unregister(wifi_rfkill);
411 if (bluetooth_rfkill)
412 rfkill_unregister(bluetooth_rfkill);
413 if (wwan_rfkill)
414 rfkill_unregister(wwan_rfkill);
415 kfree(da_tokens);
416 return ret;
417}
418
419static void __exit dell_exit(void)
420{
421 backlight_device_unregister(dell_backlight_device);
422 if (wifi_rfkill)
423 rfkill_unregister(wifi_rfkill);
424 if (bluetooth_rfkill)
425 rfkill_unregister(bluetooth_rfkill);
426 if (wwan_rfkill)
427 rfkill_unregister(wwan_rfkill);
428}
429
430module_init(dell_init);
431module_exit(dell_exit);
432
433MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
434MODULE_DESCRIPTION("Dell laptop driver");
435MODULE_LICENSE("GPL");
436MODULE_ALIAS("dmi:*svnDellInc.:*:ct8:*");
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 02fe2b8b8939..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
@@ -90,7 +91,7 @@ enum {
90}; 91};
91 92
92static const char *cm_getv[] = { 93static const char *cm_getv[] = {
93 "WLDG", NULL, NULL, NULL, 94 "WLDG", "BTHG", NULL, NULL,
94 "CAMG", NULL, NULL, NULL, 95 "CAMG", NULL, NULL, NULL,
95 NULL, "PBLG", NULL, NULL, 96 NULL, "PBLG", NULL, NULL,
96 "CFVG", NULL, NULL, NULL, 97 "CFVG", NULL, NULL, NULL,
@@ -99,7 +100,7 @@ static const char *cm_getv[] = {
99}; 100};
100 101
101static const char *cm_setv[] = { 102static const char *cm_setv[] = {
102 "WLDS", NULL, NULL, NULL, 103 "WLDS", "BTHS", NULL, NULL,
103 "CAMS", NULL, NULL, NULL, 104 "CAMS", NULL, NULL, NULL,
104 "SDSP", "PBLS", "HDPS", NULL, 105 "SDSP", "PBLS", "HDPS", NULL,
105 "CFVS", NULL, NULL, NULL, 106 "CFVS", NULL, NULL, NULL,
@@ -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)
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)
@@ -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
584static 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
605static 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
542static int eeepc_hotk_add(struct acpi_device *device) 623static 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
855static 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
863static void eeepc_input_exit(void)
864{
865 if (ehotk->inputdev)
866 input_unregister_device(ehotk->inputdev);
747} 867}
748 868
749static void eeepc_hwmon_exit(void) 869static void eeepc_hwmon_exit(void)
@@ -762,6 +882,8 @@ static void eeepc_hwmon_exit(void)
762static void __exit eeepc_laptop_exit(void) 882static 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:
865fail_hwmon: 987fail_hwmon:
866 eeepc_backlight_exit(); 988 eeepc_backlight_exit();
867fail_backlight: 989fail_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 7c789f0a94d7..f41135f2fb29 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -382,6 +382,11 @@ static int __init hp_wmi_input_setup(void)
382 case KE_SW: 382 case KE_SW:
383 set_bit(EV_SW, hp_wmi_input_dev->evbit); 383 set_bit(EV_SW, hp_wmi_input_dev->evbit);
384 set_bit(key->keycode, hp_wmi_input_dev->swbit); 384 set_bit(key->keycode, hp_wmi_input_dev->swbit);
385
386 /* Set initial dock state */
387 input_report_switch(hp_wmi_input_dev, key->keycode,
388 hp_wmi_dock_state());
389 input_sync(hp_wmi_input_dev);
385 break; 390 break;
386 } 391 }
387 } 392 }
@@ -441,6 +446,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
441 bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set; 446 bluetooth_rfkill->toggle_radio = hp_wmi_bluetooth_set;
442 bluetooth_rfkill->user_claim_unsupported = 1; 447 bluetooth_rfkill->user_claim_unsupported = 1;
443 err = rfkill_register(bluetooth_rfkill); 448 err = rfkill_register(bluetooth_rfkill);
449 if (err)
444 goto register_bluetooth_error; 450 goto register_bluetooth_error;
445 } 451 }
446 452
@@ -457,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
457 463
458 return 0; 464 return 0;
459register_wwan_err: 465register_wwan_err:
460 rfkill_unregister(bluetooth_rfkill); 466 if (bluetooth_rfkill)
467 rfkill_unregister(bluetooth_rfkill);
461register_bluetooth_error: 468register_bluetooth_error:
462 rfkill_unregister(wifi_rfkill); 469 if (wifi_rfkill)
470 rfkill_unregister(wifi_rfkill);
463add_sysfs_error: 471add_sysfs_error:
464 cleanup_sysfs(device); 472 cleanup_sysfs(device);
465 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 3478453eba7a..bcbc05107ba8 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,7 +21,7 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define TPACPI_VERSION "0.21" 24#define TPACPI_VERSION "0.22"
25#define TPACPI_SYSFS_VERSION 0x020200 25#define TPACPI_SYSFS_VERSION 0x020200
26 26
27/* 27/*
@@ -122,6 +122,27 @@ enum {
122#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ 122#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */
123#define TPACPI_HKEY_INPUT_VERSION 0x4101 123#define TPACPI_HKEY_INPUT_VERSION 0x4101
124 124
125/* ACPI \WGSV commands */
126enum {
127 TP_ACPI_WGSV_GET_STATE = 0x01, /* Get state information */
128 TP_ACPI_WGSV_PWR_ON_ON_RESUME = 0x02, /* Resume WWAN powered on */
129 TP_ACPI_WGSV_PWR_OFF_ON_RESUME = 0x03, /* Resume WWAN powered off */
130 TP_ACPI_WGSV_SAVE_STATE = 0x04, /* Save state for S4/S5 */
131};
132
133/* TP_ACPI_WGSV_GET_STATE bits */
134enum {
135 TP_ACPI_WGSV_STATE_WWANEXIST = 0x0001, /* WWAN hw available */
136 TP_ACPI_WGSV_STATE_WWANPWR = 0x0002, /* WWAN radio enabled */
137 TP_ACPI_WGSV_STATE_WWANPWRRES = 0x0004, /* WWAN state at resume */
138 TP_ACPI_WGSV_STATE_WWANBIOSOFF = 0x0008, /* WWAN disabled in BIOS */
139 TP_ACPI_WGSV_STATE_BLTHEXIST = 0x0001, /* BLTH hw available */
140 TP_ACPI_WGSV_STATE_BLTHPWR = 0x0002, /* BLTH radio enabled */
141 TP_ACPI_WGSV_STATE_BLTHPWRRES = 0x0004, /* BLTH state at resume */
142 TP_ACPI_WGSV_STATE_BLTHBIOSOFF = 0x0008, /* BLTH disabled in BIOS */
143 TP_ACPI_WGSV_STATE_UWBEXIST = 0x0010, /* UWB hw available */
144 TP_ACPI_WGSV_STATE_UWBPWR = 0x0020, /* UWB radio enabled */
145};
125 146
126/**************************************************************************** 147/****************************************************************************
127 * Main driver 148 * Main driver
@@ -148,14 +169,17 @@ enum {
148enum { 169enum {
149 TPACPI_RFK_BLUETOOTH_SW_ID = 0, 170 TPACPI_RFK_BLUETOOTH_SW_ID = 0,
150 TPACPI_RFK_WWAN_SW_ID, 171 TPACPI_RFK_WWAN_SW_ID,
172 TPACPI_RFK_UWB_SW_ID,
151}; 173};
152 174
153/* Debugging */ 175/* Debugging */
154#define TPACPI_LOG TPACPI_FILE ": " 176#define TPACPI_LOG TPACPI_FILE ": "
155#define TPACPI_ERR KERN_ERR TPACPI_LOG 177#define TPACPI_ALERT KERN_ALERT TPACPI_LOG
156#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG 178#define TPACPI_CRIT KERN_CRIT TPACPI_LOG
157#define TPACPI_INFO KERN_INFO TPACPI_LOG 179#define TPACPI_ERR KERN_ERR TPACPI_LOG
158#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG 180#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
181#define TPACPI_INFO KERN_INFO TPACPI_LOG
182#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
159 183
160#define TPACPI_DBG_ALL 0xffff 184#define TPACPI_DBG_ALL 0xffff
161#define TPACPI_DBG_INIT 0x0001 185#define TPACPI_DBG_INIT 0x0001
@@ -201,6 +225,7 @@ struct ibm_struct {
201 void (*exit) (void); 225 void (*exit) (void);
202 void (*resume) (void); 226 void (*resume) (void);
203 void (*suspend) (pm_message_t state); 227 void (*suspend) (pm_message_t state);
228 void (*shutdown) (void);
204 229
205 struct list_head all_drivers; 230 struct list_head all_drivers;
206 231
@@ -239,6 +264,7 @@ static struct {
239 u32 bright_16levels:1; 264 u32 bright_16levels:1;
240 u32 bright_acpimode:1; 265 u32 bright_acpimode:1;
241 u32 wan:1; 266 u32 wan:1;
267 u32 uwb:1;
242 u32 fan_ctrl_status_undef:1; 268 u32 fan_ctrl_status_undef:1;
243 u32 input_device_registered:1; 269 u32 input_device_registered:1;
244 u32 platform_drv_registered:1; 270 u32 platform_drv_registered:1;
@@ -288,6 +314,18 @@ struct tpacpi_led_classdev {
288 unsigned int led; 314 unsigned int led;
289}; 315};
290 316
317#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
318static int dbg_wlswemul;
319static int tpacpi_wlsw_emulstate;
320static int dbg_bluetoothemul;
321static int tpacpi_bluetooth_emulstate;
322static int dbg_wwanemul;
323static int tpacpi_wwan_emulstate;
324static int dbg_uwbemul;
325static int tpacpi_uwb_emulstate;
326#endif
327
328
291/**************************************************************************** 329/****************************************************************************
292 **************************************************************************** 330 ****************************************************************************
293 * 331 *
@@ -728,6 +766,18 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
728 return 0; 766 return 0;
729} 767}
730 768
769static void tpacpi_shutdown_handler(struct platform_device *pdev)
770{
771 struct ibm_struct *ibm, *itmp;
772
773 list_for_each_entry_safe(ibm, itmp,
774 &tpacpi_all_drivers,
775 all_drivers) {
776 if (ibm->shutdown)
777 (ibm->shutdown)();
778 }
779}
780
731static struct platform_driver tpacpi_pdriver = { 781static struct platform_driver tpacpi_pdriver = {
732 .driver = { 782 .driver = {
733 .name = TPACPI_DRVR_NAME, 783 .name = TPACPI_DRVR_NAME,
@@ -735,6 +785,7 @@ static struct platform_driver tpacpi_pdriver = {
735 }, 785 },
736 .suspend = tpacpi_suspend_handler, 786 .suspend = tpacpi_suspend_handler,
737 .resume = tpacpi_resume_handler, 787 .resume = tpacpi_resume_handler,
788 .shutdown = tpacpi_shutdown_handler,
738}; 789};
739 790
740static struct platform_driver tpacpi_hwmon_pdriver = { 791static struct platform_driver tpacpi_hwmon_pdriver = {
@@ -922,11 +973,27 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
922 struct rfkill **rfk, 973 struct rfkill **rfk,
923 const enum rfkill_type rfktype, 974 const enum rfkill_type rfktype,
924 const char *name, 975 const char *name,
976 const bool set_default,
925 int (*toggle_radio)(void *, enum rfkill_state), 977 int (*toggle_radio)(void *, enum rfkill_state),
926 int (*get_state)(void *, enum rfkill_state *)) 978 int (*get_state)(void *, enum rfkill_state *))
927{ 979{
928 int res; 980 int res;
929 enum rfkill_state initial_state; 981 enum rfkill_state initial_state = RFKILL_STATE_SOFT_BLOCKED;
982
983 res = get_state(NULL, &initial_state);
984 if (res < 0) {
985 printk(TPACPI_ERR
986 "failed to read initial state for %s, error %d; "
987 "will turn radio off\n", name, res);
988 } else if (set_default) {
989 /* try to set the initial state as the default for the rfkill
990 * type, since we ask the firmware to preserve it across S5 in
991 * NVRAM */
992 rfkill_set_default(rfktype,
993 (initial_state == RFKILL_STATE_UNBLOCKED) ?
994 RFKILL_STATE_UNBLOCKED :
995 RFKILL_STATE_SOFT_BLOCKED);
996 }
930 997
931 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); 998 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
932 if (!*rfk) { 999 if (!*rfk) {
@@ -938,9 +1005,7 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
938 (*rfk)->name = name; 1005 (*rfk)->name = name;
939 (*rfk)->get_state = get_state; 1006 (*rfk)->get_state = get_state;
940 (*rfk)->toggle_radio = toggle_radio; 1007 (*rfk)->toggle_radio = toggle_radio;
941 1008 (*rfk)->state = initial_state;
942 if (!get_state(NULL, &initial_state))
943 (*rfk)->state = initial_state;
944 1009
945 res = rfkill_register(*rfk); 1010 res = rfkill_register(*rfk);
946 if (res < 0) { 1011 if (res < 0) {
@@ -1006,6 +1071,119 @@ static DRIVER_ATTR(version, S_IRUGO,
1006 1071
1007/* --------------------------------------------------------------------- */ 1072/* --------------------------------------------------------------------- */
1008 1073
1074#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1075
1076static void tpacpi_send_radiosw_update(void);
1077
1078/* wlsw_emulstate ------------------------------------------------------ */
1079static ssize_t tpacpi_driver_wlsw_emulstate_show(struct device_driver *drv,
1080 char *buf)
1081{
1082 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wlsw_emulstate);
1083}
1084
1085static ssize_t tpacpi_driver_wlsw_emulstate_store(struct device_driver *drv,
1086 const char *buf, size_t count)
1087{
1088 unsigned long t;
1089
1090 if (parse_strtoul(buf, 1, &t))
1091 return -EINVAL;
1092
1093 if (tpacpi_wlsw_emulstate != t) {
1094 tpacpi_wlsw_emulstate = !!t;
1095 tpacpi_send_radiosw_update();
1096 } else
1097 tpacpi_wlsw_emulstate = !!t;
1098
1099 return count;
1100}
1101
1102static DRIVER_ATTR(wlsw_emulstate, S_IWUSR | S_IRUGO,
1103 tpacpi_driver_wlsw_emulstate_show,
1104 tpacpi_driver_wlsw_emulstate_store);
1105
1106/* bluetooth_emulstate ------------------------------------------------- */
1107static ssize_t tpacpi_driver_bluetooth_emulstate_show(
1108 struct device_driver *drv,
1109 char *buf)
1110{
1111 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_bluetooth_emulstate);
1112}
1113
1114static ssize_t tpacpi_driver_bluetooth_emulstate_store(
1115 struct device_driver *drv,
1116 const char *buf, size_t count)
1117{
1118 unsigned long t;
1119
1120 if (parse_strtoul(buf, 1, &t))
1121 return -EINVAL;
1122
1123 tpacpi_bluetooth_emulstate = !!t;
1124
1125 return count;
1126}
1127
1128static DRIVER_ATTR(bluetooth_emulstate, S_IWUSR | S_IRUGO,
1129 tpacpi_driver_bluetooth_emulstate_show,
1130 tpacpi_driver_bluetooth_emulstate_store);
1131
1132/* wwan_emulstate ------------------------------------------------- */
1133static ssize_t tpacpi_driver_wwan_emulstate_show(
1134 struct device_driver *drv,
1135 char *buf)
1136{
1137 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_wwan_emulstate);
1138}
1139
1140static ssize_t tpacpi_driver_wwan_emulstate_store(
1141 struct device_driver *drv,
1142 const char *buf, size_t count)
1143{
1144 unsigned long t;
1145
1146 if (parse_strtoul(buf, 1, &t))
1147 return -EINVAL;
1148
1149 tpacpi_wwan_emulstate = !!t;
1150
1151 return count;
1152}
1153
1154static DRIVER_ATTR(wwan_emulstate, S_IWUSR | S_IRUGO,
1155 tpacpi_driver_wwan_emulstate_show,
1156 tpacpi_driver_wwan_emulstate_store);
1157
1158/* uwb_emulstate ------------------------------------------------- */
1159static ssize_t tpacpi_driver_uwb_emulstate_show(
1160 struct device_driver *drv,
1161 char *buf)
1162{
1163 return snprintf(buf, PAGE_SIZE, "%d\n", !!tpacpi_uwb_emulstate);
1164}
1165
1166static ssize_t tpacpi_driver_uwb_emulstate_store(
1167 struct device_driver *drv,
1168 const char *buf, size_t count)
1169{
1170 unsigned long t;
1171
1172 if (parse_strtoul(buf, 1, &t))
1173 return -EINVAL;
1174
1175 tpacpi_uwb_emulstate = !!t;
1176
1177 return count;
1178}
1179
1180static DRIVER_ATTR(uwb_emulstate, S_IWUSR | S_IRUGO,
1181 tpacpi_driver_uwb_emulstate_show,
1182 tpacpi_driver_uwb_emulstate_store);
1183#endif
1184
1185/* --------------------------------------------------------------------- */
1186
1009static struct driver_attribute *tpacpi_driver_attributes[] = { 1187static struct driver_attribute *tpacpi_driver_attributes[] = {
1010 &driver_attr_debug_level, &driver_attr_version, 1188 &driver_attr_debug_level, &driver_attr_version,
1011 &driver_attr_interface_version, 1189 &driver_attr_interface_version,
@@ -1022,6 +1200,17 @@ static int __init tpacpi_create_driver_attributes(struct device_driver *drv)
1022 i++; 1200 i++;
1023 } 1201 }
1024 1202
1203#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1204 if (!res && dbg_wlswemul)
1205 res = driver_create_file(drv, &driver_attr_wlsw_emulstate);
1206 if (!res && dbg_bluetoothemul)
1207 res = driver_create_file(drv, &driver_attr_bluetooth_emulstate);
1208 if (!res && dbg_wwanemul)
1209 res = driver_create_file(drv, &driver_attr_wwan_emulstate);
1210 if (!res && dbg_uwbemul)
1211 res = driver_create_file(drv, &driver_attr_uwb_emulstate);
1212#endif
1213
1025 return res; 1214 return res;
1026} 1215}
1027 1216
@@ -1031,6 +1220,13 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv)
1031 1220
1032 for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++) 1221 for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++)
1033 driver_remove_file(drv, tpacpi_driver_attributes[i]); 1222 driver_remove_file(drv, tpacpi_driver_attributes[i]);
1223
1224#ifdef THINKPAD_ACPI_DEBUGFACILITIES
1225 driver_remove_file(drv, &driver_attr_wlsw_emulstate);
1226 driver_remove_file(drv, &driver_attr_bluetooth_emulstate);
1227 driver_remove_file(drv, &driver_attr_wwan_emulstate);
1228 driver_remove_file(drv, &driver_attr_uwb_emulstate);
1229#endif
1034} 1230}
1035 1231
1036/**************************************************************************** 1232/****************************************************************************
@@ -1216,6 +1412,12 @@ static struct attribute_set *hotkey_dev_attributes;
1216 1412
1217static int hotkey_get_wlsw(int *status) 1413static int hotkey_get_wlsw(int *status)
1218{ 1414{
1415#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
1416 if (dbg_wlswemul) {
1417 *status = !!tpacpi_wlsw_emulstate;
1418 return 0;
1419 }
1420#endif
1219 if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) 1421 if (!acpi_evalf(hkey_handle, status, "WLSW", "d"))
1220 return -EIO; 1422 return -EIO;
1221 return 0; 1423 return 0;
@@ -1678,7 +1880,7 @@ static ssize_t hotkey_mask_show(struct device *dev,
1678{ 1880{
1679 int res; 1881 int res;
1680 1882
1681 if (mutex_lock_interruptible(&hotkey_mutex)) 1883 if (mutex_lock_killable(&hotkey_mutex))
1682 return -ERESTARTSYS; 1884 return -ERESTARTSYS;
1683 res = hotkey_mask_get(); 1885 res = hotkey_mask_get();
1684 mutex_unlock(&hotkey_mutex); 1886 mutex_unlock(&hotkey_mutex);
@@ -1697,7 +1899,7 @@ static ssize_t hotkey_mask_store(struct device *dev,
1697 if (parse_strtoul(buf, 0xffffffffUL, &t)) 1899 if (parse_strtoul(buf, 0xffffffffUL, &t))
1698 return -EINVAL; 1900 return -EINVAL;
1699 1901
1700 if (mutex_lock_interruptible(&hotkey_mutex)) 1902 if (mutex_lock_killable(&hotkey_mutex))
1701 return -ERESTARTSYS; 1903 return -ERESTARTSYS;
1702 1904
1703 res = hotkey_mask_set(t); 1905 res = hotkey_mask_set(t);
@@ -1783,7 +1985,7 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
1783 ((t & ~TPACPI_HKEY_NVRAM_KNOWN_MASK) != 0)) 1985 ((t & ~TPACPI_HKEY_NVRAM_KNOWN_MASK) != 0))
1784 return -EINVAL; 1986 return -EINVAL;
1785 1987
1786 if (mutex_lock_interruptible(&hotkey_mutex)) 1988 if (mutex_lock_killable(&hotkey_mutex))
1787 return -ERESTARTSYS; 1989 return -ERESTARTSYS;
1788 1990
1789 HOTKEY_CONFIG_CRITICAL_START 1991 HOTKEY_CONFIG_CRITICAL_START
@@ -1818,7 +2020,7 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
1818 if (parse_strtoul(buf, 25, &t)) 2020 if (parse_strtoul(buf, 25, &t))
1819 return -EINVAL; 2021 return -EINVAL;
1820 2022
1821 if (mutex_lock_interruptible(&hotkey_mutex)) 2023 if (mutex_lock_killable(&hotkey_mutex))
1822 return -ERESTARTSYS; 2024 return -ERESTARTSYS;
1823 2025
1824 hotkey_poll_freq = t; 2026 hotkey_poll_freq = t;
@@ -1958,6 +2160,7 @@ static struct attribute *hotkey_mask_attributes[] __initdata = {
1958 2160
1959static void bluetooth_update_rfk(void); 2161static void bluetooth_update_rfk(void);
1960static void wan_update_rfk(void); 2162static void wan_update_rfk(void);
2163static void uwb_update_rfk(void);
1961static void tpacpi_send_radiosw_update(void) 2164static void tpacpi_send_radiosw_update(void)
1962{ 2165{
1963 int wlsw; 2166 int wlsw;
@@ -1967,6 +2170,8 @@ static void tpacpi_send_radiosw_update(void)
1967 bluetooth_update_rfk(); 2170 bluetooth_update_rfk();
1968 if (tp_features.wan) 2171 if (tp_features.wan)
1969 wan_update_rfk(); 2172 wan_update_rfk();
2173 if (tp_features.uwb)
2174 uwb_update_rfk();
1970 2175
1971 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { 2176 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
1972 mutex_lock(&tpacpi_inputdev_send_mutex); 2177 mutex_lock(&tpacpi_inputdev_send_mutex);
@@ -2222,6 +2427,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2222 hotkey_source_mask, hotkey_poll_freq); 2427 hotkey_source_mask, hotkey_poll_freq);
2223#endif 2428#endif
2224 2429
2430#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
2431 if (dbg_wlswemul) {
2432 tp_features.hotkey_wlsw = 1;
2433 printk(TPACPI_INFO
2434 "radio switch emulation enabled\n");
2435 } else
2436#endif
2225 /* Not all thinkpads have a hardware radio switch */ 2437 /* Not all thinkpads have a hardware radio switch */
2226 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 2438 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
2227 tp_features.hotkey_wlsw = 1; 2439 tp_features.hotkey_wlsw = 1;
@@ -2361,13 +2573,154 @@ err_exit:
2361 return (res < 0)? res : 1; 2573 return (res < 0)? res : 1;
2362} 2574}
2363 2575
2576static bool hotkey_notify_hotkey(const u32 hkey,
2577 bool *send_acpi_ev,
2578 bool *ignore_acpi_ev)
2579{
2580 /* 0x1000-0x1FFF: key presses */
2581 unsigned int scancode = hkey & 0xfff;
2582 *send_acpi_ev = true;
2583 *ignore_acpi_ev = false;
2584
2585 if (scancode > 0 && scancode < 0x21) {
2586 scancode--;
2587 if (!(hotkey_source_mask & (1 << scancode))) {
2588 tpacpi_input_send_key(scancode);
2589 *send_acpi_ev = false;
2590 } else {
2591 *ignore_acpi_ev = true;
2592 }
2593 return true;
2594 }
2595 return false;
2596}
2597
2598static bool hotkey_notify_wakeup(const u32 hkey,
2599 bool *send_acpi_ev,
2600 bool *ignore_acpi_ev)
2601{
2602 /* 0x2000-0x2FFF: Wakeup reason */
2603 *send_acpi_ev = true;
2604 *ignore_acpi_ev = false;
2605
2606 switch (hkey) {
2607 case 0x2304: /* suspend, undock */
2608 case 0x2404: /* hibernation, undock */
2609 hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
2610 *ignore_acpi_ev = true;
2611 break;
2612
2613 case 0x2305: /* suspend, bay eject */
2614 case 0x2405: /* hibernation, bay eject */
2615 hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
2616 *ignore_acpi_ev = true;
2617 break;
2618
2619 case 0x2313: /* Battery on critical low level (S3) */
2620 case 0x2413: /* Battery on critical low level (S4) */
2621 printk(TPACPI_ALERT
2622 "EMERGENCY WAKEUP: battery almost empty\n");
2623 /* how to auto-heal: */
2624 /* 2313: woke up from S3, go to S4/S5 */
2625 /* 2413: woke up from S4, go to S5 */
2626 break;
2627
2628 default:
2629 return false;
2630 }
2631
2632 if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
2633 printk(TPACPI_INFO
2634 "woke up due to a hot-unplug "
2635 "request...\n");
2636 hotkey_wakeup_reason_notify_change();
2637 }
2638 return true;
2639}
2640
2641static bool hotkey_notify_usrevent(const u32 hkey,
2642 bool *send_acpi_ev,
2643 bool *ignore_acpi_ev)
2644{
2645 /* 0x5000-0x5FFF: human interface helpers */
2646 *send_acpi_ev = true;
2647 *ignore_acpi_ev = false;
2648
2649 switch (hkey) {
2650 case 0x5010: /* Lenovo new BIOS: brightness changed */
2651 case 0x500b: /* X61t: tablet pen inserted into bay */
2652 case 0x500c: /* X61t: tablet pen removed from bay */
2653 return true;
2654
2655 case 0x5009: /* X41t-X61t: swivel up (tablet mode) */
2656 case 0x500a: /* X41t-X61t: swivel down (normal mode) */
2657 tpacpi_input_send_tabletsw();
2658 hotkey_tablet_mode_notify_change();
2659 *send_acpi_ev = false;
2660 return true;
2661
2662 case 0x5001:
2663 case 0x5002:
2664 /* LID switch events. Do not propagate */
2665 *ignore_acpi_ev = true;
2666 return true;
2667
2668 default:
2669 return false;
2670 }
2671}
2672
2673static bool hotkey_notify_thermal(const u32 hkey,
2674 bool *send_acpi_ev,
2675 bool *ignore_acpi_ev)
2676{
2677 /* 0x6000-0x6FFF: thermal alarms */
2678 *send_acpi_ev = true;
2679 *ignore_acpi_ev = false;
2680
2681 switch (hkey) {
2682 case 0x6011:
2683 printk(TPACPI_CRIT
2684 "THERMAL ALARM: battery is too hot!\n");
2685 /* recommended action: warn user through gui */
2686 return true;
2687 case 0x6012:
2688 printk(TPACPI_ALERT
2689 "THERMAL EMERGENCY: battery is extremely hot!\n");
2690 /* recommended action: immediate sleep/hibernate */
2691 return true;
2692 case 0x6021:
2693 printk(TPACPI_CRIT
2694 "THERMAL ALARM: "
2695 "a sensor reports something is too hot!\n");
2696 /* recommended action: warn user through gui, that */
2697 /* some internal component is too hot */
2698 return true;
2699 case 0x6022:
2700 printk(TPACPI_ALERT
2701 "THERMAL EMERGENCY: "
2702 "a sensor reports something is extremely hot!\n");
2703 /* recommended action: immediate sleep/hibernate */
2704 return true;
2705 case 0x6030:
2706 printk(TPACPI_INFO
2707 "EC reports that Thermal Table has changed\n");
2708 /* recommended action: do nothing, we don't have
2709 * Lenovo ATM information */
2710 return true;
2711 default:
2712 printk(TPACPI_ALERT
2713 "THERMAL ALERT: unknown thermal alarm received\n");
2714 return false;
2715 }
2716}
2717
2364static void hotkey_notify(struct ibm_struct *ibm, u32 event) 2718static void hotkey_notify(struct ibm_struct *ibm, u32 event)
2365{ 2719{
2366 u32 hkey; 2720 u32 hkey;
2367 unsigned int scancode; 2721 bool send_acpi_ev;
2368 int send_acpi_ev; 2722 bool ignore_acpi_ev;
2369 int ignore_acpi_ev; 2723 bool known_ev;
2370 int unk_ev;
2371 2724
2372 if (event != 0x80) { 2725 if (event != 0x80) {
2373 printk(TPACPI_ERR 2726 printk(TPACPI_ERR
@@ -2375,7 +2728,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
2375 /* forward it to userspace, maybe it knows how to handle it */ 2728 /* forward it to userspace, maybe it knows how to handle it */
2376 acpi_bus_generate_netlink_event( 2729 acpi_bus_generate_netlink_event(
2377 ibm->acpi->device->pnp.device_class, 2730 ibm->acpi->device->pnp.device_class,
2378 ibm->acpi->device->dev.bus_id, 2731 dev_name(&ibm->acpi->device->dev),
2379 event, 0); 2732 event, 0);
2380 return; 2733 return;
2381 } 2734 }
@@ -2391,107 +2744,72 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
2391 return; 2744 return;
2392 } 2745 }
2393 2746
2394 send_acpi_ev = 1; 2747 send_acpi_ev = true;
2395 ignore_acpi_ev = 0; 2748 ignore_acpi_ev = false;
2396 unk_ev = 0;
2397 2749
2398 switch (hkey >> 12) { 2750 switch (hkey >> 12) {
2399 case 1: 2751 case 1:
2400 /* 0x1000-0x1FFF: key presses */ 2752 /* 0x1000-0x1FFF: key presses */
2401 scancode = hkey & 0xfff; 2753 known_ev = hotkey_notify_hotkey(hkey, &send_acpi_ev,
2402 if (scancode > 0 && scancode < 0x21) { 2754 &ignore_acpi_ev);
2403 scancode--;
2404 if (!(hotkey_source_mask & (1 << scancode))) {
2405 tpacpi_input_send_key(scancode);
2406 send_acpi_ev = 0;
2407 } else {
2408 ignore_acpi_ev = 1;
2409 }
2410 } else {
2411 unk_ev = 1;
2412 }
2413 break; 2755 break;
2414 case 2: 2756 case 2:
2415 /* Wakeup reason */ 2757 /* 0x2000-0x2FFF: Wakeup reason */
2416 switch (hkey) { 2758 known_ev = hotkey_notify_wakeup(hkey, &send_acpi_ev,
2417 case 0x2304: /* suspend, undock */ 2759 &ignore_acpi_ev);
2418 case 0x2404: /* hibernation, undock */
2419 hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK;
2420 ignore_acpi_ev = 1;
2421 break;
2422 case 0x2305: /* suspend, bay eject */
2423 case 0x2405: /* hibernation, bay eject */
2424 hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ;
2425 ignore_acpi_ev = 1;
2426 break;
2427 default:
2428 unk_ev = 1;
2429 }
2430 if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) {
2431 printk(TPACPI_INFO
2432 "woke up due to a hot-unplug "
2433 "request...\n");
2434 hotkey_wakeup_reason_notify_change();
2435 }
2436 break; 2760 break;
2437 case 3: 2761 case 3:
2438 /* bay-related wakeups */ 2762 /* 0x3000-0x3FFF: bay-related wakeups */
2439 if (hkey == 0x3003) { 2763 if (hkey == 0x3003) {
2440 hotkey_autosleep_ack = 1; 2764 hotkey_autosleep_ack = 1;
2441 printk(TPACPI_INFO 2765 printk(TPACPI_INFO
2442 "bay ejected\n"); 2766 "bay ejected\n");
2443 hotkey_wakeup_hotunplug_complete_notify_change(); 2767 hotkey_wakeup_hotunplug_complete_notify_change();
2768 known_ev = true;
2444 } else { 2769 } else {
2445 unk_ev = 1; 2770 known_ev = false;
2446 } 2771 }
2447 break; 2772 break;
2448 case 4: 2773 case 4:
2449 /* dock-related wakeups */ 2774 /* 0x4000-0x4FFF: dock-related wakeups */
2450 if (hkey == 0x4003) { 2775 if (hkey == 0x4003) {
2451 hotkey_autosleep_ack = 1; 2776 hotkey_autosleep_ack = 1;
2452 printk(TPACPI_INFO 2777 printk(TPACPI_INFO
2453 "undocked\n"); 2778 "undocked\n");
2454 hotkey_wakeup_hotunplug_complete_notify_change(); 2779 hotkey_wakeup_hotunplug_complete_notify_change();
2780 known_ev = true;
2455 } else { 2781 } else {
2456 unk_ev = 1; 2782 known_ev = false;
2457 } 2783 }
2458 break; 2784 break;
2459 case 5: 2785 case 5:
2460 /* 0x5000-0x5FFF: human interface helpers */ 2786 /* 0x5000-0x5FFF: human interface helpers */
2461 switch (hkey) { 2787 known_ev = hotkey_notify_usrevent(hkey, &send_acpi_ev,
2462 case 0x5010: /* Lenovo new BIOS: brightness changed */ 2788 &ignore_acpi_ev);
2463 case 0x500b: /* X61t: tablet pen inserted into bay */ 2789 break;
2464 case 0x500c: /* X61t: tablet pen removed from bay */ 2790 case 6:
2465 break; 2791 /* 0x6000-0x6FFF: thermal alarms */
2466 case 0x5009: /* X41t-X61t: swivel up (tablet mode) */ 2792 known_ev = hotkey_notify_thermal(hkey, &send_acpi_ev,
2467 case 0x500a: /* X41t-X61t: swivel down (normal mode) */ 2793 &ignore_acpi_ev);
2468 tpacpi_input_send_tabletsw();
2469 hotkey_tablet_mode_notify_change();
2470 send_acpi_ev = 0;
2471 break;
2472 case 0x5001:
2473 case 0x5002:
2474 /* LID switch events. Do not propagate */
2475 ignore_acpi_ev = 1;
2476 break;
2477 default:
2478 unk_ev = 1;
2479 }
2480 break; 2794 break;
2481 case 7: 2795 case 7:
2482 /* 0x7000-0x7FFF: misc */ 2796 /* 0x7000-0x7FFF: misc */
2483 if (tp_features.hotkey_wlsw && hkey == 0x7000) { 2797 if (tp_features.hotkey_wlsw && hkey == 0x7000) {
2484 tpacpi_send_radiosw_update(); 2798 tpacpi_send_radiosw_update();
2485 send_acpi_ev = 0; 2799 send_acpi_ev = 0;
2800 known_ev = true;
2486 break; 2801 break;
2487 } 2802 }
2488 /* fallthrough to default */ 2803 /* fallthrough to default */
2489 default: 2804 default:
2490 unk_ev = 1; 2805 known_ev = false;
2491 } 2806 }
2492 if (unk_ev) { 2807 if (!known_ev) {
2493 printk(TPACPI_NOTICE 2808 printk(TPACPI_NOTICE
2494 "unhandled HKEY event 0x%04x\n", hkey); 2809 "unhandled HKEY event 0x%04x\n", hkey);
2810 printk(TPACPI_NOTICE
2811 "please report the conditions when this "
2812 "event happened to %s\n", TPACPI_MAIL);
2495 } 2813 }
2496 2814
2497 /* Legacy events */ 2815 /* Legacy events */
@@ -2505,7 +2823,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
2505 if (!ignore_acpi_ev && send_acpi_ev) { 2823 if (!ignore_acpi_ev && send_acpi_ev) {
2506 acpi_bus_generate_netlink_event( 2824 acpi_bus_generate_netlink_event(
2507 ibm->acpi->device->pnp.device_class, 2825 ibm->acpi->device->pnp.device_class,
2508 ibm->acpi->device->dev.bus_id, 2826 dev_name(&ibm->acpi->device->dev),
2509 event, hkey); 2827 event, hkey);
2510 } 2828 }
2511 } 2829 }
@@ -2544,7 +2862,7 @@ static int hotkey_read(char *p)
2544 return len; 2862 return len;
2545 } 2863 }
2546 2864
2547 if (mutex_lock_interruptible(&hotkey_mutex)) 2865 if (mutex_lock_killable(&hotkey_mutex))
2548 return -ERESTARTSYS; 2866 return -ERESTARTSYS;
2549 res = hotkey_status_get(&status); 2867 res = hotkey_status_get(&status);
2550 if (!res) 2868 if (!res)
@@ -2575,7 +2893,7 @@ static int hotkey_write(char *buf)
2575 if (!tp_features.hotkey) 2893 if (!tp_features.hotkey)
2576 return -ENODEV; 2894 return -ENODEV;
2577 2895
2578 if (mutex_lock_interruptible(&hotkey_mutex)) 2896 if (mutex_lock_killable(&hotkey_mutex))
2579 return -ERESTARTSYS; 2897 return -ERESTARTSYS;
2580 2898
2581 status = -1; 2899 status = -1;
@@ -2640,11 +2958,28 @@ enum {
2640 /* ACPI GBDC/SBDC bits */ 2958 /* ACPI GBDC/SBDC bits */
2641 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ 2959 TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */
2642 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ 2960 TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */
2643 TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ 2961 TP_ACPI_BLUETOOTH_RESUMECTRL = 0x04, /* Bluetooth state at resume:
2962 off / last state */
2963};
2964
2965enum {
2966 /* ACPI \BLTH commands */
2967 TP_ACPI_BLTH_GET_ULTRAPORT_ID = 0x00, /* Get Ultraport BT ID */
2968 TP_ACPI_BLTH_GET_PWR_ON_RESUME = 0x01, /* Get power-on-resume state */
2969 TP_ACPI_BLTH_PWR_ON_ON_RESUME = 0x02, /* Resume powered on */
2970 TP_ACPI_BLTH_PWR_OFF_ON_RESUME = 0x03, /* Resume powered off */
2971 TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */
2644}; 2972};
2645 2973
2646static struct rfkill *tpacpi_bluetooth_rfkill; 2974static struct rfkill *tpacpi_bluetooth_rfkill;
2647 2975
2976static void bluetooth_suspend(pm_message_t state)
2977{
2978 /* Try to make sure radio will resume powered off */
2979 acpi_evalf(NULL, NULL, "\\BLTH", "vd",
2980 TP_ACPI_BLTH_PWR_OFF_ON_RESUME);
2981}
2982
2648static int bluetooth_get_radiosw(void) 2983static int bluetooth_get_radiosw(void)
2649{ 2984{
2650 int status; 2985 int status;
@@ -2656,6 +2991,12 @@ static int bluetooth_get_radiosw(void)
2656 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) 2991 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
2657 return RFKILL_STATE_HARD_BLOCKED; 2992 return RFKILL_STATE_HARD_BLOCKED;
2658 2993
2994#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
2995 if (dbg_bluetoothemul)
2996 return (tpacpi_bluetooth_emulstate) ?
2997 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
2998#endif
2999
2659 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 3000 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d"))
2660 return -EIO; 3001 return -EIO;
2661 3002
@@ -2689,12 +3030,20 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
2689 && radio_on) 3030 && radio_on)
2690 return -EPERM; 3031 return -EPERM;
2691 3032
2692 if (!acpi_evalf(hkey_handle, &status, "GBDC", "d")) 3033#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
2693 return -EIO; 3034 if (dbg_bluetoothemul) {
3035 tpacpi_bluetooth_emulstate = !!radio_on;
3036 if (update_rfk)
3037 bluetooth_update_rfk();
3038 return 0;
3039 }
3040#endif
3041
3042 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
2694 if (radio_on) 3043 if (radio_on)
2695 status |= TP_ACPI_BLUETOOTH_RADIOSSW; 3044 status = TP_ACPI_BLUETOOTH_RADIOSSW;
2696 else 3045 else
2697 status &= ~TP_ACPI_BLUETOOTH_RADIOSSW; 3046 status = 0;
2698 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3047 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
2699 return -EIO; 3048 return -EIO;
2700 3049
@@ -2765,8 +3114,19 @@ static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
2765 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 3114 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
2766} 3115}
2767 3116
3117static void bluetooth_shutdown(void)
3118{
3119 /* Order firmware to save current state to NVRAM */
3120 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
3121 TP_ACPI_BLTH_SAVE_STATE))
3122 printk(TPACPI_NOTICE
3123 "failed to save bluetooth state to NVRAM\n");
3124}
3125
2768static void bluetooth_exit(void) 3126static void bluetooth_exit(void)
2769{ 3127{
3128 bluetooth_shutdown();
3129
2770 if (tpacpi_bluetooth_rfkill) 3130 if (tpacpi_bluetooth_rfkill)
2771 rfkill_unregister(tpacpi_bluetooth_rfkill); 3131 rfkill_unregister(tpacpi_bluetooth_rfkill);
2772 3132
@@ -2792,6 +3152,13 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
2792 str_supported(tp_features.bluetooth), 3152 str_supported(tp_features.bluetooth),
2793 status); 3153 status);
2794 3154
3155#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3156 if (dbg_bluetoothemul) {
3157 tp_features.bluetooth = 1;
3158 printk(TPACPI_INFO
3159 "bluetooth switch emulation enabled\n");
3160 } else
3161#endif
2795 if (tp_features.bluetooth && 3162 if (tp_features.bluetooth &&
2796 !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { 3163 !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
2797 /* no bluetooth hardware present in system */ 3164 /* no bluetooth hardware present in system */
@@ -2812,6 +3179,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
2812 &tpacpi_bluetooth_rfkill, 3179 &tpacpi_bluetooth_rfkill,
2813 RFKILL_TYPE_BLUETOOTH, 3180 RFKILL_TYPE_BLUETOOTH,
2814 "tpacpi_bluetooth_sw", 3181 "tpacpi_bluetooth_sw",
3182 true,
2815 tpacpi_bluetooth_rfk_set, 3183 tpacpi_bluetooth_rfk_set,
2816 tpacpi_bluetooth_rfk_get); 3184 tpacpi_bluetooth_rfk_get);
2817 if (res) { 3185 if (res) {
@@ -2864,6 +3232,8 @@ static struct ibm_struct bluetooth_driver_data = {
2864 .read = bluetooth_read, 3232 .read = bluetooth_read,
2865 .write = bluetooth_write, 3233 .write = bluetooth_write,
2866 .exit = bluetooth_exit, 3234 .exit = bluetooth_exit,
3235 .suspend = bluetooth_suspend,
3236 .shutdown = bluetooth_shutdown,
2867}; 3237};
2868 3238
2869/************************************************************************* 3239/*************************************************************************
@@ -2874,11 +3244,19 @@ enum {
2874 /* ACPI GWAN/SWAN bits */ 3244 /* ACPI GWAN/SWAN bits */
2875 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ 3245 TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */
2876 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ 3246 TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */
2877 TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ 3247 TP_ACPI_WANCARD_RESUMECTRL = 0x04, /* Wan state at resume:
3248 off / last state */
2878}; 3249};
2879 3250
2880static struct rfkill *tpacpi_wan_rfkill; 3251static struct rfkill *tpacpi_wan_rfkill;
2881 3252
3253static void wan_suspend(pm_message_t state)
3254{
3255 /* Try to make sure radio will resume powered off */
3256 acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
3257 TP_ACPI_WGSV_PWR_OFF_ON_RESUME);
3258}
3259
2882static int wan_get_radiosw(void) 3260static int wan_get_radiosw(void)
2883{ 3261{
2884 int status; 3262 int status;
@@ -2890,6 +3268,12 @@ static int wan_get_radiosw(void)
2890 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status) 3268 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
2891 return RFKILL_STATE_HARD_BLOCKED; 3269 return RFKILL_STATE_HARD_BLOCKED;
2892 3270
3271#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3272 if (dbg_wwanemul)
3273 return (tpacpi_wwan_emulstate) ?
3274 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
3275#endif
3276
2893 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3277 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d"))
2894 return -EIO; 3278 return -EIO;
2895 3279
@@ -2923,12 +3307,20 @@ static int wan_set_radiosw(int radio_on, int update_rfk)
2923 && radio_on) 3307 && radio_on)
2924 return -EPERM; 3308 return -EPERM;
2925 3309
2926 if (!acpi_evalf(hkey_handle, &status, "GWAN", "d")) 3310#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
2927 return -EIO; 3311 if (dbg_wwanemul) {
3312 tpacpi_wwan_emulstate = !!radio_on;
3313 if (update_rfk)
3314 wan_update_rfk();
3315 return 0;
3316 }
3317#endif
3318
3319 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */
2928 if (radio_on) 3320 if (radio_on)
2929 status |= TP_ACPI_WANCARD_RADIOSSW; 3321 status = TP_ACPI_WANCARD_RADIOSSW;
2930 else 3322 else
2931 status &= ~TP_ACPI_WANCARD_RADIOSSW; 3323 status = 0;
2932 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 3324 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
2933 return -EIO; 3325 return -EIO;
2934 3326
@@ -2999,8 +3391,19 @@ static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
2999 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 3391 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3000} 3392}
3001 3393
3394static void wan_shutdown(void)
3395{
3396 /* Order firmware to save current state to NVRAM */
3397 if (!acpi_evalf(NULL, NULL, "\\WGSV", "vd",
3398 TP_ACPI_WGSV_SAVE_STATE))
3399 printk(TPACPI_NOTICE
3400 "failed to save WWAN state to NVRAM\n");
3401}
3402
3002static void wan_exit(void) 3403static void wan_exit(void)
3003{ 3404{
3405 wan_shutdown();
3406
3004 if (tpacpi_wan_rfkill) 3407 if (tpacpi_wan_rfkill)
3005 rfkill_unregister(tpacpi_wan_rfkill); 3408 rfkill_unregister(tpacpi_wan_rfkill);
3006 3409
@@ -3024,6 +3427,13 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3024 str_supported(tp_features.wan), 3427 str_supported(tp_features.wan),
3025 status); 3428 status);
3026 3429
3430#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3431 if (dbg_wwanemul) {
3432 tp_features.wan = 1;
3433 printk(TPACPI_INFO
3434 "wwan switch emulation enabled\n");
3435 } else
3436#endif
3027 if (tp_features.wan && 3437 if (tp_features.wan &&
3028 !(status & TP_ACPI_WANCARD_HWPRESENT)) { 3438 !(status & TP_ACPI_WANCARD_HWPRESENT)) {
3029 /* no wan hardware present in system */ 3439 /* no wan hardware present in system */
@@ -3044,6 +3454,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3044 &tpacpi_wan_rfkill, 3454 &tpacpi_wan_rfkill,
3045 RFKILL_TYPE_WWAN, 3455 RFKILL_TYPE_WWAN,
3046 "tpacpi_wwan_sw", 3456 "tpacpi_wwan_sw",
3457 true,
3047 tpacpi_wan_rfk_set, 3458 tpacpi_wan_rfk_set,
3048 tpacpi_wan_rfk_get); 3459 tpacpi_wan_rfk_get);
3049 if (res) { 3460 if (res) {
@@ -3096,6 +3507,164 @@ static struct ibm_struct wan_driver_data = {
3096 .read = wan_read, 3507 .read = wan_read,
3097 .write = wan_write, 3508 .write = wan_write,
3098 .exit = wan_exit, 3509 .exit = wan_exit,
3510 .suspend = wan_suspend,
3511 .shutdown = wan_shutdown,
3512};
3513
3514/*************************************************************************
3515 * UWB subdriver
3516 */
3517
3518enum {
3519 /* ACPI GUWB/SUWB bits */
3520 TP_ACPI_UWB_HWPRESENT = 0x01, /* UWB hw available */
3521 TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */
3522};
3523
3524static struct rfkill *tpacpi_uwb_rfkill;
3525
3526static int uwb_get_radiosw(void)
3527{
3528 int status;
3529
3530 if (!tp_features.uwb)
3531 return -ENODEV;
3532
3533 /* WLSW overrides UWB in firmware/hardware, reflect that */
3534 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status)
3535 return RFKILL_STATE_HARD_BLOCKED;
3536
3537#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3538 if (dbg_uwbemul)
3539 return (tpacpi_uwb_emulstate) ?
3540 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
3541#endif
3542
3543 if (!acpi_evalf(hkey_handle, &status, "GUWB", "d"))
3544 return -EIO;
3545
3546 return ((status & TP_ACPI_UWB_RADIOSSW) != 0) ?
3547 RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED;
3548}
3549
3550static void uwb_update_rfk(void)
3551{
3552 int status;
3553
3554 if (!tpacpi_uwb_rfkill)
3555 return;
3556
3557 status = uwb_get_radiosw();
3558 if (status < 0)
3559 return;
3560 rfkill_force_state(tpacpi_uwb_rfkill, status);
3561}
3562
3563static int uwb_set_radiosw(int radio_on, int update_rfk)
3564{
3565 int status;
3566
3567 if (!tp_features.uwb)
3568 return -ENODEV;
3569
3570 /* WLSW overrides UWB in firmware/hardware, but there is no
3571 * reason to risk weird behaviour. */
3572 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&status) && !status
3573 && radio_on)
3574 return -EPERM;
3575
3576#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3577 if (dbg_uwbemul) {
3578 tpacpi_uwb_emulstate = !!radio_on;
3579 if (update_rfk)
3580 uwb_update_rfk();
3581 return 0;
3582 }
3583#endif
3584
3585 status = (radio_on) ? TP_ACPI_UWB_RADIOSSW : 0;
3586 if (!acpi_evalf(hkey_handle, NULL, "SUWB", "vd", status))
3587 return -EIO;
3588
3589 if (update_rfk)
3590 uwb_update_rfk();
3591
3592 return 0;
3593}
3594
3595/* --------------------------------------------------------------------- */
3596
3597static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state)
3598{
3599 int uwbs = uwb_get_radiosw();
3600
3601 if (uwbs < 0)
3602 return uwbs;
3603
3604 *state = uwbs;
3605 return 0;
3606}
3607
3608static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state)
3609{
3610 return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3611}
3612
3613static void uwb_exit(void)
3614{
3615 if (tpacpi_uwb_rfkill)
3616 rfkill_unregister(tpacpi_uwb_rfkill);
3617}
3618
3619static int __init uwb_init(struct ibm_init_struct *iibm)
3620{
3621 int res;
3622 int status = 0;
3623
3624 vdbg_printk(TPACPI_DBG_INIT, "initializing uwb subdriver\n");
3625
3626 TPACPI_ACPIHANDLE_INIT(hkey);
3627
3628 tp_features.uwb = hkey_handle &&
3629 acpi_evalf(hkey_handle, &status, "GUWB", "qd");
3630
3631 vdbg_printk(TPACPI_DBG_INIT, "uwb is %s, status 0x%02x\n",
3632 str_supported(tp_features.uwb),
3633 status);
3634
3635#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3636 if (dbg_uwbemul) {
3637 tp_features.uwb = 1;
3638 printk(TPACPI_INFO
3639 "uwb switch emulation enabled\n");
3640 } else
3641#endif
3642 if (tp_features.uwb &&
3643 !(status & TP_ACPI_UWB_HWPRESENT)) {
3644 /* no uwb hardware present in system */
3645 tp_features.uwb = 0;
3646 dbg_printk(TPACPI_DBG_INIT,
3647 "uwb hardware not installed\n");
3648 }
3649
3650 if (!tp_features.uwb)
3651 return 1;
3652
3653 res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID,
3654 &tpacpi_uwb_rfkill,
3655 RFKILL_TYPE_UWB,
3656 "tpacpi_uwb_sw",
3657 false,
3658 tpacpi_uwb_rfk_set,
3659 tpacpi_uwb_rfk_get);
3660
3661 return res;
3662}
3663
3664static struct ibm_struct uwb_driver_data = {
3665 .name = "uwb",
3666 .exit = uwb_exit,
3667 .flags.experimental = 1,
3099}; 3668};
3100 3669
3101/************************************************************************* 3670/*************************************************************************
@@ -3724,7 +4293,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event)
3724 } 4293 }
3725 acpi_bus_generate_proc_event(ibm->acpi->device, event, data); 4294 acpi_bus_generate_proc_event(ibm->acpi->device, event, data);
3726 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, 4295 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
3727 ibm->acpi->device->dev.bus_id, 4296 dev_name(&ibm->acpi->device->dev),
3728 event, data); 4297 event, data);
3729} 4298}
3730 4299
@@ -3826,7 +4395,7 @@ static void bay_notify(struct ibm_struct *ibm, u32 event)
3826{ 4395{
3827 acpi_bus_generate_proc_event(ibm->acpi->device, event, 0); 4396 acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);
3828 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, 4397 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
3829 ibm->acpi->device->dev.bus_id, 4398 dev_name(&ibm->acpi->device->dev),
3830 event, 0); 4399 event, 0);
3831} 4400}
3832 4401
@@ -4850,7 +5419,7 @@ static int brightness_set(int value)
4850 value < 0) 5419 value < 0)
4851 return -EINVAL; 5420 return -EINVAL;
4852 5421
4853 res = mutex_lock_interruptible(&brightness_mutex); 5422 res = mutex_lock_killable(&brightness_mutex);
4854 if (res < 0) 5423 if (res < 0)
4855 return res; 5424 return res;
4856 5425
@@ -5334,6 +5903,60 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */
5334 ); /* all others */ 5903 ); /* all others */
5335 5904
5336/* 5905/*
5906 * Unitialized HFSP quirk: ACPI DSDT and EC fail to initialize the
5907 * HFSP register at boot, so it contains 0x07 but the Thinkpad could
5908 * be in auto mode (0x80).
5909 *
5910 * This is corrected by any write to HFSP either by the driver, or
5911 * by the firmware.
5912 *
5913 * We assume 0x07 really means auto mode while this quirk is active,
5914 * as this is far more likely than the ThinkPad being in level 7,
5915 * which is only used by the firmware during thermal emergencies.
5916 */
5917
5918static void fan_quirk1_detect(void)
5919{
5920 /* In some ThinkPads, neither the EC nor the ACPI
5921 * DSDT initialize the HFSP register, and it ends up
5922 * being initially set to 0x07 when it *could* be
5923 * either 0x07 or 0x80.
5924 *
5925 * Enable for TP-1Y (T43), TP-78 (R51e),
5926 * TP-76 (R52), TP-70 (T43, R52), which are known
5927 * to be buggy. */
5928 if (fan_control_initial_status == 0x07) {
5929 switch (thinkpad_id.ec_model) {
5930 case 0x5931: /* TP-1Y */
5931 case 0x3837: /* TP-78 */
5932 case 0x3637: /* TP-76 */
5933 case 0x3037: /* TP-70 */
5934 printk(TPACPI_NOTICE
5935 "fan_init: initial fan status is unknown, "
5936 "assuming it is in auto mode\n");
5937 tp_features.fan_ctrl_status_undef = 1;
5938 ;;
5939 }
5940 }
5941}
5942
5943static void fan_quirk1_handle(u8 *fan_status)
5944{
5945 if (unlikely(tp_features.fan_ctrl_status_undef)) {
5946 if (*fan_status != fan_control_initial_status) {
5947 /* something changed the HFSP regisnter since
5948 * driver init time, so it is not undefined
5949 * anymore */
5950 tp_features.fan_ctrl_status_undef = 0;
5951 } else {
5952 /* Return most likely status. In fact, it
5953 * might be the only possible status */
5954 *fan_status = TP_EC_FAN_AUTO;
5955 }
5956 }
5957}
5958
5959/*
5337 * Call with fan_mutex held 5960 * Call with fan_mutex held
5338 */ 5961 */
5339static void fan_update_desired_level(u8 status) 5962static void fan_update_desired_level(u8 status)
@@ -5371,8 +5994,10 @@ static int fan_get_status(u8 *status)
5371 if (unlikely(!acpi_ec_read(fan_status_offset, &s))) 5994 if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
5372 return -EIO; 5995 return -EIO;
5373 5996
5374 if (likely(status)) 5997 if (likely(status)) {
5375 *status = s; 5998 *status = s;
5999 fan_quirk1_handle(status);
6000 }
5376 6001
5377 break; 6002 break;
5378 6003
@@ -5388,7 +6013,7 @@ static int fan_get_status_safe(u8 *status)
5388 int rc; 6013 int rc;
5389 u8 s; 6014 u8 s;
5390 6015
5391 if (mutex_lock_interruptible(&fan_mutex)) 6016 if (mutex_lock_killable(&fan_mutex))
5392 return -ERESTARTSYS; 6017 return -ERESTARTSYS;
5393 rc = fan_get_status(&s); 6018 rc = fan_get_status(&s);
5394 if (!rc) 6019 if (!rc)
@@ -5471,7 +6096,7 @@ static int fan_set_level_safe(int level)
5471 if (!fan_control_allowed) 6096 if (!fan_control_allowed)
5472 return -EPERM; 6097 return -EPERM;
5473 6098
5474 if (mutex_lock_interruptible(&fan_mutex)) 6099 if (mutex_lock_killable(&fan_mutex))
5475 return -ERESTARTSYS; 6100 return -ERESTARTSYS;
5476 6101
5477 if (level == TPACPI_FAN_LAST_LEVEL) 6102 if (level == TPACPI_FAN_LAST_LEVEL)
@@ -5493,7 +6118,7 @@ static int fan_set_enable(void)
5493 if (!fan_control_allowed) 6118 if (!fan_control_allowed)
5494 return -EPERM; 6119 return -EPERM;
5495 6120
5496 if (mutex_lock_interruptible(&fan_mutex)) 6121 if (mutex_lock_killable(&fan_mutex))
5497 return -ERESTARTSYS; 6122 return -ERESTARTSYS;
5498 6123
5499 switch (fan_control_access_mode) { 6124 switch (fan_control_access_mode) {
@@ -5548,7 +6173,7 @@ static int fan_set_disable(void)
5548 if (!fan_control_allowed) 6173 if (!fan_control_allowed)
5549 return -EPERM; 6174 return -EPERM;
5550 6175
5551 if (mutex_lock_interruptible(&fan_mutex)) 6176 if (mutex_lock_killable(&fan_mutex))
5552 return -ERESTARTSYS; 6177 return -ERESTARTSYS;
5553 6178
5554 rc = 0; 6179 rc = 0;
@@ -5586,7 +6211,7 @@ static int fan_set_speed(int speed)
5586 if (!fan_control_allowed) 6211 if (!fan_control_allowed)
5587 return -EPERM; 6212 return -EPERM;
5588 6213
5589 if (mutex_lock_interruptible(&fan_mutex)) 6214 if (mutex_lock_killable(&fan_mutex))
5590 return -ERESTARTSYS; 6215 return -ERESTARTSYS;
5591 6216
5592 rc = 0; 6217 rc = 0;
@@ -5682,16 +6307,6 @@ static ssize_t fan_pwm1_enable_show(struct device *dev,
5682 if (res) 6307 if (res)
5683 return res; 6308 return res;
5684 6309
5685 if (unlikely(tp_features.fan_ctrl_status_undef)) {
5686 if (status != fan_control_initial_status) {
5687 tp_features.fan_ctrl_status_undef = 0;
5688 } else {
5689 /* Return most likely status. In fact, it
5690 * might be the only possible status */
5691 status = TP_EC_FAN_AUTO;
5692 }
5693 }
5694
5695 if (status & TP_EC_FAN_FULLSPEED) { 6310 if (status & TP_EC_FAN_FULLSPEED) {
5696 mode = 0; 6311 mode = 0;
5697 } else if (status & TP_EC_FAN_AUTO) { 6312 } else if (status & TP_EC_FAN_AUTO) {
@@ -5756,14 +6371,6 @@ static ssize_t fan_pwm1_show(struct device *dev,
5756 if (res) 6371 if (res)
5757 return res; 6372 return res;
5758 6373
5759 if (unlikely(tp_features.fan_ctrl_status_undef)) {
5760 if (status != fan_control_initial_status) {
5761 tp_features.fan_ctrl_status_undef = 0;
5762 } else {
5763 status = TP_EC_FAN_AUTO;
5764 }
5765 }
5766
5767 if ((status & 6374 if ((status &
5768 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0) 6375 (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0)
5769 status = fan_control_desired_level; 6376 status = fan_control_desired_level;
@@ -5788,7 +6395,7 @@ static ssize_t fan_pwm1_store(struct device *dev,
5788 /* scale down from 0-255 to 0-7 */ 6395 /* scale down from 0-255 to 0-7 */
5789 newlevel = (s >> 5) & 0x07; 6396 newlevel = (s >> 5) & 0x07;
5790 6397
5791 if (mutex_lock_interruptible(&fan_mutex)) 6398 if (mutex_lock_killable(&fan_mutex))
5792 return -ERESTARTSYS; 6399 return -ERESTARTSYS;
5793 6400
5794 rc = fan_get_status(&status); 6401 rc = fan_get_status(&status);
@@ -5895,29 +6502,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
5895 if (likely(acpi_ec_read(fan_status_offset, 6502 if (likely(acpi_ec_read(fan_status_offset,
5896 &fan_control_initial_status))) { 6503 &fan_control_initial_status))) {
5897 fan_status_access_mode = TPACPI_FAN_RD_TPEC; 6504 fan_status_access_mode = TPACPI_FAN_RD_TPEC;
5898 6505 fan_quirk1_detect();
5899 /* In some ThinkPads, neither the EC nor the ACPI
5900 * DSDT initialize the fan status, and it ends up
5901 * being set to 0x07 when it *could* be either
5902 * 0x07 or 0x80.
5903 *
5904 * Enable for TP-1Y (T43), TP-78 (R51e),
5905 * TP-76 (R52), TP-70 (T43, R52), which are known
5906 * to be buggy. */
5907 if (fan_control_initial_status == 0x07) {
5908 switch (thinkpad_id.ec_model) {
5909 case 0x5931: /* TP-1Y */
5910 case 0x3837: /* TP-78 */
5911 case 0x3637: /* TP-76 */
5912 case 0x3037: /* TP-70 */
5913 printk(TPACPI_NOTICE
5914 "fan_init: initial fan status "
5915 "is unknown, assuming it is "
5916 "in auto mode\n");
5917 tp_features.fan_ctrl_status_undef = 1;
5918 ;;
5919 }
5920 }
5921 } else { 6506 } else {
5922 printk(TPACPI_ERR 6507 printk(TPACPI_ERR
5923 "ThinkPad ACPI EC access misbehaving, " 6508 "ThinkPad ACPI EC access misbehaving, "
@@ -6106,15 +6691,6 @@ static int fan_read(char *p)
6106 if (rc < 0) 6691 if (rc < 0)
6107 return rc; 6692 return rc;
6108 6693
6109 if (unlikely(tp_features.fan_ctrl_status_undef)) {
6110 if (status != fan_control_initial_status)
6111 tp_features.fan_ctrl_status_undef = 0;
6112 else
6113 /* Return most likely status. In fact, it
6114 * might be the only possible status */
6115 status = TP_EC_FAN_AUTO;
6116 }
6117
6118 len += sprintf(p + len, "status:\t\t%s\n", 6694 len += sprintf(p + len, "status:\t\t%s\n",
6119 (status != 0) ? "enabled" : "disabled"); 6695 (status != 0) ? "enabled" : "disabled");
6120 6696
@@ -6563,6 +7139,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
6563 .init = wan_init, 7139 .init = wan_init,
6564 .data = &wan_driver_data, 7140 .data = &wan_driver_data,
6565 }, 7141 },
7142 {
7143 .init = uwb_init,
7144 .data = &uwb_driver_data,
7145 },
6566#ifdef CONFIG_THINKPAD_ACPI_VIDEO 7146#ifdef CONFIG_THINKPAD_ACPI_VIDEO
6567 { 7147 {
6568 .init = video_init, 7148 .init = video_init,
@@ -6701,6 +7281,32 @@ TPACPI_PARAM(brightness);
6701TPACPI_PARAM(volume); 7281TPACPI_PARAM(volume);
6702TPACPI_PARAM(fan); 7282TPACPI_PARAM(fan);
6703 7283
7284#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
7285module_param(dbg_wlswemul, uint, 0);
7286MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
7287module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
7288MODULE_PARM_DESC(wlsw_state,
7289 "Initial state of the emulated WLSW switch");
7290
7291module_param(dbg_bluetoothemul, uint, 0);
7292MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
7293module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
7294MODULE_PARM_DESC(bluetooth_state,
7295 "Initial state of the emulated bluetooth switch");
7296
7297module_param(dbg_wwanemul, uint, 0);
7298MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
7299module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
7300MODULE_PARM_DESC(wwan_state,
7301 "Initial state of the emulated WWAN switch");
7302
7303module_param(dbg_uwbemul, uint, 0);
7304MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
7305module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
7306MODULE_PARM_DESC(uwb_state,
7307 "Initial state of the emulated UWB switch");
7308#endif
7309
6704static void thinkpad_acpi_module_exit(void) 7310static void thinkpad_acpi_module_exit(void)
6705{ 7311{
6706 struct ibm_struct *ibm, *itmp; 7312 struct ibm_struct *ibm, *itmp;