aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/Kconfig23
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/dell-laptop.c436
-rw-r--r--drivers/platform/x86/eeepc-laptop.c4
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c910
5 files changed, 1220 insertions, 154 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e65448e99b48..1a266d4ab5f1 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -54,6 +54,18 @@ config ASUS_LAPTOP
54 54
55 If you have an ACPI-compatible ASUS laptop, say Y or M here. 55 If you have an ACPI-compatible ASUS laptop, say Y or M here.
56 56
57config DELL_LAPTOP
58 tristate "Dell Laptop Extras (EXPERIMENTAL)"
59 depends on X86
60 depends on DCDBAS
61 depends on EXPERIMENTAL
62 depends on BACKLIGHT_CLASS_DEVICE
63 depends on RFKILL
64 default n
65 ---help---
66 This driver adds support for rfkill and backlight control to Dell
67 laptops.
68
57config FUJITSU_LAPTOP 69config FUJITSU_LAPTOP
58 tristate "Fujitsu Laptop Extras" 70 tristate "Fujitsu Laptop Extras"
59 depends on ACPI 71 depends on ACPI
@@ -192,6 +204,17 @@ config THINKPAD_ACPI
192 204
193 If you have an IBM or Lenovo ThinkPad laptop, say Y or M here. 205 If you have an IBM or Lenovo ThinkPad laptop, say Y or M here.
194 206
207config THINKPAD_ACPI_DEBUGFACILITIES
208 bool "Maintainer debug facilities"
209 depends on THINKPAD_ACPI
210 default n
211 ---help---
212 Enables extra stuff in the thinkpad-acpi which is completely useless
213 for normal use. Read the driver source to find out what it does.
214
215 Say N here, unless you were told by a kernel maintainer to do
216 otherwise.
217
195config THINKPAD_ACPI_DEBUG 218config THINKPAD_ACPI_DEBUG
196 bool "Verbose debug mode" 219 bool "Verbose debug mode"
197 depends on THINKPAD_ACPI 220 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/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..9d93cb971e59 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -90,7 +90,7 @@ enum {
90}; 90};
91 91
92static const char *cm_getv[] = { 92static const char *cm_getv[] = {
93 "WLDG", NULL, NULL, NULL, 93 "WLDG", "BTHG", NULL, NULL,
94 "CAMG", NULL, NULL, NULL, 94 "CAMG", NULL, NULL, NULL,
95 NULL, "PBLG", NULL, NULL, 95 NULL, "PBLG", NULL, NULL,
96 "CFVG", NULL, NULL, NULL, 96 "CFVG", NULL, NULL, NULL,
@@ -99,7 +99,7 @@ static const char *cm_getv[] = {
99}; 99};
100 100
101static const char *cm_setv[] = { 101static const char *cm_setv[] = {
102 "WLDS", NULL, NULL, NULL, 102 "WLDS", "BTHS", NULL, NULL,
103 "CAMS", NULL, NULL, NULL, 103 "CAMS", NULL, NULL, NULL,
104 "SDSP", "PBLS", "HDPS", NULL, 104 "SDSP", "PBLS", "HDPS", NULL,
105 "CFVS", NULL, NULL, NULL, 105 "CFVS", NULL, NULL, NULL,
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;