aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig35
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c35
-rw-r--r--drivers/platform/x86/dell-wmi.c210
-rw-r--r--drivers/platform/x86/hp-wmi.c25
-rw-r--r--drivers/platform/x86/intel_menlow.c29
-rw-r--r--drivers/platform/x86/panasonic-laptop.c9
-rw-r--r--drivers/platform/x86/sony-laptop.c531
-rw-r--r--drivers/platform/x86/tc1100-wmi.c7
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c735
10 files changed, 1251 insertions, 366 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 3608081bc3e..284ebaca6e4 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -67,6 +67,16 @@ config DELL_LAPTOP
67 This driver adds support for rfkill and backlight control to Dell 67 This driver adds support for rfkill and backlight control to Dell
68 laptops. 68 laptops.
69 69
70config DELL_WMI
71 tristate "Dell WMI extras"
72 depends on ACPI_WMI
73 depends on INPUT
74 ---help---
75 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
76
77 To compile this driver as a module, choose M here: the module will
78 be called dell-wmi.
79
70config FUJITSU_LAPTOP 80config FUJITSU_LAPTOP
71 tristate "Fujitsu Laptop Extras" 81 tristate "Fujitsu Laptop Extras"
72 depends on ACPI 82 depends on ACPI
@@ -165,6 +175,7 @@ config SONY_LAPTOP
165 depends on ACPI 175 depends on ACPI
166 select BACKLIGHT_CLASS_DEVICE 176 select BACKLIGHT_CLASS_DEVICE
167 depends on INPUT 177 depends on INPUT
178 depends on RFKILL
168 ---help--- 179 ---help---
169 This mini-driver drives the SNC and SPIC devices present in the ACPI 180 This mini-driver drives the SNC and SPIC devices present in the ACPI
170 BIOS of the Sony Vaio laptops. 181 BIOS of the Sony Vaio laptops.
@@ -226,6 +237,30 @@ config THINKPAD_ACPI_DEBUG
226 237
227 If you are not sure, say N here. 238 If you are not sure, say N here.
228 239
240config THINKPAD_ACPI_UNSAFE_LEDS
241 bool "Allow control of important LEDs (unsafe)"
242 depends on THINKPAD_ACPI
243 default n
244 ---help---
245 Overriding LED state on ThinkPads can mask important
246 firmware alerts (like critical battery condition), or misled
247 the user into damaging the hardware (undocking or ejecting
248 the bay while buses are still active), etc.
249
250 LED control on the ThinkPad is write-only (with very few
251 exceptions on very ancient models), which makes it
252 impossible to know beforehand if important information will
253 be lost when one changes LED state.
254
255 Users that know what they are doing can enable this option
256 and the driver will allow control of every LED, including
257 the ones on the dock stations.
258
259 Never enable this option on a distribution kernel.
260
261 Say N here, unless you are building a kernel for your own
262 use, and need to control the important firmware LEDs.
263
229config THINKPAD_ACPI_DOCK 264config THINKPAD_ACPI_DOCK
230 bool "Legacy Docking Station Support" 265 bool "Legacy Docking Station Support"
231 depends on THINKPAD_ACPI 266 depends on THINKPAD_ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index e29065120be..e40c7bd1b87 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -7,6 +7,7 @@ obj-$(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_DELL_LAPTOP) += dell-laptop.o
10obj-$(CONFIG_DELL_WMI) += dell-wmi.o
10obj-$(CONFIG_ACER_WMI) += acer-wmi.o 11obj-$(CONFIG_ACER_WMI) += acer-wmi.o
11obj-$(CONFIG_HP_WMI) += hp-wmi.o 12obj-$(CONFIG_HP_WMI) += hp-wmi.o
12obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o 13obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index a6a42e8c060..0f6e43bf4fc 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Acer WMI Laptop Extras 2 * Acer WMI Laptop Extras
3 * 3 *
4 * Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk> 4 * Copyright (C) 2007-2009 Carlos Corbacho <carlos@strangeworlds.co.uk>
5 * 5 *
6 * Based on acer_acpi: 6 * Based on acer_acpi:
7 * Copyright (C) 2005-2007 E.M. Smith 7 * Copyright (C) 2005-2007 E.M. Smith
@@ -225,6 +225,25 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
225 .wireless = 2, 225 .wireless = 2,
226}; 226};
227 227
228/* The Aspire One has a dummy ACPI-WMI interface - disable it */
229static struct dmi_system_id __devinitdata acer_blacklist[] = {
230 {
231 .ident = "Acer Aspire One (SSD)",
232 .matches = {
233 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
234 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),
235 },
236 },
237 {
238 .ident = "Acer Aspire One (HDD)",
239 .matches = {
240 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
241 DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
242 },
243 },
244 {}
245};
246
228static struct dmi_system_id acer_quirks[] = { 247static struct dmi_system_id acer_quirks[] = {
229 { 248 {
230 .callback = dmi_matched, 249 .callback = dmi_matched,
@@ -1117,11 +1136,17 @@ static int __devinit acer_platform_probe(struct platform_device *device)
1117 } 1136 }
1118 1137
1119 err = acer_rfkill_init(&device->dev); 1138 err = acer_rfkill_init(&device->dev);
1139 if (err)
1140 goto error_rfkill;
1120 1141
1121 return err; 1142 return err;
1122 1143
1144error_rfkill:
1145 if (has_cap(ACER_CAP_BRIGHTNESS))
1146 acer_backlight_exit();
1123error_brightness: 1147error_brightness:
1124 acer_led_exit(); 1148 if (has_cap(ACER_CAP_MAILLED))
1149 acer_led_exit();
1125error_mailled: 1150error_mailled:
1126 return err; 1151 return err;
1127} 1152}
@@ -1254,6 +1279,12 @@ static int __init acer_wmi_init(void)
1254 1279
1255 printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n"); 1280 printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n");
1256 1281
1282 if (dmi_check_system(acer_blacklist)) {
1283 printk(ACER_INFO "Blacklisted hardware detected - "
1284 "not loading\n");
1285 return -ENODEV;
1286 }
1287
1257 find_quirks(); 1288 find_quirks();
1258 1289
1259 /* 1290 /*
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
new file mode 100644
index 00000000000..2fab9416214
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi.c
@@ -0,0 +1,210 @@
1/*
2 * Dell WMI hotkeys
3 *
4 * Copyright (C) 2008 Red Hat <mjg@redhat.com>
5 *
6 * Portions based on wistron_btns.c:
7 * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
8 * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
9 * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/types.h>
30#include <linux/input.h>
31#include <acpi/acpi_drivers.h>
32#include <linux/acpi.h>
33#include <linux/string.h>
34
35MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
36MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
37MODULE_LICENSE("GPL");
38
39#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
40
41MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
42
43struct key_entry {
44 char type; /* See KE_* below */
45 u16 code;
46 u16 keycode;
47};
48
49enum { KE_KEY, KE_SW, KE_END };
50
51static struct key_entry dell_wmi_keymap[] = {
52 {KE_KEY, 0xe045, KEY_PROG1},
53 {KE_END, 0}
54};
55
56static struct input_dev *dell_wmi_input_dev;
57
58static struct key_entry *dell_wmi_get_entry_by_scancode(int code)
59{
60 struct key_entry *key;
61
62 for (key = dell_wmi_keymap; key->type != KE_END; key++)
63 if (code == key->code)
64 return key;
65
66 return NULL;
67}
68
69static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode)
70{
71 struct key_entry *key;
72
73 for (key = dell_wmi_keymap; key->type != KE_END; key++)
74 if (key->type == KE_KEY && keycode == key->keycode)
75 return key;
76
77 return NULL;
78}
79
80static int dell_wmi_getkeycode(struct input_dev *dev, int scancode,
81 int *keycode)
82{
83 struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
84
85 if (key && key->type == KE_KEY) {
86 *keycode = key->keycode;
87 return 0;
88 }
89
90 return -EINVAL;
91}
92
93static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
94{
95 struct key_entry *key;
96 int old_keycode;
97
98 if (keycode < 0 || keycode > KEY_MAX)
99 return -EINVAL;
100
101 key = dell_wmi_get_entry_by_scancode(scancode);
102 if (key && key->type == KE_KEY) {
103 old_keycode = key->keycode;
104 key->keycode = keycode;
105 set_bit(keycode, dev->keybit);
106 if (!dell_wmi_get_entry_by_keycode(old_keycode))
107 clear_bit(old_keycode, dev->keybit);
108 return 0;
109 }
110 return -EINVAL;
111}
112
113static void dell_wmi_notify(u32 value, void *context)
114{
115 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
116 static struct key_entry *key;
117 union acpi_object *obj;
118
119 wmi_get_event_data(value, &response);
120
121 obj = (union acpi_object *)response.pointer;
122
123 if (obj && obj->type == ACPI_TYPE_BUFFER) {
124 int *buffer = (int *)obj->buffer.pointer;
125 key = dell_wmi_get_entry_by_scancode(buffer[1]);
126 if (key) {
127 input_report_key(dell_wmi_input_dev, key->keycode, 1);
128 input_sync(dell_wmi_input_dev);
129 input_report_key(dell_wmi_input_dev, key->keycode, 0);
130 input_sync(dell_wmi_input_dev);
131 } else
132 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
133 buffer[1]);
134 }
135}
136
137static int __init dell_wmi_input_setup(void)
138{
139 struct key_entry *key;
140 int err;
141
142 dell_wmi_input_dev = input_allocate_device();
143
144 if (!dell_wmi_input_dev)
145 return -ENOMEM;
146
147 dell_wmi_input_dev->name = "Dell WMI hotkeys";
148 dell_wmi_input_dev->phys = "wmi/input0";
149 dell_wmi_input_dev->id.bustype = BUS_HOST;
150 dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode;
151 dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode;
152
153 for (key = dell_wmi_keymap; key->type != KE_END; key++) {
154 switch (key->type) {
155 case KE_KEY:
156 set_bit(EV_KEY, dell_wmi_input_dev->evbit);
157 set_bit(key->keycode, dell_wmi_input_dev->keybit);
158 break;
159 case KE_SW:
160 set_bit(EV_SW, dell_wmi_input_dev->evbit);
161 set_bit(key->keycode, dell_wmi_input_dev->swbit);
162 break;
163 }
164 }
165
166 err = input_register_device(dell_wmi_input_dev);
167
168 if (err) {
169 input_free_device(dell_wmi_input_dev);
170 return err;
171 }
172
173 return 0;
174}
175
176static int __init dell_wmi_init(void)
177{
178 int err;
179
180 if (wmi_has_guid(DELL_EVENT_GUID)) {
181 err = dell_wmi_input_setup();
182
183 if (err)
184 return err;
185
186 err = wmi_install_notify_handler(DELL_EVENT_GUID,
187 dell_wmi_notify, NULL);
188 if (err) {
189 input_unregister_device(dell_wmi_input_dev);
190 printk(KERN_ERR "dell-wmi: Unable to register"
191 " notify handler - %d\n", err);
192 return err;
193 }
194
195 } else
196 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
197
198 return 0;
199}
200
201static void __exit dell_wmi_exit(void)
202{
203 if (wmi_has_guid(DELL_EVENT_GUID)) {
204 wmi_remove_notify_handler(DELL_EVENT_GUID);
205 input_unregister_device(dell_wmi_input_dev);
206 }
207}
208
209module_init(dell_wmi_init);
210module_exit(dell_wmi_exit);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index f41135f2fb2..50d9019de2b 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -53,6 +53,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
53 53
54static int __init hp_wmi_bios_setup(struct platform_device *device); 54static int __init hp_wmi_bios_setup(struct platform_device *device);
55static int __exit hp_wmi_bios_remove(struct platform_device *device); 55static int __exit hp_wmi_bios_remove(struct platform_device *device);
56static int hp_wmi_resume_handler(struct platform_device *device);
56 57
57struct bios_args { 58struct bios_args {
58 u32 signature; 59 u32 signature;
@@ -101,6 +102,7 @@ static struct platform_driver hp_wmi_driver = {
101 }, 102 },
102 .probe = hp_wmi_bios_setup, 103 .probe = hp_wmi_bios_setup,
103 .remove = hp_wmi_bios_remove, 104 .remove = hp_wmi_bios_remove,
105 .resume = hp_wmi_resume_handler,
104}; 106};
105 107
106static int hp_wmi_perform_query(int query, int write, int value) 108static int hp_wmi_perform_query(int query, int write, int value)
@@ -487,6 +489,29 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
487 return 0; 489 return 0;
488} 490}
489 491
492static int hp_wmi_resume_handler(struct platform_device *device)
493{
494 struct key_entry *key;
495
496 /*
497 * Docking state may have changed while suspended, so trigger
498 * an input event for the current state. As this is a switch,
499 * the input layer will only actually pass it on if the state
500 * changed.
501 */
502 for (key = hp_wmi_keymap; key->type != KE_END; key++) {
503 switch (key->type) {
504 case KE_SW:
505 input_report_switch(hp_wmi_input_dev, key->keycode,
506 hp_wmi_dock_state());
507 input_sync(hp_wmi_input_dev);
508 break;
509 }
510 }
511
512 return 0;
513}
514
490static int __init hp_wmi_init(void) 515static int __init hp_wmi_init(void)
491{ 516{
492 int err; 517 int err;
diff --git a/drivers/platform/x86/intel_menlow.c b/drivers/platform/x86/intel_menlow.c
index 27b7662955b..29432a50be4 100644
--- a/drivers/platform/x86/intel_menlow.c
+++ b/drivers/platform/x86/intel_menlow.c
@@ -57,8 +57,8 @@ MODULE_LICENSE("GPL");
57 * In that case max_cstate would be n-1 57 * In that case max_cstate would be n-1
58 * GTHS returning '0' would mean that no bandwidth control states are supported 58 * GTHS returning '0' would mean that no bandwidth control states are supported
59 */ 59 */
60static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, 60static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev,
61 unsigned long *max_state) 61 unsigned long *max_state)
62{ 62{
63 struct acpi_device *device = cdev->devdata; 63 struct acpi_device *device = cdev->devdata;
64 acpi_handle handle = device->handle; 64 acpi_handle handle = device->handle;
@@ -83,22 +83,12 @@ static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev,
83 return 0; 83 return 0;
84} 84}
85 85
86static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev,
87 char *buf)
88{
89 unsigned long value;
90 if (memory_get_int_max_bandwidth(cdev, &value))
91 return -EINVAL;
92
93 return sprintf(buf, "%ld\n", value);
94}
95
96static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev, 86static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
97 char *buf) 87 unsigned long *value)
98{ 88{
99 struct acpi_device *device = cdev->devdata; 89 struct acpi_device *device = cdev->devdata;
100 acpi_handle handle = device->handle; 90 acpi_handle handle = device->handle;
101 unsigned long long value; 91 unsigned long long result;
102 struct acpi_object_list arg_list; 92 struct acpi_object_list arg_list;
103 union acpi_object arg; 93 union acpi_object arg;
104 acpi_status status = AE_OK; 94 acpi_status status = AE_OK;
@@ -108,15 +98,16 @@ static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev,
108 arg.type = ACPI_TYPE_INTEGER; 98 arg.type = ACPI_TYPE_INTEGER;
109 arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH; 99 arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH;
110 status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH, 100 status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH,
111 &arg_list, &value); 101 &arg_list, &result);
112 if (ACPI_FAILURE(status)) 102 if (ACPI_FAILURE(status))
113 return -EFAULT; 103 return -EFAULT;
114 104
115 return sprintf(buf, "%llu\n", value); 105 *value = result;
106 return 0;
116} 107}
117 108
118static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, 109static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
119 unsigned int state) 110 unsigned long state)
120{ 111{
121 struct acpi_device *device = cdev->devdata; 112 struct acpi_device *device = cdev->devdata;
122 acpi_handle handle = device->handle; 113 acpi_handle handle = device->handle;
@@ -126,7 +117,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
126 unsigned long long temp; 117 unsigned long long temp;
127 unsigned long max_state; 118 unsigned long max_state;
128 119
129 if (memory_get_int_max_bandwidth(cdev, &max_state)) 120 if (memory_get_max_bandwidth(cdev, &max_state))
130 return -EFAULT; 121 return -EFAULT;
131 122
132 if (state > max_state) 123 if (state > max_state)
@@ -142,7 +133,7 @@ static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev,
142 &temp); 133 &temp);
143 134
144 printk(KERN_INFO 135 printk(KERN_INFO
145 "Bandwidth value was %d: status is %d\n", state, status); 136 "Bandwidth value was %ld: status is %d\n", state, status);
146 if (ACPI_FAILURE(status)) 137 if (ACPI_FAILURE(status))
147 return -EFAULT; 138 return -EFAULT;
148 139
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index c47a44dcb70..a5ce4bc202e 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -184,6 +184,7 @@ static const struct acpi_device_id pcc_device_ids[] = {
184 { "MAT0019", 0}, 184 { "MAT0019", 0},
185 { "", 0}, 185 { "", 0},
186}; 186};
187MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
187 188
188static struct acpi_driver acpi_pcc_driver = { 189static struct acpi_driver acpi_pcc_driver = {
189 .name = ACPI_PCC_DRIVER_NAME, 190 .name = ACPI_PCC_DRIVER_NAME,
@@ -366,7 +367,7 @@ static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr,
366 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 367 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
367 return -EIO; 368 return -EIO;
368 369
369 return sprintf(buf, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]); 370 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
370} 371}
371 372
372static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr, 373static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
@@ -378,7 +379,7 @@ static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
378 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 379 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
379 return -EIO; 380 return -EIO;
380 381
381 return sprintf(buf, "%u\n", pcc->sinf[SINF_LCD_TYPE]); 382 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
382} 383}
383 384
384static ssize_t show_mute(struct device *dev, struct device_attribute *attr, 385static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
@@ -390,7 +391,7 @@ static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
390 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 391 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
391 return -EIO; 392 return -EIO;
392 393
393 return sprintf(buf, "%u\n", pcc->sinf[SINF_MUTE]); 394 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]);
394} 395}
395 396
396static ssize_t show_sticky(struct device *dev, struct device_attribute *attr, 397static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
@@ -402,7 +403,7 @@ static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
402 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) 403 if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
403 return -EIO; 404 return -EIO;
404 405
405 return sprintf(buf, "%u\n", pcc->sinf[SINF_STICKY_KEY]); 406 return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]);
406} 407}
407 408
408static ssize_t set_sticky(struct device *dev, struct device_attribute *attr, 409static ssize_t set_sticky(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index bc8996c849a..a90ec5cb2f2 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -2,7 +2,7 @@
2 * ACPI Sony Notebook Control Driver (SNC and SPIC) 2 * ACPI Sony Notebook Control Driver (SNC and SPIC)
3 * 3 *
4 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net> 4 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
5 * Copyright (C) 2007 Mattia Dongili <malattia@linux.it> 5 * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
6 * 6 *
7 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c 7 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
8 * which are copyrighted by their respective authors. 8 * which are copyrighted by their respective authors.
@@ -46,7 +46,6 @@
46#include <linux/module.h> 46#include <linux/module.h>
47#include <linux/moduleparam.h> 47#include <linux/moduleparam.h>
48#include <linux/init.h> 48#include <linux/init.h>
49#include <linux/smp_lock.h>
50#include <linux/types.h> 49#include <linux/types.h>
51#include <linux/backlight.h> 50#include <linux/backlight.h>
52#include <linux/platform_device.h> 51#include <linux/platform_device.h>
@@ -64,6 +63,7 @@
64#include <asm/uaccess.h> 63#include <asm/uaccess.h>
65#include <linux/sonypi.h> 64#include <linux/sonypi.h>
66#include <linux/sony-laptop.h> 65#include <linux/sony-laptop.h>
66#include <linux/rfkill.h>
67#ifdef CONFIG_SONYPI_COMPAT 67#ifdef CONFIG_SONYPI_COMPAT
68#include <linux/poll.h> 68#include <linux/poll.h>
69#include <linux/miscdevice.h> 69#include <linux/miscdevice.h>
@@ -123,6 +123,18 @@ MODULE_PARM_DESC(minor,
123 "default is -1 (automatic)"); 123 "default is -1 (automatic)");
124#endif 124#endif
125 125
126enum sony_nc_rfkill {
127 SONY_WIFI,
128 SONY_BLUETOOTH,
129 SONY_WWAN,
130 SONY_WIMAX,
131 SONY_RFKILL_MAX,
132};
133
134static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX];
135static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900};
136static void sony_nc_rfkill_update(void);
137
126/*********** Input Devices ***********/ 138/*********** Input Devices ***********/
127 139
128#define SONY_LAPTOP_BUF_SIZE 128 140#define SONY_LAPTOP_BUF_SIZE 128
@@ -134,6 +146,7 @@ struct sony_laptop_input_s {
134 spinlock_t fifo_lock; 146 spinlock_t fifo_lock;
135 struct workqueue_struct *wq; 147 struct workqueue_struct *wq;
136}; 148};
149
137static struct sony_laptop_input_s sony_laptop_input = { 150static struct sony_laptop_input_s sony_laptop_input = {
138 .users = ATOMIC_INIT(0), 151 .users = ATOMIC_INIT(0),
139}; 152};
@@ -211,6 +224,14 @@ static int sony_laptop_input_index[] = {
211 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ 224 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */
212 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ 225 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */
213 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 226 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */
227 51, /* 64 SONYPI_EVENT_CD_EJECT_PRESSED */
228 52, /* 65 SONYPI_EVENT_MODEKEY_PRESSED */
229 53, /* 66 SONYPI_EVENT_PKEY_P4 */
230 54, /* 67 SONYPI_EVENT_PKEY_P5 */
231 55, /* 68 SONYPI_EVENT_SETTINGKEY_PRESSED */
232 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */
233 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */
234 -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */
214}; 235};
215 236
216static int sony_laptop_input_keycode_map[] = { 237static int sony_laptop_input_keycode_map[] = {
@@ -264,7 +285,14 @@ static int sony_laptop_input_keycode_map[] = {
264 KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ 285 KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */
265 KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ 286 KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */
266 KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ 287 KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */
267 KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ 288 KEY_ZOOMOUT, /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
289 KEY_EJECTCD, /* 51 SONYPI_EVENT_CD_EJECT_PRESSED */
290 KEY_F13, /* 52 SONYPI_EVENT_MODEKEY_PRESSED */
291 KEY_PROG4, /* 53 SONYPI_EVENT_PKEY_P4 */
292 KEY_F14, /* 54 SONYPI_EVENT_PKEY_P5 */
293 KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */
294 KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */
295 KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */
268}; 296};
269 297
270/* release buttons after a short delay if pressed */ 298/* release buttons after a short delay if pressed */
@@ -369,7 +397,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device)
369 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop"); 397 sony_laptop_input.wq = create_singlethread_workqueue("sony-laptop");
370 if (!sony_laptop_input.wq) { 398 if (!sony_laptop_input.wq) {
371 printk(KERN_ERR DRV_PFX 399 printk(KERN_ERR DRV_PFX
372 "Unabe to create workqueue.\n"); 400 "Unable to create workqueue.\n");
373 error = -ENXIO; 401 error = -ENXIO;
374 goto err_free_kfifo; 402 goto err_free_kfifo;
375 } 403 }
@@ -689,6 +717,31 @@ static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
689 return -1; 717 return -1;
690} 718}
691 719
720static int sony_find_snc_handle(int handle)
721{
722 int i;
723 int result;
724
725 for (i = 0x20; i < 0x30; i++) {
726 acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
727 if (result == handle)
728 return i-0x20;
729 }
730
731 return -1;
732}
733
734static int sony_call_snc_handle(int handle, int argument, int *result)
735{
736 int offset = sony_find_snc_handle(handle);
737
738 if (offset < 0)
739 return -1;
740
741 return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
742 result);
743}
744
692/* 745/*
693 * sony_nc_values input/output validate functions 746 * sony_nc_values input/output validate functions
694 */ 747 */
@@ -809,87 +862,53 @@ struct sony_nc_event {
809 u8 event; 862 u8 event;
810}; 863};
811 864
812static struct sony_nc_event *sony_nc_events; 865static struct sony_nc_event sony_100_events[] = {
813 866 { 0x90, SONYPI_EVENT_PKEY_P1 },
814/* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence 867 { 0x10, SONYPI_EVENT_ANYBUTTON_RELEASED },
815 * for Fn keys 868 { 0x91, SONYPI_EVENT_PKEY_P2 },
816 */ 869 { 0x11, SONYPI_EVENT_ANYBUTTON_RELEASED },
817static int sony_nc_C_enable(const struct dmi_system_id *id)
818{
819 int result = 0;
820
821 printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident);
822
823 sony_nc_events = id->driver_data;
824
825 if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0
826 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0
827 || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0
828 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0
829 || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0
830 || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) {
831 printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some "
832 "functionalities may be missing\n");
833 return 1;
834 }
835 return 0;
836}
837
838static struct sony_nc_event sony_C_events[] = {
839 { 0x81, SONYPI_EVENT_FNKEY_F1 }, 870 { 0x81, SONYPI_EVENT_FNKEY_F1 },
840 { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, 871 { 0x01, SONYPI_EVENT_FNKEY_RELEASED },
872 { 0x82, SONYPI_EVENT_FNKEY_F2 },
873 { 0x02, SONYPI_EVENT_FNKEY_RELEASED },
874 { 0x83, SONYPI_EVENT_FNKEY_F3 },
875 { 0x03, SONYPI_EVENT_FNKEY_RELEASED },
876 { 0x84, SONYPI_EVENT_FNKEY_F4 },
877 { 0x04, SONYPI_EVENT_FNKEY_RELEASED },
841 { 0x85, SONYPI_EVENT_FNKEY_F5 }, 878 { 0x85, SONYPI_EVENT_FNKEY_F5 },
842 { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, 879 { 0x05, SONYPI_EVENT_FNKEY_RELEASED },
843 { 0x86, SONYPI_EVENT_FNKEY_F6 }, 880 { 0x86, SONYPI_EVENT_FNKEY_F6 },
844 { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, 881 { 0x06, SONYPI_EVENT_FNKEY_RELEASED },
845 { 0x87, SONYPI_EVENT_FNKEY_F7 }, 882 { 0x87, SONYPI_EVENT_FNKEY_F7 },
846 { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, 883 { 0x07, SONYPI_EVENT_FNKEY_RELEASED },
884 { 0x89, SONYPI_EVENT_FNKEY_F9 },
885 { 0x09, SONYPI_EVENT_FNKEY_RELEASED },
847 { 0x8A, SONYPI_EVENT_FNKEY_F10 }, 886 { 0x8A, SONYPI_EVENT_FNKEY_F10 },
848 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, 887 { 0x0A, SONYPI_EVENT_FNKEY_RELEASED },
849 { 0x8C, SONYPI_EVENT_FNKEY_F12 }, 888 { 0x8C, SONYPI_EVENT_FNKEY_F12 },
850 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, 889 { 0x0C, SONYPI_EVENT_FNKEY_RELEASED },
890 { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED },
891 { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED },
851 { 0, 0 }, 892 { 0, 0 },
852}; 893};
853 894
854/* SNC-only model map */ 895static struct sony_nc_event sony_127_events[] = {
855static const struct dmi_system_id sony_nc_ids[] = { 896 { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
856 { 897 { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
857 .ident = "Sony Vaio FE Series", 898 { 0x82, SONYPI_EVENT_PKEY_P1 },
858 .callback = sony_nc_C_enable, 899 { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
859 .driver_data = sony_C_events, 900 { 0x83, SONYPI_EVENT_PKEY_P2 },
860 .matches = { 901 { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
861 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 902 { 0x84, SONYPI_EVENT_PKEY_P3 },
862 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), 903 { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
863 }, 904 { 0x85, SONYPI_EVENT_PKEY_P4 },
864 }, 905 { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
865 { 906 { 0x86, SONYPI_EVENT_PKEY_P5 },
866 .ident = "Sony Vaio FZ Series", 907 { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
867 .callback = sony_nc_C_enable, 908 { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
868 .driver_data = sony_C_events, 909 { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
869 .matches = { 910 { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
870 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 911 { 0, 0 },
871 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"),
872 },
873 },
874 {
875 .ident = "Sony Vaio C Series",
876 .callback = sony_nc_C_enable,
877 .driver_data = sony_C_events,
878 .matches = {
879 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
880 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"),
881 },
882 },
883 {
884 .ident = "Sony Vaio N Series",
885 .callback = sony_nc_C_enable,
886 .driver_data = sony_C_events,
887 .matches = {
888 DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
889 DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"),
890 },
891 },
892 { }
893}; 912};
894 913
895/* 914/*
@@ -897,38 +916,59 @@ static const struct dmi_system_id sony_nc_ids[] = {
897 */ 916 */
898static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 917static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
899{ 918{
900 struct sony_nc_event *evmap;
901 u32 ev = event; 919 u32 ev = event;
902 int result;
903 920
904 if (ev == 0x92) { 921 if (ev >= 0x90) {
905 /* read the key pressed from EC.GECR 922 /* New-style event */
906 * A call to SN07 with 0x0202 will do it as well respecting 923 int result;
907 * the current protocol on different OSes 924 int key_handle = 0;
908 * 925 ev -= 0x90;
909 * Note: the path for GECR may be 926
910 * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) 927 if (sony_find_snc_handle(0x100) == ev)
911 * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) 928 key_handle = 0x100;
912 * 929 if (sony_find_snc_handle(0x127) == ev)
913 * TODO: we may want to do the same for the older GHKE -need 930 key_handle = 0x127;
914 * dmi list- so this snippet may become one more callback. 931
915 */ 932 if (key_handle) {
916 if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) 933 struct sony_nc_event *key_event;
917 dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); 934
918 else 935 if (sony_call_snc_handle(key_handle, 0x200, &result)) {
919 ev = result & 0xFF; 936 dprintk("sony_acpi_notify, unable to decode"
920 } 937 " event 0x%.2x 0x%.2x\n", key_handle,
938 ev);
939 /* restore the original event */
940 ev = event;
941 } else {
942 ev = result & 0xFF;
943
944 if (key_handle == 0x100)
945 key_event = sony_100_events;
946 else
947 key_event = sony_127_events;
948
949 for (; key_event->data; key_event++) {
950 if (key_event->data == ev) {
951 ev = key_event->event;
952 break;
953 }
954 }
921 955
922 if (sony_nc_events) 956 if (!key_event->data)
923 for (evmap = sony_nc_events; evmap->event; evmap++) { 957 printk(KERN_INFO DRV_PFX
924 if (evmap->data == ev) { 958 "Unknown event: 0x%x 0x%x\n",
925 ev = evmap->event; 959 key_handle,
926 break; 960 ev);
961 else
962 sony_laptop_report_input_event(ev);
927 } 963 }
964 } else if (sony_find_snc_handle(0x124) == ev) {
965 sony_nc_rfkill_update();
966 return;
928 } 967 }
968 } else
969 sony_laptop_report_input_event(ev);
929 970
930 dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); 971 dprintk("sony_acpi_notify, event: 0x%.2x\n", ev);
931 sony_laptop_report_input_event(ev);
932 acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev); 972 acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
933} 973}
934 974
@@ -953,9 +993,25 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
953/* 993/*
954 * ACPI device 994 * ACPI device
955 */ 995 */
996static int sony_nc_function_setup(struct acpi_device *device)
997{
998 int result;
999
1000 /* Enable all events */
1001 acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
1002
1003 /* Setup hotkeys */
1004 sony_call_snc_handle(0x0100, 0, &result);
1005 sony_call_snc_handle(0x0101, 0, &result);
1006 sony_call_snc_handle(0x0102, 0x100, &result);
1007
1008 return 0;
1009}
1010
956static int sony_nc_resume(struct acpi_device *device) 1011static int sony_nc_resume(struct acpi_device *device)
957{ 1012{
958 struct sony_nc_value *item; 1013 struct sony_nc_value *item;
1014 acpi_handle handle;
959 1015
960 for (item = sony_nc_values; item->name; item++) { 1016 for (item = sony_nc_values; item->name; item++) {
961 int ret; 1017 int ret;
@@ -970,13 +1026,188 @@ static int sony_nc_resume(struct acpi_device *device)
970 } 1026 }
971 } 1027 }
972 1028
1029 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1030 &handle))) {
1031 if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1032 dprintk("ECON Method failed\n");
1033 }
1034
1035 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1036 &handle))) {
1037 dprintk("Doing SNC setup\n");
1038 sony_nc_function_setup(device);
1039 }
1040
973 /* set the last requested brightness level */ 1041 /* set the last requested brightness level */
974 if (sony_backlight_device && 1042 if (sony_backlight_device &&
975 !sony_backlight_update_status(sony_backlight_device)) 1043 !sony_backlight_update_status(sony_backlight_device))
976 printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n"); 1044 printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
977 1045
978 /* re-initialize models with specific requirements */ 1046 return 0;
979 dmi_check_system(sony_nc_ids); 1047}
1048
1049static void sony_nc_rfkill_cleanup(void)
1050{
1051 int i;
1052
1053 for (i = 0; i < SONY_RFKILL_MAX; i++) {
1054 if (sony_rfkill_devices[i])
1055 rfkill_unregister(sony_rfkill_devices[i]);
1056 }
1057}
1058
1059static int sony_nc_rfkill_get(void *data, enum rfkill_state *state)
1060{
1061 int result;
1062 int argument = sony_rfkill_address[(long) data];
1063
1064 sony_call_snc_handle(0x124, 0x200, &result);
1065 if (result & 0x1) {
1066 sony_call_snc_handle(0x124, argument, &result);
1067 if (result & 0xf)
1068 *state = RFKILL_STATE_UNBLOCKED;
1069 else
1070 *state = RFKILL_STATE_SOFT_BLOCKED;
1071 } else {
1072 *state = RFKILL_STATE_HARD_BLOCKED;
1073 }
1074
1075 return 0;
1076}
1077
1078static int sony_nc_rfkill_set(void *data, enum rfkill_state state)
1079{
1080 int result;
1081 int argument = sony_rfkill_address[(long) data] + 0x100;
1082
1083 if (state == RFKILL_STATE_UNBLOCKED)
1084 argument |= 0xff0000;
1085
1086 return sony_call_snc_handle(0x124, argument, &result);
1087}
1088
1089static int sony_nc_setup_wifi_rfkill(struct acpi_device *device)
1090{
1091 int err = 0;
1092 struct rfkill *sony_wifi_rfkill;
1093
1094 sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
1095 if (!sony_wifi_rfkill)
1096 return -1;
1097 sony_wifi_rfkill->name = "sony-wifi";
1098 sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set;
1099 sony_wifi_rfkill->get_state = sony_nc_rfkill_get;
1100 sony_wifi_rfkill->user_claim_unsupported = 1;
1101 sony_wifi_rfkill->data = (void *)SONY_WIFI;
1102 err = rfkill_register(sony_wifi_rfkill);
1103 if (err)
1104 rfkill_free(sony_wifi_rfkill);
1105 else
1106 sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill;
1107 return err;
1108}
1109
1110static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device)
1111{
1112 int err = 0;
1113 struct rfkill *sony_bluetooth_rfkill;
1114
1115 sony_bluetooth_rfkill = rfkill_allocate(&device->dev,
1116 RFKILL_TYPE_BLUETOOTH);
1117 if (!sony_bluetooth_rfkill)
1118 return -1;
1119 sony_bluetooth_rfkill->name = "sony-bluetooth";
1120 sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set;
1121 sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get;
1122 sony_bluetooth_rfkill->user_claim_unsupported = 1;
1123 sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH;
1124 err = rfkill_register(sony_bluetooth_rfkill);
1125 if (err)
1126 rfkill_free(sony_bluetooth_rfkill);
1127 else
1128 sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill;
1129 return err;
1130}
1131
1132static int sony_nc_setup_wwan_rfkill(struct acpi_device *device)
1133{
1134 int err = 0;
1135 struct rfkill *sony_wwan_rfkill;
1136
1137 sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN);
1138 if (!sony_wwan_rfkill)
1139 return -1;
1140 sony_wwan_rfkill->name = "sony-wwan";
1141 sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set;
1142 sony_wwan_rfkill->get_state = sony_nc_rfkill_get;
1143 sony_wwan_rfkill->user_claim_unsupported = 1;
1144 sony_wwan_rfkill->data = (void *)SONY_WWAN;
1145 err = rfkill_register(sony_wwan_rfkill);
1146 if (err)
1147 rfkill_free(sony_wwan_rfkill);
1148 else
1149 sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill;
1150 return err;
1151}
1152
1153static int sony_nc_setup_wimax_rfkill(struct acpi_device *device)
1154{
1155 int err = 0;
1156 struct rfkill *sony_wimax_rfkill;
1157
1158 sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
1159 if (!sony_wimax_rfkill)
1160 return -1;
1161 sony_wimax_rfkill->name = "sony-wimax";
1162 sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set;
1163 sony_wimax_rfkill->get_state = sony_nc_rfkill_get;
1164 sony_wimax_rfkill->user_claim_unsupported = 1;
1165 sony_wimax_rfkill->data = (void *)SONY_WIMAX;
1166 err = rfkill_register(sony_wimax_rfkill);
1167 if (err)
1168 rfkill_free(sony_wimax_rfkill);
1169 else
1170 sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill;
1171 return err;
1172}
1173
1174static void sony_nc_rfkill_update()
1175{
1176 int i;
1177 enum rfkill_state state;
1178
1179 for (i = 0; i < SONY_RFKILL_MAX; i++) {
1180 if (sony_rfkill_devices[i]) {
1181 sony_rfkill_devices[i]->
1182 get_state(sony_rfkill_devices[i]->data,
1183 &state);
1184 rfkill_force_state(sony_rfkill_devices[i], state);
1185 }
1186 }
1187}
1188
1189static int sony_nc_rfkill_setup(struct acpi_device *device)
1190{
1191 int result, ret;
1192
1193 if (sony_find_snc_handle(0x124) == -1)
1194 return -1;
1195
1196 ret = sony_call_snc_handle(0x124, 0xb00, &result);
1197 if (ret) {
1198 printk(KERN_INFO DRV_PFX
1199 "Unable to enumerate rfkill devices: %x\n", ret);
1200 return ret;
1201 }
1202
1203 if (result & 0x1)
1204 sony_nc_setup_wifi_rfkill(device);
1205 if (result & 0x2)
1206 sony_nc_setup_bluetooth_rfkill(device);
1207 if (result & 0x1c)
1208 sony_nc_setup_wwan_rfkill(device);
1209 if (result & 0x20)
1210 sony_nc_setup_wimax_rfkill(device);
980 1211
981 return 0; 1212 return 0;
982} 1213}
@@ -1024,11 +1255,24 @@ static int sony_nc_add(struct acpi_device *device)
1024 dprintk("_INI Method failed\n"); 1255 dprintk("_INI Method failed\n");
1025 } 1256 }
1026 1257
1258 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
1259 &handle))) {
1260 if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
1261 dprintk("ECON Method failed\n");
1262 }
1263
1264 if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
1265 &handle))) {
1266 dprintk("Doing SNC setup\n");
1267 sony_nc_function_setup(device);
1268 sony_nc_rfkill_setup(device);
1269 }
1270
1027 /* setup input devices and helper fifo */ 1271 /* setup input devices and helper fifo */
1028 result = sony_laptop_setup_input(device); 1272 result = sony_laptop_setup_input(device);
1029 if (result) { 1273 if (result) {
1030 printk(KERN_ERR DRV_PFX 1274 printk(KERN_ERR DRV_PFX
1031 "Unabe to create input devices.\n"); 1275 "Unable to create input devices.\n");
1032 goto outwalk; 1276 goto outwalk;
1033 } 1277 }
1034 1278
@@ -1063,9 +1307,6 @@ static int sony_nc_add(struct acpi_device *device)
1063 1307
1064 } 1308 }
1065 1309
1066 /* initialize models with specific requirements */
1067 dmi_check_system(sony_nc_ids);
1068
1069 result = sony_pf_add(); 1310 result = sony_pf_add();
1070 if (result) 1311 if (result)
1071 goto outbacklight; 1312 goto outbacklight;
@@ -1131,6 +1372,7 @@ static int sony_nc_add(struct acpi_device *device)
1131 sony_laptop_remove_input(); 1372 sony_laptop_remove_input();
1132 1373
1133 outwalk: 1374 outwalk:
1375 sony_nc_rfkill_cleanup();
1134 return result; 1376 return result;
1135} 1377}
1136 1378
@@ -1156,6 +1398,7 @@ static int sony_nc_remove(struct acpi_device *device, int type)
1156 1398
1157 sony_pf_remove(); 1399 sony_pf_remove();
1158 sony_laptop_remove_input(); 1400 sony_laptop_remove_input();
1401 sony_nc_rfkill_cleanup();
1159 dprintk(SONY_NC_DRIVER_NAME " removed.\n"); 1402 dprintk(SONY_NC_DRIVER_NAME " removed.\n");
1160 1403
1161 return 0; 1404 return 0;
@@ -1195,7 +1438,6 @@ static struct acpi_driver sony_nc_driver = {
1195#define SONYPI_TYPE1_OFFSET 0x04 1438#define SONYPI_TYPE1_OFFSET 0x04
1196#define SONYPI_TYPE2_OFFSET 0x12 1439#define SONYPI_TYPE2_OFFSET 0x12
1197#define SONYPI_TYPE3_OFFSET 0x12 1440#define SONYPI_TYPE3_OFFSET 0x12
1198#define SONYPI_TYPE4_OFFSET 0x12
1199 1441
1200struct sony_pic_ioport { 1442struct sony_pic_ioport {
1201 struct acpi_resource_io io1; 1443 struct acpi_resource_io io1;
@@ -1328,6 +1570,7 @@ static struct sonypi_event sonypi_pkeyev[] = {
1328 { 0x01, SONYPI_EVENT_PKEY_P1 }, 1570 { 0x01, SONYPI_EVENT_PKEY_P1 },
1329 { 0x02, SONYPI_EVENT_PKEY_P2 }, 1571 { 0x02, SONYPI_EVENT_PKEY_P2 },
1330 { 0x04, SONYPI_EVENT_PKEY_P3 }, 1572 { 0x04, SONYPI_EVENT_PKEY_P3 },
1573 { 0x20, SONYPI_EVENT_PKEY_P1 },
1331 { 0, 0 } 1574 { 0, 0 }
1332}; 1575};
1333 1576
@@ -1371,6 +1614,7 @@ static struct sonypi_event sonypi_zoomev[] = {
1371 { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, 1614 { 0x39, SONYPI_EVENT_ZOOM_PRESSED },
1372 { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, 1615 { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
1373 { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, 1616 { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
1617 { 0x04, SONYPI_EVENT_ZOOM_PRESSED },
1374 { 0, 0 } 1618 { 0, 0 }
1375}; 1619};
1376 1620
@@ -1401,6 +1645,19 @@ static struct sonypi_event sonypi_batteryev[] = {
1401 { 0, 0 } 1645 { 0, 0 }
1402}; 1646};
1403 1647
1648/* The set of possible volume events */
1649static struct sonypi_event sonypi_volumeev[] = {
1650 { 0x01, SONYPI_EVENT_VOLUME_INC_PRESSED },
1651 { 0x02, SONYPI_EVENT_VOLUME_DEC_PRESSED },
1652 { 0, 0 }
1653};
1654
1655/* The set of possible brightness events */
1656static struct sonypi_event sonypi_brightnessev[] = {
1657 { 0x80, SONYPI_EVENT_BRIGHTNESS_PRESSED },
1658 { 0, 0 }
1659};
1660
1404static struct sonypi_eventtypes type1_events[] = { 1661static struct sonypi_eventtypes type1_events[] = {
1405 { 0, 0xffffffff, sonypi_releaseev }, 1662 { 0, 0xffffffff, sonypi_releaseev },
1406 { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, 1663 { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
@@ -1438,17 +1695,11 @@ static struct sonypi_eventtypes type3_events[] = {
1438 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, 1695 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1439 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, 1696 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
1440 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1697 { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
1441 { 0 },
1442};
1443static struct sonypi_eventtypes type4_events[] = {
1444 { 0, 0xffffffff, sonypi_releaseev },
1445 { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
1446 { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
1447 { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
1448 { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
1449 { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, 1698 { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
1450 { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, 1699 { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
1451 { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, 1700 { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
1701 { 0x05, SONYPI_PKEY_MASK, sonypi_volumeev },
1702 { 0x05, SONYPI_PKEY_MASK, sonypi_brightnessev },
1452 { 0 }, 1703 { 0 },
1453}; 1704};
1454 1705
@@ -1511,11 +1762,11 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
1511/* 1762/*
1512 * minidrivers for SPIC models 1763 * minidrivers for SPIC models
1513 */ 1764 */
1514static int type4_handle_irq(const u8 data_mask, const u8 ev) 1765static int type3_handle_irq(const u8 data_mask, const u8 ev)
1515{ 1766{
1516 /* 1767 /*
1517 * 0x31 could mean we have to take some extra action and wait for 1768 * 0x31 could mean we have to take some extra action and wait for
1518 * the next irq for some Type4 models, it will generate a new 1769 * the next irq for some Type3 models, it will generate a new
1519 * irq and we can read new data from the device: 1770 * irq and we can read new data from the device:
1520 * - 0x5c and 0x5f requires 0xA0 1771 * - 0x5c and 0x5f requires 0xA0
1521 * - 0x61 requires 0xB3 1772 * - 0x61 requires 0xB3
@@ -1545,16 +1796,10 @@ static struct device_ctrl spic_types[] = {
1545 }, 1796 },
1546 { 1797 {
1547 .model = SONYPI_DEVICE_TYPE3, 1798 .model = SONYPI_DEVICE_TYPE3,
1548 .handle_irq = NULL, 1799 .handle_irq = type3_handle_irq,
1549 .evport_offset = SONYPI_TYPE3_OFFSET, 1800 .evport_offset = SONYPI_TYPE3_OFFSET,
1550 .event_types = type3_events, 1801 .event_types = type3_events,
1551 }, 1802 },
1552 {
1553 .model = SONYPI_DEVICE_TYPE4,
1554 .handle_irq = type4_handle_irq,
1555 .evport_offset = SONYPI_TYPE4_OFFSET,
1556 .event_types = type4_events,
1557 },
1558}; 1803};
1559 1804
1560static void sony_pic_detect_device_type(struct sony_pic_dev *dev) 1805static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
@@ -1578,14 +1823,21 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
1578 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1823 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1579 PCI_DEVICE_ID_INTEL_ICH7_1, NULL); 1824 PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
1580 if (pcidev) { 1825 if (pcidev) {
1581 dev->control = &spic_types[3]; 1826 dev->control = &spic_types[2];
1582 goto out; 1827 goto out;
1583 } 1828 }
1584 1829
1585 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, 1830 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1586 PCI_DEVICE_ID_INTEL_ICH8_4, NULL); 1831 PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
1587 if (pcidev) { 1832 if (pcidev) {
1588 dev->control = &spic_types[3]; 1833 dev->control = &spic_types[2];
1834 goto out;
1835 }
1836
1837 pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
1838 PCI_DEVICE_ID_INTEL_ICH9_1, NULL);
1839 if (pcidev) {
1840 dev->control = &spic_types[2];
1589 goto out; 1841 goto out;
1590 } 1842 }
1591 1843
@@ -1598,8 +1850,7 @@ out:
1598 1850
1599 printk(KERN_INFO DRV_PFX "detected Type%d model\n", 1851 printk(KERN_INFO DRV_PFX "detected Type%d model\n",
1600 dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : 1852 dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
1601 dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 1853 dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
1602 dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4);
1603} 1854}
1604 1855
1605/* camera tests and poweron/poweroff */ 1856/* camera tests and poweron/poweroff */
@@ -1754,17 +2005,14 @@ int sony_pic_camera_command(int command, u8 value)
1754EXPORT_SYMBOL(sony_pic_camera_command); 2005EXPORT_SYMBOL(sony_pic_camera_command);
1755 2006
1756/* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */ 2007/* gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise */
1757static void sony_pic_set_wwanpower(u8 state) 2008static void __sony_pic_set_wwanpower(u8 state)
1758{ 2009{
1759 state = !!state; 2010 state = !!state;
1760 mutex_lock(&spic_dev.lock); 2011 if (spic_dev.wwan_power == state)
1761 if (spic_dev.wwan_power == state) {
1762 mutex_unlock(&spic_dev.lock);
1763 return; 2012 return;
1764 }
1765 sony_pic_call2(0xB0, state); 2013 sony_pic_call2(0xB0, state);
2014 sony_pic_call1(0x82);
1766 spic_dev.wwan_power = state; 2015 spic_dev.wwan_power = state;
1767 mutex_unlock(&spic_dev.lock);
1768} 2016}
1769 2017
1770static ssize_t sony_pic_wwanpower_store(struct device *dev, 2018static ssize_t sony_pic_wwanpower_store(struct device *dev,
@@ -1776,7 +2024,9 @@ static ssize_t sony_pic_wwanpower_store(struct device *dev,
1776 return -EINVAL; 2024 return -EINVAL;
1777 2025
1778 value = simple_strtoul(buffer, NULL, 10); 2026 value = simple_strtoul(buffer, NULL, 10);
1779 sony_pic_set_wwanpower(value); 2027 mutex_lock(&spic_dev.lock);
2028 __sony_pic_set_wwanpower(value);
2029 mutex_unlock(&spic_dev.lock);
1780 2030
1781 return count; 2031 return count;
1782} 2032}
@@ -1929,10 +2179,15 @@ static int sonypi_misc_release(struct inode *inode, struct file *file)
1929static int sonypi_misc_open(struct inode *inode, struct file *file) 2179static int sonypi_misc_open(struct inode *inode, struct file *file)
1930{ 2180{
1931 /* Flush input queue on first open */ 2181 /* Flush input queue on first open */
1932 lock_kernel(); 2182 unsigned long flags;
2183
2184 spin_lock_irqsave(sonypi_compat.fifo->lock, flags);
2185
1933 if (atomic_inc_return(&sonypi_compat.open_count) == 1) 2186 if (atomic_inc_return(&sonypi_compat.open_count) == 1)
1934 kfifo_reset(sonypi_compat.fifo); 2187 __kfifo_reset(sonypi_compat.fifo);
1935 unlock_kernel(); 2188
2189 spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags);
2190
1936 return 0; 2191 return 0;
1937} 2192}
1938 2193
@@ -1985,8 +2240,8 @@ static int ec_read16(u8 addr, u16 *value)
1985 return 0; 2240 return 0;
1986} 2241}
1987 2242
1988static int sonypi_misc_ioctl(struct inode *ip, struct file *fp, 2243static long sonypi_misc_ioctl(struct file *fp, unsigned int cmd,
1989 unsigned int cmd, unsigned long arg) 2244 unsigned long arg)
1990{ 2245{
1991 int ret = 0; 2246 int ret = 0;
1992 void __user *argp = (void __user *)arg; 2247 void __user *argp = (void __user *)arg;
@@ -2120,7 +2375,7 @@ static const struct file_operations sonypi_misc_fops = {
2120 .open = sonypi_misc_open, 2375 .open = sonypi_misc_open,
2121 .release = sonypi_misc_release, 2376 .release = sonypi_misc_release,
2122 .fasync = sonypi_misc_fasync, 2377 .fasync = sonypi_misc_fasync,
2123 .ioctl = sonypi_misc_ioctl, 2378 .unlocked_ioctl = sonypi_misc_ioctl,
2124}; 2379};
2125 2380
2126static struct miscdevice sonypi_misc_device = { 2381static struct miscdevice sonypi_misc_device = {
@@ -2561,7 +2816,7 @@ static int sony_pic_add(struct acpi_device *device)
2561 result = sony_pic_possible_resources(device); 2816 result = sony_pic_possible_resources(device);
2562 if (result) { 2817 if (result) {
2563 printk(KERN_ERR DRV_PFX 2818 printk(KERN_ERR DRV_PFX
2564 "Unabe to read possible resources.\n"); 2819 "Unable to read possible resources.\n");
2565 goto err_free_resources; 2820 goto err_free_resources;
2566 } 2821 }
2567 2822
@@ -2569,7 +2824,7 @@ static int sony_pic_add(struct acpi_device *device)
2569 result = sony_laptop_setup_input(device); 2824 result = sony_laptop_setup_input(device);
2570 if (result) { 2825 if (result) {
2571 printk(KERN_ERR DRV_PFX 2826 printk(KERN_ERR DRV_PFX
2572 "Unabe to create input devices.\n"); 2827 "Unable to create input devices.\n");
2573 goto err_free_resources; 2828 goto err_free_resources;
2574 } 2829 }
2575 2830
diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c
index b4a4aa9ee48..44166003d4e 100644
--- a/drivers/platform/x86/tc1100-wmi.c
+++ b/drivers/platform/x86/tc1100-wmi.c
@@ -94,9 +94,8 @@ static int get_state(u32 *out, u8 instance)
94 return -ENODEV; 94 return -ENODEV;
95 95
96 obj = (union acpi_object *) result.pointer; 96 obj = (union acpi_object *) result.pointer;
97 if (obj && obj->type == ACPI_TYPE_BUFFER && 97 if (obj && obj->type == ACPI_TYPE_INTEGER) {
98 obj->buffer.length == sizeof(u32)) { 98 tmp = obj->integer.value;
99 tmp = *((u32 *) obj->buffer.pointer);
100 } else { 99 } else {
101 tmp = 0; 100 tmp = 0;
102 } 101 }
@@ -109,7 +108,7 @@ static int get_state(u32 *out, u8 instance)
109 *out = (tmp == 3) ? 1 : 0; 108 *out = (tmp == 3) ? 1 : 0;
110 return 0; 109 return 0;
111 case TC1100_INSTANCE_JOGDIAL: 110 case TC1100_INSTANCE_JOGDIAL:
112 *out = (tmp == 1) ? 1 : 0; 111 *out = (tmp == 1) ? 0 : 1;
113 return 0; 112 return 0;
114 default: 113 default:
115 return -ENODEV; 114 return -ENODEV;
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index d99f1cd435a..a40b075743d 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * 4 *
5 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net> 5 * Copyright (C) 2004-2005 Borislav Deianov <borislav@users.sf.net>
6 * Copyright (C) 2006-2008 Henrique de Moraes Holschuh <hmh@hmh.eng.br> 6 * Copyright (C) 2006-2009 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
22 */ 22 */
23 23
24#define TPACPI_VERSION "0.22" 24#define TPACPI_VERSION "0.22"
25#define TPACPI_SYSFS_VERSION 0x020200 25#define TPACPI_SYSFS_VERSION 0x020300
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -54,6 +54,7 @@
54#include <linux/string.h> 54#include <linux/string.h>
55#include <linux/list.h> 55#include <linux/list.h>
56#include <linux/mutex.h> 56#include <linux/mutex.h>
57#include <linux/sched.h>
57#include <linux/kthread.h> 58#include <linux/kthread.h>
58#include <linux/freezer.h> 59#include <linux/freezer.h>
59#include <linux/delay.h> 60#include <linux/delay.h>
@@ -172,29 +173,26 @@ enum {
172 TPACPI_RFK_UWB_SW_ID, 173 TPACPI_RFK_UWB_SW_ID,
173}; 174};
174 175
175/* Debugging */ 176/* printk headers */
176#define TPACPI_LOG TPACPI_FILE ": " 177#define TPACPI_LOG TPACPI_FILE ": "
177#define TPACPI_ALERT KERN_ALERT TPACPI_LOG 178#define TPACPI_EMERG KERN_EMERG TPACPI_LOG
178#define TPACPI_CRIT KERN_CRIT TPACPI_LOG 179#define TPACPI_ALERT KERN_ALERT TPACPI_LOG
179#define TPACPI_ERR KERN_ERR TPACPI_LOG 180#define TPACPI_CRIT KERN_CRIT TPACPI_LOG
180#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG 181#define TPACPI_ERR KERN_ERR TPACPI_LOG
181#define TPACPI_INFO KERN_INFO TPACPI_LOG 182#define TPACPI_WARN KERN_WARNING TPACPI_LOG
182#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG 183#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG
183 184#define TPACPI_INFO KERN_INFO TPACPI_LOG
185#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG
186
187/* Debugging printk groups */
184#define TPACPI_DBG_ALL 0xffff 188#define TPACPI_DBG_ALL 0xffff
189#define TPACPI_DBG_DISCLOSETASK 0x8000
185#define TPACPI_DBG_INIT 0x0001 190#define TPACPI_DBG_INIT 0x0001
186#define TPACPI_DBG_EXIT 0x0002 191#define TPACPI_DBG_EXIT 0x0002
187#define dbg_printk(a_dbg_level, format, arg...) \ 192#define TPACPI_DBG_RFKILL 0x0004
188 do { if (dbg_level & a_dbg_level) \ 193#define TPACPI_DBG_HKEY 0x0008
189 printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ 194#define TPACPI_DBG_FAN 0x0010
190 } while (0) 195#define TPACPI_DBG_BRGHT 0x0020
191#ifdef CONFIG_THINKPAD_ACPI_DEBUG
192#define vdbg_printk(a_dbg_level, format, arg...) \
193 dbg_printk(a_dbg_level, format, ## arg)
194static const char *str_supported(int is_supported);
195#else
196#define vdbg_printk(a_dbg_level, format, arg...)
197#endif
198 196
199#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") 197#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
200#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") 198#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -277,7 +275,6 @@ static struct {
277 275
278static struct { 276static struct {
279 u16 hotkey_mask_ff:1; 277 u16 hotkey_mask_ff:1;
280 u16 bright_cmos_ec_unsync:1;
281} tp_warned; 278} tp_warned;
282 279
283struct thinkpad_id_data { 280struct thinkpad_id_data {
@@ -326,6 +323,39 @@ static int tpacpi_uwb_emulstate;
326#endif 323#endif
327 324
328 325
326/*************************************************************************
327 * Debugging helpers
328 */
329
330#define dbg_printk(a_dbg_level, format, arg...) \
331 do { if (dbg_level & (a_dbg_level)) \
332 printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \
333 } while (0)
334
335#ifdef CONFIG_THINKPAD_ACPI_DEBUG
336#define vdbg_printk dbg_printk
337static const char *str_supported(int is_supported);
338#else
339#define vdbg_printk(a_dbg_level, format, arg...) \
340 do { } while (0)
341#endif
342
343static void tpacpi_log_usertask(const char * const what)
344{
345 printk(TPACPI_DEBUG "%s: access by process with PID %d\n",
346 what, task_tgid_vnr(current));
347}
348
349#define tpacpi_disclose_usertask(what, format, arg...) \
350 do { \
351 if (unlikely( \
352 (dbg_level & TPACPI_DBG_DISCLOSETASK) && \
353 (tpacpi_lifecycle == TPACPI_LIFE_RUNNING))) { \
354 printk(TPACPI_DEBUG "%s: PID %d: " format, \
355 what, task_tgid_vnr(current), ## arg); \
356 } \
357 } while (0)
358
329/**************************************************************************** 359/****************************************************************************
330 **************************************************************************** 360 ****************************************************************************
331 * 361 *
@@ -989,10 +1019,13 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
989 /* try to set the initial state as the default for the rfkill 1019 /* 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 1020 * type, since we ask the firmware to preserve it across S5 in
991 * NVRAM */ 1021 * NVRAM */
992 rfkill_set_default(rfktype, 1022 if (rfkill_set_default(rfktype,
993 (initial_state == RFKILL_STATE_UNBLOCKED) ? 1023 (initial_state == RFKILL_STATE_UNBLOCKED) ?
994 RFKILL_STATE_UNBLOCKED : 1024 RFKILL_STATE_UNBLOCKED :
995 RFKILL_STATE_SOFT_BLOCKED); 1025 RFKILL_STATE_SOFT_BLOCKED) == -EPERM)
1026 vdbg_printk(TPACPI_DBG_RFKILL,
1027 "Default state for %s cannot be changed\n",
1028 name);
996 } 1029 }
997 1030
998 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype); 1031 *rfk = rfkill_allocate(&tpacpi_pdev->dev, rfktype);
@@ -1020,6 +1053,21 @@ static int __init tpacpi_new_rfkill(const unsigned int id,
1020 return 0; 1053 return 0;
1021} 1054}
1022 1055
1056static void printk_deprecated_attribute(const char * const what,
1057 const char * const details)
1058{
1059 tpacpi_log_usertask("deprecated sysfs attribute");
1060 printk(TPACPI_WARN "WARNING: sysfs attribute %s is deprecated and "
1061 "will be removed. %s\n",
1062 what, details);
1063}
1064
1065static void printk_deprecated_rfkill_attribute(const char * const what)
1066{
1067 printk_deprecated_attribute(what,
1068 "Please switch to generic rfkill before year 2010");
1069}
1070
1023/************************************************************************* 1071/*************************************************************************
1024 * thinkpad-acpi driver attributes 1072 * thinkpad-acpi driver attributes
1025 */ 1073 */
@@ -1382,7 +1430,6 @@ static enum { /* Reasons for waking up */
1382 1430
1383static int hotkey_autosleep_ack; 1431static int hotkey_autosleep_ack;
1384 1432
1385static int hotkey_orig_status;
1386static u32 hotkey_orig_mask; 1433static u32 hotkey_orig_mask;
1387static u32 hotkey_all_mask; 1434static u32 hotkey_all_mask;
1388static u32 hotkey_reserved_mask; 1435static u32 hotkey_reserved_mask;
@@ -1529,9 +1576,9 @@ static int hotkey_status_get(int *status)
1529 return 0; 1576 return 0;
1530} 1577}
1531 1578
1532static int hotkey_status_set(int status) 1579static int hotkey_status_set(bool enable)
1533{ 1580{
1534 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status)) 1581 if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", enable ? 1 : 0))
1535 return -EIO; 1582 return -EIO;
1536 1583
1537 return 0; 1584 return 0;
@@ -1847,6 +1894,9 @@ static ssize_t hotkey_enable_show(struct device *dev,
1847{ 1894{
1848 int res, status; 1895 int res, status;
1849 1896
1897 printk_deprecated_attribute("hotkey_enable",
1898 "Hotkey reporting is always enabled");
1899
1850 res = hotkey_status_get(&status); 1900 res = hotkey_status_get(&status);
1851 if (res) 1901 if (res)
1852 return res; 1902 return res;
@@ -1859,14 +1909,17 @@ static ssize_t hotkey_enable_store(struct device *dev,
1859 const char *buf, size_t count) 1909 const char *buf, size_t count)
1860{ 1910{
1861 unsigned long t; 1911 unsigned long t;
1862 int res; 1912
1913 printk_deprecated_attribute("hotkey_enable",
1914 "Hotkeys can be disabled through hotkey_mask");
1863 1915
1864 if (parse_strtoul(buf, 1, &t)) 1916 if (parse_strtoul(buf, 1, &t))
1865 return -EINVAL; 1917 return -EINVAL;
1866 1918
1867 res = hotkey_status_set(t); 1919 if (t == 0)
1920 return -EPERM;
1868 1921
1869 return (res) ? res : count; 1922 return count;
1870} 1923}
1871 1924
1872static struct device_attribute dev_attr_hotkey_enable = 1925static struct device_attribute dev_attr_hotkey_enable =
@@ -1910,6 +1963,8 @@ static ssize_t hotkey_mask_store(struct device *dev,
1910 1963
1911 mutex_unlock(&hotkey_mutex); 1964 mutex_unlock(&hotkey_mutex);
1912 1965
1966 tpacpi_disclose_usertask("hotkey_mask", "set to 0x%08lx\n", t);
1967
1913 return (res) ? res : count; 1968 return (res) ? res : count;
1914} 1969}
1915 1970
@@ -1922,7 +1977,7 @@ static ssize_t hotkey_bios_enabled_show(struct device *dev,
1922 struct device_attribute *attr, 1977 struct device_attribute *attr,
1923 char *buf) 1978 char *buf)
1924{ 1979{
1925 return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status); 1980 return sprintf(buf, "0\n");
1926} 1981}
1927 1982
1928static struct device_attribute dev_attr_hotkey_bios_enabled = 1983static struct device_attribute dev_attr_hotkey_bios_enabled =
@@ -1996,6 +2051,8 @@ static ssize_t hotkey_source_mask_store(struct device *dev,
1996 2051
1997 mutex_unlock(&hotkey_mutex); 2052 mutex_unlock(&hotkey_mutex);
1998 2053
2054 tpacpi_disclose_usertask("hotkey_source_mask", "set to 0x%08lx\n", t);
2055
1999 return count; 2056 return count;
2000} 2057}
2001 2058
@@ -2028,6 +2085,8 @@ static ssize_t hotkey_poll_freq_store(struct device *dev,
2028 hotkey_poll_setup(1); 2085 hotkey_poll_setup(1);
2029 mutex_unlock(&hotkey_mutex); 2086 mutex_unlock(&hotkey_mutex);
2030 2087
2088 tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t);
2089
2031 return count; 2090 return count;
2032} 2091}
2033 2092
@@ -2197,11 +2256,11 @@ static void hotkey_exit(void)
2197 kfree(hotkey_keycode_map); 2256 kfree(hotkey_keycode_map);
2198 2257
2199 if (tp_features.hotkey) { 2258 if (tp_features.hotkey) {
2200 dbg_printk(TPACPI_DBG_EXIT, 2259 dbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_HKEY,
2201 "restoring original hot key mask\n"); 2260 "restoring original hot key mask\n");
2202 /* no short-circuit boolean operator below! */ 2261 /* no short-circuit boolean operator below! */
2203 if ((hotkey_mask_set(hotkey_orig_mask) | 2262 if ((hotkey_mask_set(hotkey_orig_mask) |
2204 hotkey_status_set(hotkey_orig_status)) != 0) 2263 hotkey_status_set(false)) != 0)
2205 printk(TPACPI_ERR 2264 printk(TPACPI_ERR
2206 "failed to restore hot key mask " 2265 "failed to restore hot key mask "
2207 "to BIOS defaults\n"); 2266 "to BIOS defaults\n");
@@ -2327,7 +2386,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2327 int status; 2386 int status;
2328 int hkeyv; 2387 int hkeyv;
2329 2388
2330 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 2389 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2390 "initializing hotkey subdriver\n");
2331 2391
2332 BUG_ON(!tpacpi_inputdev); 2392 BUG_ON(!tpacpi_inputdev);
2333 BUG_ON(tpacpi_inputdev->open != NULL || 2393 BUG_ON(tpacpi_inputdev->open != NULL ||
@@ -2344,7 +2404,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2344 /* hotkey not supported on 570 */ 2404 /* hotkey not supported on 570 */
2345 tp_features.hotkey = hkey_handle != NULL; 2405 tp_features.hotkey = hkey_handle != NULL;
2346 2406
2347 vdbg_printk(TPACPI_DBG_INIT, "hotkeys are %s\n", 2407 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2408 "hotkeys are %s\n",
2348 str_supported(tp_features.hotkey)); 2409 str_supported(tp_features.hotkey));
2349 2410
2350 if (!tp_features.hotkey) 2411 if (!tp_features.hotkey)
@@ -2376,10 +2437,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2376 * T4x, X31, and later 2437 * T4x, X31, and later
2377 */ 2438 */
2378 tp_features.hotkey_mask = 1; 2439 tp_features.hotkey_mask = 1;
2440 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2441 "firmware HKEY interface version: 0x%x\n",
2442 hkeyv);
2379 } 2443 }
2380 } 2444 }
2381 2445
2382 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", 2446 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2447 "hotkey masks are %s\n",
2383 str_supported(tp_features.hotkey_mask)); 2448 str_supported(tp_features.hotkey_mask));
2384 2449
2385 if (tp_features.hotkey_mask) { 2450 if (tp_features.hotkey_mask) {
@@ -2396,10 +2461,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2396 2461
2397 /* hotkey_source_mask *must* be zero for 2462 /* hotkey_source_mask *must* be zero for
2398 * the first hotkey_mask_get */ 2463 * the first hotkey_mask_get */
2399 res = hotkey_status_get(&hotkey_orig_status);
2400 if (res)
2401 goto err_exit;
2402
2403 if (tp_features.hotkey_mask) { 2464 if (tp_features.hotkey_mask) {
2404 res = hotkey_mask_get(); 2465 res = hotkey_mask_get();
2405 if (res) 2466 if (res)
@@ -2422,7 +2483,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2422 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; 2483 hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK;
2423 } 2484 }
2424 2485
2425 vdbg_printk(TPACPI_DBG_INIT, 2486 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2426 "hotkey source mask 0x%08x, polling freq %d\n", 2487 "hotkey source mask 0x%08x, polling freq %d\n",
2427 hotkey_source_mask, hotkey_poll_freq); 2488 hotkey_source_mask, hotkey_poll_freq);
2428#endif 2489#endif
@@ -2476,12 +2537,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2476 } 2537 }
2477 2538
2478 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { 2539 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) {
2479 dbg_printk(TPACPI_DBG_INIT, 2540 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2480 "using Lenovo default hot key map\n"); 2541 "using Lenovo default hot key map\n");
2481 memcpy(hotkey_keycode_map, &lenovo_keycode_map, 2542 memcpy(hotkey_keycode_map, &lenovo_keycode_map,
2482 TPACPI_HOTKEY_MAP_SIZE); 2543 TPACPI_HOTKEY_MAP_SIZE);
2483 } else { 2544 } else {
2484 dbg_printk(TPACPI_DBG_INIT, 2545 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2485 "using IBM default hot key map\n"); 2546 "using IBM default hot key map\n");
2486 memcpy(hotkey_keycode_map, &ibm_keycode_map, 2547 memcpy(hotkey_keycode_map, &ibm_keycode_map,
2487 TPACPI_HOTKEY_MAP_SIZE); 2548 TPACPI_HOTKEY_MAP_SIZE);
@@ -2538,8 +2599,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2538 | (1 << TP_ACPI_HOTKEYSCAN_FNEND); 2599 | (1 << TP_ACPI_HOTKEYSCAN_FNEND);
2539 } 2600 }
2540 2601
2541 dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); 2602 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2542 res = hotkey_status_set(1); 2603 "enabling firmware HKEY event interface...\n");
2604 res = hotkey_status_set(true);
2543 if (res) { 2605 if (res) {
2544 hotkey_exit(); 2606 hotkey_exit();
2545 return res; 2607 return res;
@@ -2552,8 +2614,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2552 return res; 2614 return res;
2553 } 2615 }
2554 2616
2555 dbg_printk(TPACPI_DBG_INIT, 2617 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY,
2556 "legacy hot key reporting over procfs %s\n", 2618 "legacy ibm/hotkey event reporting over procfs %s\n",
2557 (hotkey_report_mode < 2) ? 2619 (hotkey_report_mode < 2) ?
2558 "enabled" : "disabled"); 2620 "enabled" : "disabled");
2559 2621
@@ -2884,9 +2946,17 @@ static int hotkey_read(char *p)
2884 return len; 2946 return len;
2885} 2947}
2886 2948
2949static void hotkey_enabledisable_warn(void)
2950{
2951 tpacpi_log_usertask("procfs hotkey enable/disable");
2952 WARN(1, TPACPI_WARN
2953 "hotkey enable/disable functionality has been "
2954 "removed from the driver. Hotkeys are always enabled.\n");
2955}
2956
2887static int hotkey_write(char *buf) 2957static int hotkey_write(char *buf)
2888{ 2958{
2889 int res, status; 2959 int res;
2890 u32 mask; 2960 u32 mask;
2891 char *cmd; 2961 char *cmd;
2892 2962
@@ -2896,17 +2966,16 @@ static int hotkey_write(char *buf)
2896 if (mutex_lock_killable(&hotkey_mutex)) 2966 if (mutex_lock_killable(&hotkey_mutex))
2897 return -ERESTARTSYS; 2967 return -ERESTARTSYS;
2898 2968
2899 status = -1;
2900 mask = hotkey_mask; 2969 mask = hotkey_mask;
2901 2970
2902 res = 0; 2971 res = 0;
2903 while ((cmd = next_cmd(&buf))) { 2972 while ((cmd = next_cmd(&buf))) {
2904 if (strlencmp(cmd, "enable") == 0) { 2973 if (strlencmp(cmd, "enable") == 0) {
2905 status = 1; 2974 hotkey_enabledisable_warn();
2906 } else if (strlencmp(cmd, "disable") == 0) { 2975 } else if (strlencmp(cmd, "disable") == 0) {
2907 status = 0; 2976 hotkey_enabledisable_warn();
2977 res = -EPERM;
2908 } else if (strlencmp(cmd, "reset") == 0) { 2978 } else if (strlencmp(cmd, "reset") == 0) {
2909 status = hotkey_orig_status;
2910 mask = hotkey_orig_mask; 2979 mask = hotkey_orig_mask;
2911 } else if (sscanf(cmd, "0x%x", &mask) == 1) { 2980 } else if (sscanf(cmd, "0x%x", &mask) == 1) {
2912 /* mask set */ 2981 /* mask set */
@@ -2917,8 +2986,10 @@ static int hotkey_write(char *buf)
2917 goto errexit; 2986 goto errexit;
2918 } 2987 }
2919 } 2988 }
2920 if (status != -1) 2989
2921 res = hotkey_status_set(status); 2990 if (!res)
2991 tpacpi_disclose_usertask("procfs hotkey",
2992 "set mask to 0x%08x\n", mask);
2922 2993
2923 if (!res && mask != hotkey_mask) 2994 if (!res && mask != hotkey_mask)
2924 res = hotkey_mask_set(mask); 2995 res = hotkey_mask_set(mask);
@@ -2971,13 +3042,17 @@ enum {
2971 TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */ 3042 TP_ACPI_BLTH_SAVE_STATE = 0x05, /* Save state for S4/S5 */
2972}; 3043};
2973 3044
3045#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
3046
2974static struct rfkill *tpacpi_bluetooth_rfkill; 3047static struct rfkill *tpacpi_bluetooth_rfkill;
2975 3048
2976static void bluetooth_suspend(pm_message_t state) 3049static void bluetooth_suspend(pm_message_t state)
2977{ 3050{
2978 /* Try to make sure radio will resume powered off */ 3051 /* Try to make sure radio will resume powered off */
2979 acpi_evalf(NULL, NULL, "\\BLTH", "vd", 3052 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
2980 TP_ACPI_BLTH_PWR_OFF_ON_RESUME); 3053 TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
3054 vdbg_printk(TPACPI_DBG_RFKILL,
3055 "bluetooth power down on resume request failed\n");
2981} 3056}
2982 3057
2983static int bluetooth_get_radiosw(void) 3058static int bluetooth_get_radiosw(void)
@@ -3015,6 +3090,10 @@ static void bluetooth_update_rfk(void)
3015 if (status < 0) 3090 if (status < 0)
3016 return; 3091 return;
3017 rfkill_force_state(tpacpi_bluetooth_rfkill, status); 3092 rfkill_force_state(tpacpi_bluetooth_rfkill, status);
3093
3094 vdbg_printk(TPACPI_DBG_RFKILL,
3095 "forced rfkill state to %d\n",
3096 status);
3018} 3097}
3019 3098
3020static int bluetooth_set_radiosw(int radio_on, int update_rfk) 3099static int bluetooth_set_radiosw(int radio_on, int update_rfk)
@@ -3030,6 +3109,9 @@ static int bluetooth_set_radiosw(int radio_on, int update_rfk)
3030 && radio_on) 3109 && radio_on)
3031 return -EPERM; 3110 return -EPERM;
3032 3111
3112 vdbg_printk(TPACPI_DBG_RFKILL,
3113 "will %s bluetooth\n", radio_on ? "enable" : "disable");
3114
3033#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3115#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3034 if (dbg_bluetoothemul) { 3116 if (dbg_bluetoothemul) {
3035 tpacpi_bluetooth_emulstate = !!radio_on; 3117 tpacpi_bluetooth_emulstate = !!radio_on;
@@ -3060,6 +3142,8 @@ static ssize_t bluetooth_enable_show(struct device *dev,
3060{ 3142{
3061 int status; 3143 int status;
3062 3144
3145 printk_deprecated_rfkill_attribute("bluetooth_enable");
3146
3063 status = bluetooth_get_radiosw(); 3147 status = bluetooth_get_radiosw();
3064 if (status < 0) 3148 if (status < 0)
3065 return status; 3149 return status;
@@ -3075,9 +3159,13 @@ static ssize_t bluetooth_enable_store(struct device *dev,
3075 unsigned long t; 3159 unsigned long t;
3076 int res; 3160 int res;
3077 3161
3162 printk_deprecated_rfkill_attribute("bluetooth_enable");
3163
3078 if (parse_strtoul(buf, 1, &t)) 3164 if (parse_strtoul(buf, 1, &t))
3079 return -EINVAL; 3165 return -EINVAL;
3080 3166
3167 tpacpi_disclose_usertask("bluetooth_enable", "set to %ld\n", t);
3168
3081 res = bluetooth_set_radiosw(t, 1); 3169 res = bluetooth_set_radiosw(t, 1);
3082 3170
3083 return (res) ? res : count; 3171 return (res) ? res : count;
@@ -3111,6 +3199,8 @@ static int tpacpi_bluetooth_rfk_get(void *data, enum rfkill_state *state)
3111 3199
3112static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state) 3200static int tpacpi_bluetooth_rfk_set(void *data, enum rfkill_state state)
3113{ 3201{
3202 dbg_printk(TPACPI_DBG_RFKILL,
3203 "request to change radio state to %d\n", state);
3114 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 3204 return bluetooth_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3115} 3205}
3116 3206
@@ -3121,6 +3211,9 @@ static void bluetooth_shutdown(void)
3121 TP_ACPI_BLTH_SAVE_STATE)) 3211 TP_ACPI_BLTH_SAVE_STATE))
3122 printk(TPACPI_NOTICE 3212 printk(TPACPI_NOTICE
3123 "failed to save bluetooth state to NVRAM\n"); 3213 "failed to save bluetooth state to NVRAM\n");
3214 else
3215 vdbg_printk(TPACPI_DBG_RFKILL,
3216 "bluestooth state saved to NVRAM\n");
3124} 3217}
3125 3218
3126static void bluetooth_exit(void) 3219static void bluetooth_exit(void)
@@ -3139,7 +3232,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
3139 int res; 3232 int res;
3140 int status = 0; 3233 int status = 0;
3141 3234
3142 vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); 3235 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3236 "initializing bluetooth subdriver\n");
3143 3237
3144 TPACPI_ACPIHANDLE_INIT(hkey); 3238 TPACPI_ACPIHANDLE_INIT(hkey);
3145 3239
@@ -3148,7 +3242,8 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
3148 tp_features.bluetooth = hkey_handle && 3242 tp_features.bluetooth = hkey_handle &&
3149 acpi_evalf(hkey_handle, &status, "GBDC", "qd"); 3243 acpi_evalf(hkey_handle, &status, "GBDC", "qd");
3150 3244
3151 vdbg_printk(TPACPI_DBG_INIT, "bluetooth is %s, status 0x%02x\n", 3245 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3246 "bluetooth is %s, status 0x%02x\n",
3152 str_supported(tp_features.bluetooth), 3247 str_supported(tp_features.bluetooth),
3153 status); 3248 status);
3154 3249
@@ -3163,7 +3258,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
3163 !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) { 3258 !(status & TP_ACPI_BLUETOOTH_HWPRESENT)) {
3164 /* no bluetooth hardware present in system */ 3259 /* no bluetooth hardware present in system */
3165 tp_features.bluetooth = 0; 3260 tp_features.bluetooth = 0;
3166 dbg_printk(TPACPI_DBG_INIT, 3261 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3167 "bluetooth hardware not installed\n"); 3262 "bluetooth hardware not installed\n");
3168 } 3263 }
3169 3264
@@ -3178,7 +3273,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
3178 res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID, 3273 res = tpacpi_new_rfkill(TPACPI_RFK_BLUETOOTH_SW_ID,
3179 &tpacpi_bluetooth_rfkill, 3274 &tpacpi_bluetooth_rfkill,
3180 RFKILL_TYPE_BLUETOOTH, 3275 RFKILL_TYPE_BLUETOOTH,
3181 "tpacpi_bluetooth_sw", 3276 TPACPI_RFK_BLUETOOTH_SW_NAME,
3182 true, 3277 true,
3183 tpacpi_bluetooth_rfk_set, 3278 tpacpi_bluetooth_rfk_set,
3184 tpacpi_bluetooth_rfk_get); 3279 tpacpi_bluetooth_rfk_get);
@@ -3211,19 +3306,27 @@ static int bluetooth_read(char *p)
3211static int bluetooth_write(char *buf) 3306static int bluetooth_write(char *buf)
3212{ 3307{
3213 char *cmd; 3308 char *cmd;
3309 int state = -1;
3214 3310
3215 if (!tp_features.bluetooth) 3311 if (!tp_features.bluetooth)
3216 return -ENODEV; 3312 return -ENODEV;
3217 3313
3218 while ((cmd = next_cmd(&buf))) { 3314 while ((cmd = next_cmd(&buf))) {
3219 if (strlencmp(cmd, "enable") == 0) { 3315 if (strlencmp(cmd, "enable") == 0) {
3220 bluetooth_set_radiosw(1, 1); 3316 state = 1;
3221 } else if (strlencmp(cmd, "disable") == 0) { 3317 } else if (strlencmp(cmd, "disable") == 0) {
3222 bluetooth_set_radiosw(0, 1); 3318 state = 0;
3223 } else 3319 } else
3224 return -EINVAL; 3320 return -EINVAL;
3225 } 3321 }
3226 3322
3323 if (state != -1) {
3324 tpacpi_disclose_usertask("procfs bluetooth",
3325 "attempt to %s\n",
3326 state ? "enable" : "disable");
3327 bluetooth_set_radiosw(state, 1);
3328 }
3329
3227 return 0; 3330 return 0;
3228} 3331}
3229 3332
@@ -3248,13 +3351,17 @@ enum {
3248 off / last state */ 3351 off / last state */
3249}; 3352};
3250 3353
3354#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
3355
3251static struct rfkill *tpacpi_wan_rfkill; 3356static struct rfkill *tpacpi_wan_rfkill;
3252 3357
3253static void wan_suspend(pm_message_t state) 3358static void wan_suspend(pm_message_t state)
3254{ 3359{
3255 /* Try to make sure radio will resume powered off */ 3360 /* Try to make sure radio will resume powered off */
3256 acpi_evalf(NULL, NULL, "\\WGSV", "qvd", 3361 if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
3257 TP_ACPI_WGSV_PWR_OFF_ON_RESUME); 3362 TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
3363 vdbg_printk(TPACPI_DBG_RFKILL,
3364 "WWAN power down on resume request failed\n");
3258} 3365}
3259 3366
3260static int wan_get_radiosw(void) 3367static int wan_get_radiosw(void)
@@ -3292,6 +3399,10 @@ static void wan_update_rfk(void)
3292 if (status < 0) 3399 if (status < 0)
3293 return; 3400 return;
3294 rfkill_force_state(tpacpi_wan_rfkill, status); 3401 rfkill_force_state(tpacpi_wan_rfkill, status);
3402
3403 vdbg_printk(TPACPI_DBG_RFKILL,
3404 "forced rfkill state to %d\n",
3405 status);
3295} 3406}
3296 3407
3297static int wan_set_radiosw(int radio_on, int update_rfk) 3408static int wan_set_radiosw(int radio_on, int update_rfk)
@@ -3307,6 +3418,9 @@ static int wan_set_radiosw(int radio_on, int update_rfk)
3307 && radio_on) 3418 && radio_on)
3308 return -EPERM; 3419 return -EPERM;
3309 3420
3421 vdbg_printk(TPACPI_DBG_RFKILL,
3422 "will %s WWAN\n", radio_on ? "enable" : "disable");
3423
3310#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3424#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3311 if (dbg_wwanemul) { 3425 if (dbg_wwanemul) {
3312 tpacpi_wwan_emulstate = !!radio_on; 3426 tpacpi_wwan_emulstate = !!radio_on;
@@ -3337,6 +3451,8 @@ static ssize_t wan_enable_show(struct device *dev,
3337{ 3451{
3338 int status; 3452 int status;
3339 3453
3454 printk_deprecated_rfkill_attribute("wwan_enable");
3455
3340 status = wan_get_radiosw(); 3456 status = wan_get_radiosw();
3341 if (status < 0) 3457 if (status < 0)
3342 return status; 3458 return status;
@@ -3352,9 +3468,13 @@ static ssize_t wan_enable_store(struct device *dev,
3352 unsigned long t; 3468 unsigned long t;
3353 int res; 3469 int res;
3354 3470
3471 printk_deprecated_rfkill_attribute("wwan_enable");
3472
3355 if (parse_strtoul(buf, 1, &t)) 3473 if (parse_strtoul(buf, 1, &t))
3356 return -EINVAL; 3474 return -EINVAL;
3357 3475
3476 tpacpi_disclose_usertask("wwan_enable", "set to %ld\n", t);
3477
3358 res = wan_set_radiosw(t, 1); 3478 res = wan_set_radiosw(t, 1);
3359 3479
3360 return (res) ? res : count; 3480 return (res) ? res : count;
@@ -3388,6 +3508,8 @@ static int tpacpi_wan_rfk_get(void *data, enum rfkill_state *state)
3388 3508
3389static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state) 3509static int tpacpi_wan_rfk_set(void *data, enum rfkill_state state)
3390{ 3510{
3511 dbg_printk(TPACPI_DBG_RFKILL,
3512 "request to change radio state to %d\n", state);
3391 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 3513 return wan_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3392} 3514}
3393 3515
@@ -3398,6 +3520,9 @@ static void wan_shutdown(void)
3398 TP_ACPI_WGSV_SAVE_STATE)) 3520 TP_ACPI_WGSV_SAVE_STATE))
3399 printk(TPACPI_NOTICE 3521 printk(TPACPI_NOTICE
3400 "failed to save WWAN state to NVRAM\n"); 3522 "failed to save WWAN state to NVRAM\n");
3523 else
3524 vdbg_printk(TPACPI_DBG_RFKILL,
3525 "WWAN state saved to NVRAM\n");
3401} 3526}
3402 3527
3403static void wan_exit(void) 3528static void wan_exit(void)
@@ -3416,14 +3541,16 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3416 int res; 3541 int res;
3417 int status = 0; 3542 int status = 0;
3418 3543
3419 vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); 3544 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3545 "initializing wan subdriver\n");
3420 3546
3421 TPACPI_ACPIHANDLE_INIT(hkey); 3547 TPACPI_ACPIHANDLE_INIT(hkey);
3422 3548
3423 tp_features.wan = hkey_handle && 3549 tp_features.wan = hkey_handle &&
3424 acpi_evalf(hkey_handle, &status, "GWAN", "qd"); 3550 acpi_evalf(hkey_handle, &status, "GWAN", "qd");
3425 3551
3426 vdbg_printk(TPACPI_DBG_INIT, "wan is %s, status 0x%02x\n", 3552 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3553 "wan is %s, status 0x%02x\n",
3427 str_supported(tp_features.wan), 3554 str_supported(tp_features.wan),
3428 status); 3555 status);
3429 3556
@@ -3438,7 +3565,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3438 !(status & TP_ACPI_WANCARD_HWPRESENT)) { 3565 !(status & TP_ACPI_WANCARD_HWPRESENT)) {
3439 /* no wan hardware present in system */ 3566 /* no wan hardware present in system */
3440 tp_features.wan = 0; 3567 tp_features.wan = 0;
3441 dbg_printk(TPACPI_DBG_INIT, 3568 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3442 "wan hardware not installed\n"); 3569 "wan hardware not installed\n");
3443 } 3570 }
3444 3571
@@ -3453,7 +3580,7 @@ static int __init wan_init(struct ibm_init_struct *iibm)
3453 res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID, 3580 res = tpacpi_new_rfkill(TPACPI_RFK_WWAN_SW_ID,
3454 &tpacpi_wan_rfkill, 3581 &tpacpi_wan_rfkill,
3455 RFKILL_TYPE_WWAN, 3582 RFKILL_TYPE_WWAN,
3456 "tpacpi_wwan_sw", 3583 TPACPI_RFK_WWAN_SW_NAME,
3457 true, 3584 true,
3458 tpacpi_wan_rfk_set, 3585 tpacpi_wan_rfk_set,
3459 tpacpi_wan_rfk_get); 3586 tpacpi_wan_rfk_get);
@@ -3471,6 +3598,8 @@ static int wan_read(char *p)
3471 int len = 0; 3598 int len = 0;
3472 int status = wan_get_radiosw(); 3599 int status = wan_get_radiosw();
3473 3600
3601 tpacpi_disclose_usertask("procfs wan", "read");
3602
3474 if (!tp_features.wan) 3603 if (!tp_features.wan)
3475 len += sprintf(p + len, "status:\t\tnot supported\n"); 3604 len += sprintf(p + len, "status:\t\tnot supported\n");
3476 else { 3605 else {
@@ -3486,19 +3615,27 @@ static int wan_read(char *p)
3486static int wan_write(char *buf) 3615static int wan_write(char *buf)
3487{ 3616{
3488 char *cmd; 3617 char *cmd;
3618 int state = -1;
3489 3619
3490 if (!tp_features.wan) 3620 if (!tp_features.wan)
3491 return -ENODEV; 3621 return -ENODEV;
3492 3622
3493 while ((cmd = next_cmd(&buf))) { 3623 while ((cmd = next_cmd(&buf))) {
3494 if (strlencmp(cmd, "enable") == 0) { 3624 if (strlencmp(cmd, "enable") == 0) {
3495 wan_set_radiosw(1, 1); 3625 state = 1;
3496 } else if (strlencmp(cmd, "disable") == 0) { 3626 } else if (strlencmp(cmd, "disable") == 0) {
3497 wan_set_radiosw(0, 1); 3627 state = 0;
3498 } else 3628 } else
3499 return -EINVAL; 3629 return -EINVAL;
3500 } 3630 }
3501 3631
3632 if (state != -1) {
3633 tpacpi_disclose_usertask("procfs wan",
3634 "attempt to %s\n",
3635 state ? "enable" : "disable");
3636 wan_set_radiosw(state, 1);
3637 }
3638
3502 return 0; 3639 return 0;
3503} 3640}
3504 3641
@@ -3521,6 +3658,8 @@ enum {
3521 TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */ 3658 TP_ACPI_UWB_RADIOSSW = 0x02, /* UWB radio enabled */
3522}; 3659};
3523 3660
3661#define TPACPI_RFK_UWB_SW_NAME "tpacpi_uwb_sw"
3662
3524static struct rfkill *tpacpi_uwb_rfkill; 3663static struct rfkill *tpacpi_uwb_rfkill;
3525 3664
3526static int uwb_get_radiosw(void) 3665static int uwb_get_radiosw(void)
@@ -3558,6 +3697,10 @@ static void uwb_update_rfk(void)
3558 if (status < 0) 3697 if (status < 0)
3559 return; 3698 return;
3560 rfkill_force_state(tpacpi_uwb_rfkill, status); 3699 rfkill_force_state(tpacpi_uwb_rfkill, status);
3700
3701 vdbg_printk(TPACPI_DBG_RFKILL,
3702 "forced rfkill state to %d\n",
3703 status);
3561} 3704}
3562 3705
3563static int uwb_set_radiosw(int radio_on, int update_rfk) 3706static int uwb_set_radiosw(int radio_on, int update_rfk)
@@ -3573,6 +3716,9 @@ static int uwb_set_radiosw(int radio_on, int update_rfk)
3573 && radio_on) 3716 && radio_on)
3574 return -EPERM; 3717 return -EPERM;
3575 3718
3719 vdbg_printk(TPACPI_DBG_RFKILL,
3720 "will %s UWB\n", radio_on ? "enable" : "disable");
3721
3576#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3722#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3577 if (dbg_uwbemul) { 3723 if (dbg_uwbemul) {
3578 tpacpi_uwb_emulstate = !!radio_on; 3724 tpacpi_uwb_emulstate = !!radio_on;
@@ -3607,6 +3753,8 @@ static int tpacpi_uwb_rfk_get(void *data, enum rfkill_state *state)
3607 3753
3608static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state) 3754static int tpacpi_uwb_rfk_set(void *data, enum rfkill_state state)
3609{ 3755{
3756 dbg_printk(TPACPI_DBG_RFKILL,
3757 "request to change radio state to %d\n", state);
3610 return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0); 3758 return uwb_set_radiosw((state == RFKILL_STATE_UNBLOCKED), 0);
3611} 3759}
3612 3760
@@ -3621,14 +3769,16 @@ static int __init uwb_init(struct ibm_init_struct *iibm)
3621 int res; 3769 int res;
3622 int status = 0; 3770 int status = 0;
3623 3771
3624 vdbg_printk(TPACPI_DBG_INIT, "initializing uwb subdriver\n"); 3772 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3773 "initializing uwb subdriver\n");
3625 3774
3626 TPACPI_ACPIHANDLE_INIT(hkey); 3775 TPACPI_ACPIHANDLE_INIT(hkey);
3627 3776
3628 tp_features.uwb = hkey_handle && 3777 tp_features.uwb = hkey_handle &&
3629 acpi_evalf(hkey_handle, &status, "GUWB", "qd"); 3778 acpi_evalf(hkey_handle, &status, "GUWB", "qd");
3630 3779
3631 vdbg_printk(TPACPI_DBG_INIT, "uwb is %s, status 0x%02x\n", 3780 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_RFKILL,
3781 "uwb is %s, status 0x%02x\n",
3632 str_supported(tp_features.uwb), 3782 str_supported(tp_features.uwb),
3633 status); 3783 status);
3634 3784
@@ -3653,7 +3803,7 @@ static int __init uwb_init(struct ibm_init_struct *iibm)
3653 res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID, 3803 res = tpacpi_new_rfkill(TPACPI_RFK_UWB_SW_ID,
3654 &tpacpi_uwb_rfkill, 3804 &tpacpi_uwb_rfkill,
3655 RFKILL_TYPE_UWB, 3805 RFKILL_TYPE_UWB,
3656 "tpacpi_uwb_sw", 3806 TPACPI_RFK_UWB_SW_NAME,
3657 false, 3807 false,
3658 tpacpi_uwb_rfk_set, 3808 tpacpi_uwb_rfk_set,
3659 tpacpi_uwb_rfk_get); 3809 tpacpi_uwb_rfk_get);
@@ -4602,6 +4752,16 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
4602 "tpacpi::unknown_led", 4752 "tpacpi::unknown_led",
4603 "tpacpi::standby", 4753 "tpacpi::standby",
4604}; 4754};
4755#define TPACPI_SAFE_LEDS 0x0081U
4756
4757static inline bool tpacpi_is_led_restricted(const unsigned int led)
4758{
4759#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
4760 return false;
4761#else
4762 return (TPACPI_SAFE_LEDS & (1 << led)) == 0;
4763#endif
4764}
4605 4765
4606static int led_get_status(const unsigned int led) 4766static int led_get_status(const unsigned int led)
4607{ 4767{
@@ -4639,16 +4799,20 @@ static int led_set_status(const unsigned int led,
4639 switch (led_supported) { 4799 switch (led_supported) {
4640 case TPACPI_LED_570: 4800 case TPACPI_LED_570:
4641 /* 570 */ 4801 /* 570 */
4642 if (led > 7) 4802 if (unlikely(led > 7))
4643 return -EINVAL; 4803 return -EINVAL;
4804 if (unlikely(tpacpi_is_led_restricted(led)))
4805 return -EPERM;
4644 if (!acpi_evalf(led_handle, NULL, NULL, "vdd", 4806 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
4645 (1 << led), led_sled_arg1[ledstatus])) 4807 (1 << led), led_sled_arg1[ledstatus]))
4646 rc = -EIO; 4808 rc = -EIO;
4647 break; 4809 break;
4648 case TPACPI_LED_OLD: 4810 case TPACPI_LED_OLD:
4649 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ 4811 /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */
4650 if (led > 7) 4812 if (unlikely(led > 7))
4651 return -EINVAL; 4813 return -EINVAL;
4814 if (unlikely(tpacpi_is_led_restricted(led)))
4815 return -EPERM;
4652 rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led)); 4816 rc = ec_write(TPACPI_LED_EC_HLMS, (1 << led));
4653 if (rc >= 0) 4817 if (rc >= 0)
4654 rc = ec_write(TPACPI_LED_EC_HLBL, 4818 rc = ec_write(TPACPI_LED_EC_HLBL,
@@ -4659,6 +4823,10 @@ static int led_set_status(const unsigned int led,
4659 break; 4823 break;
4660 case TPACPI_LED_NEW: 4824 case TPACPI_LED_NEW:
4661 /* all others */ 4825 /* all others */
4826 if (unlikely(led >= TPACPI_LED_NUMLEDS))
4827 return -EINVAL;
4828 if (unlikely(tpacpi_is_led_restricted(led)))
4829 return -EPERM;
4662 if (!acpi_evalf(led_handle, NULL, NULL, "vdd", 4830 if (!acpi_evalf(led_handle, NULL, NULL, "vdd",
4663 led, led_led_arg1[ledstatus])) 4831 led, led_led_arg1[ledstatus]))
4664 rc = -EIO; 4832 rc = -EIO;
@@ -4751,6 +4919,30 @@ static void led_exit(void)
4751 kfree(tpacpi_leds); 4919 kfree(tpacpi_leds);
4752} 4920}
4753 4921
4922static int __init tpacpi_init_led(unsigned int led)
4923{
4924 int rc;
4925
4926 tpacpi_leds[led].led = led;
4927
4928 tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set;
4929 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
4930 if (led_supported == TPACPI_LED_570)
4931 tpacpi_leds[led].led_classdev.brightness_get =
4932 &led_sysfs_get;
4933
4934 tpacpi_leds[led].led_classdev.name = tpacpi_led_names[led];
4935
4936 INIT_WORK(&tpacpi_leds[led].work, led_set_status_worker);
4937
4938 rc = led_classdev_register(&tpacpi_pdev->dev,
4939 &tpacpi_leds[led].led_classdev);
4940 if (rc < 0)
4941 tpacpi_leds[led].led_classdev.name = NULL;
4942
4943 return rc;
4944}
4945
4754static int __init led_init(struct ibm_init_struct *iibm) 4946static int __init led_init(struct ibm_init_struct *iibm)
4755{ 4947{
4756 unsigned int i; 4948 unsigned int i;
@@ -4784,27 +4976,21 @@ static int __init led_init(struct ibm_init_struct *iibm)
4784 } 4976 }
4785 4977
4786 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { 4978 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
4787 tpacpi_leds[i].led = i; 4979 if (!tpacpi_is_led_restricted(i)) {
4788 4980 rc = tpacpi_init_led(i);
4789 tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set; 4981 if (rc < 0) {
4790 tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set; 4982 led_exit();
4791 if (led_supported == TPACPI_LED_570) 4983 return rc;
4792 tpacpi_leds[i].led_classdev.brightness_get = 4984 }
4793 &led_sysfs_get;
4794
4795 tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i];
4796
4797 INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker);
4798
4799 rc = led_classdev_register(&tpacpi_pdev->dev,
4800 &tpacpi_leds[i].led_classdev);
4801 if (rc < 0) {
4802 tpacpi_leds[i].led_classdev.name = NULL;
4803 led_exit();
4804 return rc;
4805 } 4985 }
4806 } 4986 }
4807 4987
4988#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
4989 if (led_supported != TPACPI_LED_NONE)
4990 printk(TPACPI_NOTICE
4991 "warning: userspace override of important "
4992 "firmware LEDs is enabled\n");
4993#endif
4808 return (led_supported != TPACPI_LED_NONE)? 0 : 1; 4994 return (led_supported != TPACPI_LED_NONE)? 0 : 1;
4809} 4995}
4810 4996
@@ -5340,6 +5526,20 @@ static struct ibm_struct ecdump_driver_data = {
5340 5526
5341#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" 5527#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen"
5342 5528
5529/*
5530 * ThinkPads can read brightness from two places: EC HBRV (0x31), or
5531 * CMOS NVRAM byte 0x5E, bits 0-3.
5532 *
5533 * EC HBRV (0x31) has the following layout
5534 * Bit 7: unknown function
5535 * Bit 6: unknown function
5536 * Bit 5: Z: honour scale changes, NZ: ignore scale changes
5537 * Bit 4: must be set to zero to avoid problems
5538 * Bit 3-0: backlight brightness level
5539 *
5540 * brightness_get_raw returns status data in the HBRV layout
5541 */
5542
5343enum { 5543enum {
5344 TP_EC_BACKLIGHT = 0x31, 5544 TP_EC_BACKLIGHT = 0x31,
5345 5545
@@ -5349,108 +5549,164 @@ enum {
5349 TP_EC_BACKLIGHT_MAPSW = 0x20, 5549 TP_EC_BACKLIGHT_MAPSW = 0x20,
5350}; 5550};
5351 5551
5552enum tpacpi_brightness_access_mode {
5553 TPACPI_BRGHT_MODE_AUTO = 0, /* Not implemented yet */
5554 TPACPI_BRGHT_MODE_EC, /* EC control */
5555 TPACPI_BRGHT_MODE_UCMS_STEP, /* UCMS step-based control */
5556 TPACPI_BRGHT_MODE_ECNVRAM, /* EC control w/ NVRAM store */
5557 TPACPI_BRGHT_MODE_MAX
5558};
5559
5352static struct backlight_device *ibm_backlight_device; 5560static struct backlight_device *ibm_backlight_device;
5353static int brightness_mode; 5561
5562static enum tpacpi_brightness_access_mode brightness_mode =
5563 TPACPI_BRGHT_MODE_MAX;
5564
5354static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ 5565static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */
5355 5566
5356static struct mutex brightness_mutex; 5567static struct mutex brightness_mutex;
5357 5568
5358/* 5569/* NVRAM brightness access,
5359 * ThinkPads can read brightness from two places: EC 0x31, or 5570 * call with brightness_mutex held! */
5360 * CMOS NVRAM byte 0x5E, bits 0-3. 5571static unsigned int tpacpi_brightness_nvram_get(void)
5361 *
5362 * EC 0x31 has the following layout
5363 * Bit 7: unknown function
5364 * Bit 6: unknown function
5365 * Bit 5: Z: honour scale changes, NZ: ignore scale changes
5366 * Bit 4: must be set to zero to avoid problems
5367 * Bit 3-0: backlight brightness level
5368 *
5369 * brightness_get_raw returns status data in the EC 0x31 layout
5370 */
5371static int brightness_get_raw(int *status)
5372{ 5572{
5373 u8 lec = 0, lcmos = 0, level = 0; 5573 u8 lnvram;
5374 5574
5375 if (brightness_mode & 1) { 5575 lnvram = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS)
5376 if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec)) 5576 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
5377 return -EIO; 5577 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS;
5378 level = lec & TP_EC_BACKLIGHT_LVLMSK; 5578 lnvram &= (tp_features.bright_16levels) ? 0x0f : 0x07;
5379 }; 5579
5380 if (brightness_mode & 2) { 5580 return lnvram;
5381 lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) 5581}
5382 & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) 5582
5383 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; 5583static void tpacpi_brightness_checkpoint_nvram(void)
5384 lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; 5584{
5385 level = lcmos; 5585 u8 lec = 0;
5386 } 5586 u8 b_nvram;
5387 5587
5388 if (brightness_mode == 3) { 5588 if (brightness_mode != TPACPI_BRGHT_MODE_ECNVRAM)
5389 *status = lec; /* Prefer EC, CMOS is just a backing store */ 5589 return;
5390 lec &= TP_EC_BACKLIGHT_LVLMSK; 5590
5391 if (lec == lcmos) 5591 vdbg_printk(TPACPI_DBG_BRGHT,
5392 tp_warned.bright_cmos_ec_unsync = 0; 5592 "trying to checkpoint backlight level to NVRAM...\n");
5393 else { 5593
5394 if (!tp_warned.bright_cmos_ec_unsync) { 5594 if (mutex_lock_killable(&brightness_mutex) < 0)
5395 printk(TPACPI_ERR 5595 return;
5396 "CMOS NVRAM (%u) and EC (%u) do not " 5596
5397 "agree on display brightness level\n", 5597 if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
5398 (unsigned int) lcmos, 5598 goto unlock;
5399 (unsigned int) lec); 5599 lec &= TP_EC_BACKLIGHT_LVLMSK;
5400 tp_warned.bright_cmos_ec_unsync = 1; 5600 b_nvram = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS);
5401 } 5601
5602 if (lec != ((b_nvram & TP_NVRAM_MASK_LEVEL_BRIGHTNESS)
5603 >> TP_NVRAM_POS_LEVEL_BRIGHTNESS)) {
5604 /* NVRAM needs update */
5605 b_nvram &= ~(TP_NVRAM_MASK_LEVEL_BRIGHTNESS <<
5606 TP_NVRAM_POS_LEVEL_BRIGHTNESS);
5607 b_nvram |= lec;
5608 nvram_write_byte(b_nvram, TP_NVRAM_ADDR_BRIGHTNESS);
5609 dbg_printk(TPACPI_DBG_BRGHT,
5610 "updated NVRAM backlight level to %u (0x%02x)\n",
5611 (unsigned int) lec, (unsigned int) b_nvram);
5612 } else
5613 vdbg_printk(TPACPI_DBG_BRGHT,
5614 "NVRAM backlight level already is %u (0x%02x)\n",
5615 (unsigned int) lec, (unsigned int) b_nvram);
5616
5617unlock:
5618 mutex_unlock(&brightness_mutex);
5619}
5620
5621
5622/* call with brightness_mutex held! */
5623static int tpacpi_brightness_get_raw(int *status)
5624{
5625 u8 lec = 0;
5626
5627 switch (brightness_mode) {
5628 case TPACPI_BRGHT_MODE_UCMS_STEP:
5629 *status = tpacpi_brightness_nvram_get();
5630 return 0;
5631 case TPACPI_BRGHT_MODE_EC:
5632 case TPACPI_BRGHT_MODE_ECNVRAM:
5633 if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
5402 return -EIO; 5634 return -EIO;
5403 } 5635 *status = lec;
5404 } else { 5636 return 0;
5405 *status = level; 5637 default:
5638 return -ENXIO;
5406 } 5639 }
5640}
5641
5642/* call with brightness_mutex held! */
5643/* do NOT call with illegal backlight level value */
5644static int tpacpi_brightness_set_ec(unsigned int value)
5645{
5646 u8 lec = 0;
5647
5648 if (unlikely(!acpi_ec_read(TP_EC_BACKLIGHT, &lec)))
5649 return -EIO;
5650
5651 if (unlikely(!acpi_ec_write(TP_EC_BACKLIGHT,
5652 (lec & TP_EC_BACKLIGHT_CMDMSK) |
5653 (value & TP_EC_BACKLIGHT_LVLMSK))))
5654 return -EIO;
5655
5656 return 0;
5657}
5658
5659/* call with brightness_mutex held! */
5660static int tpacpi_brightness_set_ucmsstep(unsigned int value)
5661{
5662 int cmos_cmd, inc;
5663 unsigned int current_value, i;
5664
5665 current_value = tpacpi_brightness_nvram_get();
5666
5667 if (value == current_value)
5668 return 0;
5669
5670 cmos_cmd = (value > current_value) ?
5671 TP_CMOS_BRIGHTNESS_UP :
5672 TP_CMOS_BRIGHTNESS_DOWN;
5673 inc = (value > current_value) ? 1 : -1;
5674
5675 for (i = current_value; i != value; i += inc)
5676 if (issue_thinkpad_cmos_command(cmos_cmd))
5677 return -EIO;
5407 5678
5408 return 0; 5679 return 0;
5409} 5680}
5410 5681
5411/* May return EINTR which can always be mapped to ERESTARTSYS */ 5682/* May return EINTR which can always be mapped to ERESTARTSYS */
5412static int brightness_set(int value) 5683static int brightness_set(unsigned int value)
5413{ 5684{
5414 int cmos_cmd, inc, i, res; 5685 int res;
5415 int current_value;
5416 int command_bits;
5417 5686
5418 if (value > ((tp_features.bright_16levels)? 15 : 7) || 5687 if (value > ((tp_features.bright_16levels)? 15 : 7) ||
5419 value < 0) 5688 value < 0)
5420 return -EINVAL; 5689 return -EINVAL;
5421 5690
5691 vdbg_printk(TPACPI_DBG_BRGHT,
5692 "set backlight level to %d\n", value);
5693
5422 res = mutex_lock_killable(&brightness_mutex); 5694 res = mutex_lock_killable(&brightness_mutex);
5423 if (res < 0) 5695 if (res < 0)
5424 return res; 5696 return res;
5425 5697
5426 res = brightness_get_raw(&current_value); 5698 switch (brightness_mode) {
5427 if (res < 0) 5699 case TPACPI_BRGHT_MODE_EC:
5428 goto errout; 5700 case TPACPI_BRGHT_MODE_ECNVRAM:
5429 5701 res = tpacpi_brightness_set_ec(value);
5430 command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK; 5702 break;
5431 current_value &= TP_EC_BACKLIGHT_LVLMSK; 5703 case TPACPI_BRGHT_MODE_UCMS_STEP:
5432 5704 res = tpacpi_brightness_set_ucmsstep(value);
5433 cmos_cmd = value > current_value ? 5705 break;
5434 TP_CMOS_BRIGHTNESS_UP : 5706 default:
5435 TP_CMOS_BRIGHTNESS_DOWN; 5707 res = -ENXIO;
5436 inc = (value > current_value)? 1 : -1;
5437
5438 res = 0;
5439 for (i = current_value; i != value; i += inc) {
5440 if ((brightness_mode & 2) &&
5441 issue_thinkpad_cmos_command(cmos_cmd)) {
5442 res = -EIO;
5443 goto errout;
5444 }
5445 if ((brightness_mode & 1) &&
5446 !acpi_ec_write(TP_EC_BACKLIGHT,
5447 (i + inc) | command_bits)) {
5448 res = -EIO;
5449 goto errout;;
5450 }
5451 } 5708 }
5452 5709
5453errout:
5454 mutex_unlock(&brightness_mutex); 5710 mutex_unlock(&brightness_mutex);
5455 return res; 5711 return res;
5456} 5712}
@@ -5459,21 +5715,34 @@ errout:
5459 5715
5460static int brightness_update_status(struct backlight_device *bd) 5716static int brightness_update_status(struct backlight_device *bd)
5461{ 5717{
5462 /* it is the backlight class's job (caller) to handle 5718 unsigned int level =
5463 * EINTR and other errors properly */
5464 return brightness_set(
5465 (bd->props.fb_blank == FB_BLANK_UNBLANK && 5719 (bd->props.fb_blank == FB_BLANK_UNBLANK &&
5466 bd->props.power == FB_BLANK_UNBLANK) ? 5720 bd->props.power == FB_BLANK_UNBLANK) ?
5467 bd->props.brightness : 0); 5721 bd->props.brightness : 0;
5722
5723 dbg_printk(TPACPI_DBG_BRGHT,
5724 "backlight: attempt to set level to %d\n",
5725 level);
5726
5727 /* it is the backlight class's job (caller) to handle
5728 * EINTR and other errors properly */
5729 return brightness_set(level);
5468} 5730}
5469 5731
5470static int brightness_get(struct backlight_device *bd) 5732static int brightness_get(struct backlight_device *bd)
5471{ 5733{
5472 int status, res; 5734 int status, res;
5473 5735
5474 res = brightness_get_raw(&status); 5736 res = mutex_lock_killable(&brightness_mutex);
5475 if (res < 0) 5737 if (res < 0)
5476 return 0; /* FIXME: teach backlight about error handling */ 5738 return 0;
5739
5740 res = tpacpi_brightness_get_raw(&status);
5741
5742 mutex_unlock(&brightness_mutex);
5743
5744 if (res < 0)
5745 return 0;
5477 5746
5478 return status & TP_EC_BACKLIGHT_LVLMSK; 5747 return status & TP_EC_BACKLIGHT_LVLMSK;
5479} 5748}
@@ -5523,7 +5792,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
5523 } 5792 }
5524 5793
5525 if (!brightness_enable) { 5794 if (!brightness_enable) {
5526 dbg_printk(TPACPI_DBG_INIT, 5795 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
5527 "brightness support disabled by " 5796 "brightness support disabled by "
5528 "module parameter\n"); 5797 "module parameter\n");
5529 return 1; 5798 return 1;
@@ -5538,20 +5807,38 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
5538 if (b == 16) 5807 if (b == 16)
5539 tp_features.bright_16levels = 1; 5808 tp_features.bright_16levels = 1;
5540 5809
5541 if (!brightness_mode) { 5810 /*
5542 if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) 5811 * Check for module parameter bogosity, note that we
5543 brightness_mode = 2; 5812 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
5544 else 5813 * able to detect "unspecified"
5545 brightness_mode = 3; 5814 */
5815 if (brightness_mode > TPACPI_BRGHT_MODE_MAX)
5816 return -EINVAL;
5546 5817
5547 dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", 5818 /* TPACPI_BRGHT_MODE_AUTO not implemented yet, just use default */
5548 brightness_mode); 5819 if (brightness_mode == TPACPI_BRGHT_MODE_AUTO ||
5549 } 5820 brightness_mode == TPACPI_BRGHT_MODE_MAX) {
5821 if (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) {
5822 /*
5823 * IBM models that define HBRV probably have
5824 * EC-based backlight level control
5825 */
5826 if (acpi_evalf(ec_handle, NULL, "HBRV", "qd"))
5827 /* T40-T43, R50-R52, R50e, R51e, X31-X41 */
5828 brightness_mode = TPACPI_BRGHT_MODE_ECNVRAM;
5829 else
5830 /* all other IBM ThinkPads */
5831 brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
5832 } else
5833 /* All Lenovo ThinkPads */
5834 brightness_mode = TPACPI_BRGHT_MODE_UCMS_STEP;
5550 5835
5551 if (brightness_mode > 3) 5836 dbg_printk(TPACPI_DBG_BRGHT,
5552 return -EINVAL; 5837 "selected brightness_mode=%d\n",
5838 brightness_mode);
5839 }
5553 5840
5554 if (brightness_get_raw(&b) < 0) 5841 if (tpacpi_brightness_get_raw(&b) < 0)
5555 return 1; 5842 return 1;
5556 5843
5557 if (tp_features.bright_16levels) 5844 if (tp_features.bright_16levels)
@@ -5565,7 +5852,8 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
5565 printk(TPACPI_ERR "Could not register backlight device\n"); 5852 printk(TPACPI_ERR "Could not register backlight device\n");
5566 return PTR_ERR(ibm_backlight_device); 5853 return PTR_ERR(ibm_backlight_device);
5567 } 5854 }
5568 vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n"); 5855 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
5856 "brightness is supported\n");
5569 5857
5570 ibm_backlight_device->props.max_brightness = 5858 ibm_backlight_device->props.max_brightness =
5571 (tp_features.bright_16levels)? 15 : 7; 5859 (tp_features.bright_16levels)? 15 : 7;
@@ -5575,13 +5863,25 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
5575 return 0; 5863 return 0;
5576} 5864}
5577 5865
5866static void brightness_suspend(pm_message_t state)
5867{
5868 tpacpi_brightness_checkpoint_nvram();
5869}
5870
5871static void brightness_shutdown(void)
5872{
5873 tpacpi_brightness_checkpoint_nvram();
5874}
5875
5578static void brightness_exit(void) 5876static void brightness_exit(void)
5579{ 5877{
5580 if (ibm_backlight_device) { 5878 if (ibm_backlight_device) {
5581 vdbg_printk(TPACPI_DBG_EXIT, 5879 vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_BRGHT,
5582 "calling backlight_device_unregister()\n"); 5880 "calling backlight_device_unregister()\n");
5583 backlight_device_unregister(ibm_backlight_device); 5881 backlight_device_unregister(ibm_backlight_device);
5584 } 5882 }
5883
5884 tpacpi_brightness_checkpoint_nvram();
5585} 5885}
5586 5886
5587static int brightness_read(char *p) 5887static int brightness_read(char *p)
@@ -5628,6 +5928,9 @@ static int brightness_write(char *buf)
5628 return -EINVAL; 5928 return -EINVAL;
5629 } 5929 }
5630 5930
5931 tpacpi_disclose_usertask("procfs brightness",
5932 "set level to %d\n", level);
5933
5631 /* 5934 /*
5632 * Now we know what the final level should be, so we try to set it. 5935 * Now we know what the final level should be, so we try to set it.
5633 * Doing it this way makes the syscall restartable in case of EINTR 5936 * Doing it this way makes the syscall restartable in case of EINTR
@@ -5641,6 +5944,8 @@ static struct ibm_struct brightness_driver_data = {
5641 .read = brightness_read, 5944 .read = brightness_read,
5642 .write = brightness_write, 5945 .write = brightness_write,
5643 .exit = brightness_exit, 5946 .exit = brightness_exit,
5947 .suspend = brightness_suspend,
5948 .shutdown = brightness_shutdown,
5644}; 5949};
5645 5950
5646/************************************************************************* 5951/*************************************************************************
@@ -6086,6 +6391,9 @@ static int fan_set_level(int level)
6086 default: 6391 default:
6087 return -ENXIO; 6392 return -ENXIO;
6088 } 6393 }
6394
6395 vdbg_printk(TPACPI_DBG_FAN,
6396 "fan control: set fan control register to 0x%02x\n", level);
6089 return 0; 6397 return 0;
6090} 6398}
6091 6399
@@ -6163,6 +6471,11 @@ static int fan_set_enable(void)
6163 } 6471 }
6164 6472
6165 mutex_unlock(&fan_mutex); 6473 mutex_unlock(&fan_mutex);
6474
6475 if (!rc)
6476 vdbg_printk(TPACPI_DBG_FAN,
6477 "fan control: set fan control register to 0x%02x\n",
6478 s);
6166 return rc; 6479 return rc;
6167} 6480}
6168 6481
@@ -6199,6 +6512,9 @@ static int fan_set_disable(void)
6199 rc = -ENXIO; 6512 rc = -ENXIO;
6200 } 6513 }
6201 6514
6515 if (!rc)
6516 vdbg_printk(TPACPI_DBG_FAN,
6517 "fan control: set fan control register to 0\n");
6202 6518
6203 mutex_unlock(&fan_mutex); 6519 mutex_unlock(&fan_mutex);
6204 return rc; 6520 return rc;
@@ -6327,6 +6643,9 @@ static ssize_t fan_pwm1_enable_store(struct device *dev,
6327 if (parse_strtoul(buf, 2, &t)) 6643 if (parse_strtoul(buf, 2, &t))
6328 return -EINVAL; 6644 return -EINVAL;
6329 6645
6646 tpacpi_disclose_usertask("hwmon pwm1_enable",
6647 "set fan mode to %lu\n", t);
6648
6330 switch (t) { 6649 switch (t) {
6331 case 0: 6650 case 0:
6332 level = TP_EC_FAN_FULLSPEED; 6651 level = TP_EC_FAN_FULLSPEED;
@@ -6392,6 +6711,9 @@ static ssize_t fan_pwm1_store(struct device *dev,
6392 if (parse_strtoul(buf, 255, &s)) 6711 if (parse_strtoul(buf, 255, &s))
6393 return -EINVAL; 6712 return -EINVAL;
6394 6713
6714 tpacpi_disclose_usertask("hwmon pwm1",
6715 "set fan speed to %lu\n", s);
6716
6395 /* scale down from 0-255 to 0-7 */ 6717 /* scale down from 0-255 to 0-7 */
6396 newlevel = (s >> 5) & 0x07; 6718 newlevel = (s >> 5) & 0x07;
6397 6719
@@ -6458,6 +6780,8 @@ static ssize_t fan_fan_watchdog_store(struct device_driver *drv,
6458 fan_watchdog_maxinterval = t; 6780 fan_watchdog_maxinterval = t;
6459 fan_watchdog_reset(); 6781 fan_watchdog_reset();
6460 6782
6783 tpacpi_disclose_usertask("fan_watchdog", "set to %lu\n", t);
6784
6461 return count; 6785 return count;
6462} 6786}
6463 6787
@@ -6479,7 +6803,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6479{ 6803{
6480 int rc; 6804 int rc;
6481 6805
6482 vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); 6806 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
6807 "initializing fan subdriver\n");
6483 6808
6484 mutex_init(&fan_mutex); 6809 mutex_init(&fan_mutex);
6485 fan_status_access_mode = TPACPI_FAN_NONE; 6810 fan_status_access_mode = TPACPI_FAN_NONE;
@@ -6538,7 +6863,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6538 } 6863 }
6539 } 6864 }
6540 6865
6541 vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n", 6866 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
6867 "fan is %s, modes %d, %d\n",
6542 str_supported(fan_status_access_mode != TPACPI_FAN_NONE || 6868 str_supported(fan_status_access_mode != TPACPI_FAN_NONE ||
6543 fan_control_access_mode != TPACPI_FAN_WR_NONE), 6869 fan_control_access_mode != TPACPI_FAN_WR_NONE),
6544 fan_status_access_mode, fan_control_access_mode); 6870 fan_status_access_mode, fan_control_access_mode);
@@ -6547,7 +6873,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6547 if (!fan_control_allowed) { 6873 if (!fan_control_allowed) {
6548 fan_control_access_mode = TPACPI_FAN_WR_NONE; 6874 fan_control_access_mode = TPACPI_FAN_WR_NONE;
6549 fan_control_commands = 0; 6875 fan_control_commands = 0;
6550 dbg_printk(TPACPI_DBG_INIT, 6876 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
6551 "fan control features disabled by parameter\n"); 6877 "fan control features disabled by parameter\n");
6552 } 6878 }
6553 6879
@@ -6576,7 +6902,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6576 6902
6577static void fan_exit(void) 6903static void fan_exit(void)
6578{ 6904{
6579 vdbg_printk(TPACPI_DBG_EXIT, 6905 vdbg_printk(TPACPI_DBG_EXIT | TPACPI_DBG_FAN,
6580 "cancelling any pending fan watchdog tasks\n"); 6906 "cancelling any pending fan watchdog tasks\n");
6581 6907
6582 /* FIXME: can we really do this unconditionally? */ 6908 /* FIXME: can we really do this unconditionally? */
@@ -6757,6 +7083,9 @@ static int fan_write_cmd_level(const char *cmd, int *rc)
6757 if (*rc == -ENXIO) 7083 if (*rc == -ENXIO)
6758 printk(TPACPI_ERR "level command accepted for unsupported " 7084 printk(TPACPI_ERR "level command accepted for unsupported "
6759 "access mode %d", fan_control_access_mode); 7085 "access mode %d", fan_control_access_mode);
7086 else if (!*rc)
7087 tpacpi_disclose_usertask("procfs fan",
7088 "set level to %d\n", level);
6760 7089
6761 return 1; 7090 return 1;
6762} 7091}
@@ -6770,6 +7099,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc)
6770 if (*rc == -ENXIO) 7099 if (*rc == -ENXIO)
6771 printk(TPACPI_ERR "enable command accepted for unsupported " 7100 printk(TPACPI_ERR "enable command accepted for unsupported "
6772 "access mode %d", fan_control_access_mode); 7101 "access mode %d", fan_control_access_mode);
7102 else if (!*rc)
7103 tpacpi_disclose_usertask("procfs fan", "enable\n");
6773 7104
6774 return 1; 7105 return 1;
6775} 7106}
@@ -6783,6 +7114,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc)
6783 if (*rc == -ENXIO) 7114 if (*rc == -ENXIO)
6784 printk(TPACPI_ERR "disable command accepted for unsupported " 7115 printk(TPACPI_ERR "disable command accepted for unsupported "
6785 "access mode %d", fan_control_access_mode); 7116 "access mode %d", fan_control_access_mode);
7117 else if (!*rc)
7118 tpacpi_disclose_usertask("procfs fan", "disable\n");
6786 7119
6787 return 1; 7120 return 1;
6788} 7121}
@@ -6801,6 +7134,9 @@ static int fan_write_cmd_speed(const char *cmd, int *rc)
6801 if (*rc == -ENXIO) 7134 if (*rc == -ENXIO)
6802 printk(TPACPI_ERR "speed command accepted for unsupported " 7135 printk(TPACPI_ERR "speed command accepted for unsupported "
6803 "access mode %d", fan_control_access_mode); 7136 "access mode %d", fan_control_access_mode);
7137 else if (!*rc)
7138 tpacpi_disclose_usertask("procfs fan",
7139 "set speed to %d\n", speed);
6804 7140
6805 return 1; 7141 return 1;
6806} 7142}
@@ -6814,8 +7150,12 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc)
6814 7150
6815 if (interval < 0 || interval > 120) 7151 if (interval < 0 || interval > 120)
6816 *rc = -EINVAL; 7152 *rc = -EINVAL;
6817 else 7153 else {
6818 fan_watchdog_maxinterval = interval; 7154 fan_watchdog_maxinterval = interval;
7155 tpacpi_disclose_usertask("procfs fan",
7156 "set watchdog timer to %d\n",
7157 interval);
7158 }
6819 7159
6820 return 1; 7160 return 1;
6821} 7161}
@@ -7243,10 +7583,10 @@ module_param_named(fan_control, fan_control_allowed, bool, 0);
7243MODULE_PARM_DESC(fan_control, 7583MODULE_PARM_DESC(fan_control,
7244 "Enables setting fan parameters features when true"); 7584 "Enables setting fan parameters features when true");
7245 7585
7246module_param_named(brightness_mode, brightness_mode, int, 0); 7586module_param_named(brightness_mode, brightness_mode, uint, 0);
7247MODULE_PARM_DESC(brightness_mode, 7587MODULE_PARM_DESC(brightness_mode,
7248 "Selects brightness control strategy: " 7588 "Selects brightness control strategy: "
7249 "0=auto, 1=EC, 2=CMOS, 3=both"); 7589 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
7250 7590
7251module_param(brightness_enable, uint, 0); 7591module_param(brightness_enable, uint, 0);
7252MODULE_PARM_DESC(brightness_enable, 7592MODULE_PARM_DESC(brightness_enable,
@@ -7515,9 +7855,6 @@ static int __init thinkpad_acpi_module_init(void)
7515 return 0; 7855 return 0;
7516} 7856}
7517 7857
7518/* Please remove this in year 2009 */
7519MODULE_ALIAS("ibm_acpi");
7520
7521MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); 7858MODULE_ALIAS(TPACPI_DRVR_SHORTNAME);
7522 7859
7523/* 7860/*