aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86')
-rw-r--r--drivers/platform/x86/Kconfig35
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c4
-rw-r--r--drivers/platform/x86/acerhdf.c602
-rw-r--r--drivers/platform/x86/asus-laptop.c111
-rw-r--r--drivers/platform/x86/asus_acpi.c30
-rw-r--r--drivers/platform/x86/dell-wmi.c56
-rw-r--r--drivers/platform/x86/eeepc-laptop.c500
-rw-r--r--drivers/platform/x86/hp-wmi.c87
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c425
10 files changed, 1556 insertions, 295 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index c682ac536415..46dad12f952f 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -34,10 +34,27 @@ config ACER_WMI
34 If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M 34 If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M
35 here. 35 here.
36 36
37config ACERHDF
38 tristate "Acer Aspire One temperature and fan driver"
39 depends on THERMAL && THERMAL_HWMON && ACPI
40 ---help---
41 This is a driver for Acer Aspire One netbooks. It allows to access
42 the temperature sensor and to control the fan.
43
44 After loading this driver the BIOS is still in control of the fan.
45 To let the kernel handle the fan, do:
46 echo -n enabled > /sys/class/thermal/thermal_zone0/mode
47
48 For more information about this driver see
49 <http://piie.net/files/acerhdf_README.txt>
50
51 If you have an Acer Aspire One netbook, say Y or M
52 here.
53
37config ASUS_LAPTOP 54config ASUS_LAPTOP
38 tristate "Asus Laptop Extras (EXPERIMENTAL)" 55 tristate "Asus Laptop Extras"
39 depends on ACPI 56 depends on ACPI
40 depends on EXPERIMENTAL && !ACPI_ASUS 57 depends on !ACPI_ASUS
41 select LEDS_CLASS 58 select LEDS_CLASS
42 select NEW_LEDS 59 select NEW_LEDS
43 select BACKLIGHT_CLASS_DEVICE 60 select BACKLIGHT_CLASS_DEVICE
@@ -45,12 +62,12 @@ config ASUS_LAPTOP
45 ---help--- 62 ---help---
46 This is the new Linux driver for Asus laptops. It may also support some 63 This is the new Linux driver for Asus laptops. It may also support some
47 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate 64 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
48 standard ACPI events that go through /proc/acpi/events. It also adds 65 standard ACPI events and input events. It also adds
49 support for video output switching, LCD backlight control, Bluetooth and 66 support for video output switching, LCD backlight control, Bluetooth and
50 Wlan control, and most importantly, allows you to blink those fancy LEDs. 67 Wlan control, and most importantly, allows you to blink those fancy LEDs.
51 68
52 For more information and a userspace daemon for handling the extra 69 For more information and a userspace daemon for handling the extra
53 buttons see <http://acpi4asus.sf.net/>. 70 buttons see <http://acpi4asus.sf.net>.
54 71
55 If you have an ACPI-compatible ASUS laptop, say Y or M here. 72 If you have an ACPI-compatible ASUS laptop, say Y or M here.
56 73
@@ -338,11 +355,15 @@ config EEEPC_LAPTOP
338 depends on INPUT 355 depends on INPUT
339 depends on EXPERIMENTAL 356 depends on EXPERIMENTAL
340 depends on RFKILL || RFKILL = n 357 depends on RFKILL || RFKILL = n
358 depends on HOTPLUG_PCI
341 select BACKLIGHT_CLASS_DEVICE 359 select BACKLIGHT_CLASS_DEVICE
342 select HWMON 360 select HWMON
343 ---help--- 361 ---help---
344 This driver supports the Fn-Fx keys on Eee PC laptops. 362 This driver supports the Fn-Fx keys on Eee PC laptops.
345 It also adds the ability to switch camera/wlan on/off. 363
364 It also gives access to some extra laptop functionalities like
365 Bluetooth, backlight and allows powering on/off some other
366 devices.
346 367
347 If you have an Eee PC laptop, say Y or M here. 368 If you have an Eee PC laptop, say Y or M here.
348 369
@@ -369,7 +390,7 @@ config ACPI_WMI
369 any ACPI-WMI devices. 390 any ACPI-WMI devices.
370 391
371config ACPI_ASUS 392config ACPI_ASUS
372 tristate "ASUS/Medion Laptop Extras" 393 tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
373 depends on ACPI 394 depends on ACPI
374 select BACKLIGHT_CLASS_DEVICE 395 select BACKLIGHT_CLASS_DEVICE
375 ---help--- 396 ---help---
@@ -390,7 +411,7 @@ config ACPI_ASUS
390 parameters. 411 parameters.
391 412
392 More information and a userspace daemon for handling the extra buttons 413 More information and a userspace daemon for handling the extra buttons
393 at <http://sourceforge.net/projects/acpi4asus/>. 414 at <http://acpi4asus.sf.net>.
394 415
395 If you have an ACPI-compatible ASUS laptop, say Y or M here. This 416 If you have an ACPI-compatible ASUS laptop, say Y or M here. This
396 driver is still under development, so if your laptop is unsupported or 417 driver is still under development, so if your laptop is unsupported or
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index e40c7bd1b87e..641b8bfa5538 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -9,6 +9,7 @@ obj-$(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_DELL_WMI) += dell-wmi.o
11obj-$(CONFIG_ACER_WMI) += acer-wmi.o 11obj-$(CONFIG_ACER_WMI) += acer-wmi.o
12obj-$(CONFIG_ACERHDF) += acerhdf.o
12obj-$(CONFIG_HP_WMI) += hp-wmi.o 13obj-$(CONFIG_HP_WMI) += hp-wmi.o
13obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o 14obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o
14obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 15obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 09a503e5da6a..be2fd6f91639 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -958,12 +958,12 @@ static void acer_rfkill_update(struct work_struct *ignored)
958 958
959 status = get_u32(&state, ACER_CAP_WIRELESS); 959 status = get_u32(&state, ACER_CAP_WIRELESS);
960 if (ACPI_SUCCESS(status)) 960 if (ACPI_SUCCESS(status))
961 rfkill_set_sw_state(wireless_rfkill, !!state); 961 rfkill_set_sw_state(wireless_rfkill, !state);
962 962
963 if (has_cap(ACER_CAP_BLUETOOTH)) { 963 if (has_cap(ACER_CAP_BLUETOOTH)) {
964 status = get_u32(&state, ACER_CAP_BLUETOOTH); 964 status = get_u32(&state, ACER_CAP_BLUETOOTH);
965 if (ACPI_SUCCESS(status)) 965 if (ACPI_SUCCESS(status))
966 rfkill_set_sw_state(bluetooth_rfkill, !!state); 966 rfkill_set_sw_state(bluetooth_rfkill, !state);
967 } 967 }
968 968
969 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ)); 969 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
new file mode 100644
index 000000000000..bdfee177eefb
--- /dev/null
+++ b/drivers/platform/x86/acerhdf.c
@@ -0,0 +1,602 @@
1/*
2 * acerhdf - A driver which monitors the temperature
3 * of the aspire one netbook, turns on/off the fan
4 * as soon as the upper/lower threshold is reached.
5 *
6 * (C) 2009 - Peter Feuerer peter (a) piie.net
7 * http://piie.net
8 * 2009 Borislav Petkov <petkovbb@gmail.com>
9 *
10 * Inspired by and many thanks to:
11 * o acerfand - Rachel Greenham
12 * o acer_ec.pl - Michael Kurz michi.kurz (at) googlemail.com
13 * - Petr Tomasek tomasek (#) etf,cuni,cz
14 * - Carlos Corbacho cathectic (at) gmail.com
15 * o lkml - Matthew Garrett
16 * - Borislav Petkov
17 * - Andreas Mohr
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 */
33
34#define pr_fmt(fmt) "acerhdf: " fmt
35
36#include <linux/kernel.h>
37#include <linux/module.h>
38#include <linux/fs.h>
39#include <linux/dmi.h>
40#include <acpi/acpi_drivers.h>
41#include <linux/sched.h>
42#include <linux/thermal.h>
43#include <linux/platform_device.h>
44
45/*
46 * The driver is started with "kernel mode off" by default. That means, the BIOS
47 * is still in control of the fan. In this mode the driver allows to read the
48 * temperature of the cpu and a userspace tool may take over control of the fan.
49 * If the driver is switched to "kernel mode" (e.g. via module parameter) the
50 * driver is in full control of the fan. If you want the module to be started in
51 * kernel mode by default, define the following:
52 */
53#undef START_IN_KERNEL_MODE
54
55#define DRV_VER "0.5.13"
56
57/*
58 * According to the Atom N270 datasheet,
59 * (http://download.intel.com/design/processor/datashts/320032.pdf) the
60 * CPU's optimal operating limits denoted in junction temperature as
61 * measured by the on-die thermal monitor are within 0 <= Tj <= 90. So,
62 * assume 89°C is critical temperature.
63 */
64#define ACERHDF_TEMP_CRIT 89
65#define ACERHDF_FAN_OFF 0
66#define ACERHDF_FAN_AUTO 1
67
68/*
69 * No matter what value the user puts into the fanon variable, turn on the fan
70 * at 80 degree Celsius to prevent hardware damage
71 */
72#define ACERHDF_MAX_FANON 80
73
74/*
75 * Maximum interval between two temperature checks is 15 seconds, as the die
76 * can get hot really fast under heavy load (plus we shouldn't forget about
77 * possible impact of _external_ aggressive sources such as heaters, sun etc.)
78 */
79#define ACERHDF_MAX_INTERVAL 15
80
81#ifdef START_IN_KERNEL_MODE
82static int kernelmode = 1;
83#else
84static int kernelmode;
85#endif
86
87static unsigned int interval = 10;
88static unsigned int fanon = 63;
89static unsigned int fanoff = 58;
90static unsigned int verbose;
91static unsigned int fanstate = ACERHDF_FAN_AUTO;
92static char force_bios[16];
93static unsigned int prev_interval;
94struct thermal_zone_device *thz_dev;
95struct thermal_cooling_device *cl_dev;
96struct platform_device *acerhdf_dev;
97
98module_param(kernelmode, uint, 0);
99MODULE_PARM_DESC(kernelmode, "Kernel mode fan control on / off");
100module_param(interval, uint, 0600);
101MODULE_PARM_DESC(interval, "Polling interval of temperature check");
102module_param(fanon, uint, 0600);
103MODULE_PARM_DESC(fanon, "Turn the fan on above this temperature");
104module_param(fanoff, uint, 0600);
105MODULE_PARM_DESC(fanoff, "Turn the fan off below this temperature");
106module_param(verbose, uint, 0600);
107MODULE_PARM_DESC(verbose, "Enable verbose dmesg output");
108module_param_string(force_bios, force_bios, 16, 0);
109MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check");
110
111/* BIOS settings */
112struct bios_settings_t {
113 const char *vendor;
114 const char *version;
115 unsigned char fanreg;
116 unsigned char tempreg;
117 unsigned char fancmd[2]; /* fan off and auto commands */
118};
119
120/* Register addresses and values for different BIOS versions */
121static const struct bios_settings_t bios_tbl[] = {
122 {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} },
123 {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} },
124 {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} },
125 {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} },
126 {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} },
127 {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} },
128 {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} },
129 {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} },
130 {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
131 {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
132 {"", "", 0, 0, {0, 0} }
133};
134
135static const struct bios_settings_t *bios_cfg __read_mostly;
136
137
138static int acerhdf_get_temp(int *temp)
139{
140 u8 read_temp;
141
142 if (ec_read(bios_cfg->tempreg, &read_temp))
143 return -EINVAL;
144
145 *temp = read_temp;
146
147 return 0;
148}
149
150static int acerhdf_get_fanstate(int *state)
151{
152 u8 fan;
153 bool tmp;
154
155 if (ec_read(bios_cfg->fanreg, &fan))
156 return -EINVAL;
157
158 tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]);
159 *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO;
160
161 return 0;
162}
163
164static void acerhdf_change_fanstate(int state)
165{
166 unsigned char cmd;
167
168 if (verbose)
169 pr_notice("fan %s\n", (state == ACERHDF_FAN_OFF) ?
170 "OFF" : "ON");
171
172 if ((state != ACERHDF_FAN_OFF) && (state != ACERHDF_FAN_AUTO)) {
173 pr_err("invalid fan state %d requested, setting to auto!\n",
174 state);
175 state = ACERHDF_FAN_AUTO;
176 }
177
178 cmd = bios_cfg->fancmd[state];
179 fanstate = state;
180
181 ec_write(bios_cfg->fanreg, cmd);
182}
183
184static void acerhdf_check_param(struct thermal_zone_device *thermal)
185{
186 if (fanon > ACERHDF_MAX_FANON) {
187 pr_err("fanon temperature too high, set to %d\n",
188 ACERHDF_MAX_FANON);
189 fanon = ACERHDF_MAX_FANON;
190 }
191
192 if (kernelmode && prev_interval != interval) {
193 if (interval > ACERHDF_MAX_INTERVAL) {
194 pr_err("interval too high, set to %d\n",
195 ACERHDF_MAX_INTERVAL);
196 interval = ACERHDF_MAX_INTERVAL;
197 }
198 if (verbose)
199 pr_notice("interval changed to: %d\n",
200 interval);
201 thermal->polling_delay = interval*1000;
202 prev_interval = interval;
203 }
204}
205
206/*
207 * This is the thermal zone callback which does the delayed polling of the fan
208 * state. We do check /sysfs-originating settings here in acerhdf_check_param()
209 * as late as the polling interval is since we can't do that in the respective
210 * accessors of the module parameters.
211 */
212static int acerhdf_get_ec_temp(struct thermal_zone_device *thermal,
213 unsigned long *t)
214{
215 int temp, err = 0;
216
217 acerhdf_check_param(thermal);
218
219 err = acerhdf_get_temp(&temp);
220 if (err)
221 return err;
222
223 if (verbose)
224 pr_notice("temp %d\n", temp);
225
226 *t = temp;
227 return 0;
228}
229
230static int acerhdf_bind(struct thermal_zone_device *thermal,
231 struct thermal_cooling_device *cdev)
232{
233 /* if the cooling device is the one from acerhdf bind it */
234 if (cdev != cl_dev)
235 return 0;
236
237 if (thermal_zone_bind_cooling_device(thermal, 0, cdev)) {
238 pr_err("error binding cooling dev\n");
239 return -EINVAL;
240 }
241 return 0;
242}
243
244static int acerhdf_unbind(struct thermal_zone_device *thermal,
245 struct thermal_cooling_device *cdev)
246{
247 if (cdev != cl_dev)
248 return 0;
249
250 if (thermal_zone_unbind_cooling_device(thermal, 0, cdev)) {
251 pr_err("error unbinding cooling dev\n");
252 return -EINVAL;
253 }
254 return 0;
255}
256
257static inline void acerhdf_revert_to_bios_mode(void)
258{
259 acerhdf_change_fanstate(ACERHDF_FAN_AUTO);
260 kernelmode = 0;
261 if (thz_dev)
262 thz_dev->polling_delay = 0;
263 pr_notice("kernel mode fan control OFF\n");
264}
265static inline void acerhdf_enable_kernelmode(void)
266{
267 kernelmode = 1;
268
269 thz_dev->polling_delay = interval*1000;
270 thermal_zone_device_update(thz_dev);
271 pr_notice("kernel mode fan control ON\n");
272}
273
274static int acerhdf_get_mode(struct thermal_zone_device *thermal,
275 enum thermal_device_mode *mode)
276{
277 if (verbose)
278 pr_notice("kernel mode fan control %d\n", kernelmode);
279
280 *mode = (kernelmode) ? THERMAL_DEVICE_ENABLED
281 : THERMAL_DEVICE_DISABLED;
282
283 return 0;
284}
285
286/*
287 * set operation mode;
288 * enabled: the thermal layer of the kernel takes care about
289 * the temperature and the fan.
290 * disabled: the BIOS takes control of the fan.
291 */
292static int acerhdf_set_mode(struct thermal_zone_device *thermal,
293 enum thermal_device_mode mode)
294{
295 if (mode == THERMAL_DEVICE_DISABLED && kernelmode)
296 acerhdf_revert_to_bios_mode();
297 else if (mode == THERMAL_DEVICE_ENABLED && !kernelmode)
298 acerhdf_enable_kernelmode();
299
300 return 0;
301}
302
303static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip,
304 enum thermal_trip_type *type)
305{
306 if (trip == 0)
307 *type = THERMAL_TRIP_ACTIVE;
308
309 return 0;
310}
311
312static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
313 unsigned long *temp)
314{
315 if (trip == 0)
316 *temp = fanon;
317
318 return 0;
319}
320
321static int acerhdf_get_crit_temp(struct thermal_zone_device *thermal,
322 unsigned long *temperature)
323{
324 *temperature = ACERHDF_TEMP_CRIT;
325 return 0;
326}
327
328/* bind callback functions to thermalzone */
329struct thermal_zone_device_ops acerhdf_dev_ops = {
330 .bind = acerhdf_bind,
331 .unbind = acerhdf_unbind,
332 .get_temp = acerhdf_get_ec_temp,
333 .get_mode = acerhdf_get_mode,
334 .set_mode = acerhdf_set_mode,
335 .get_trip_type = acerhdf_get_trip_type,
336 .get_trip_temp = acerhdf_get_trip_temp,
337 .get_crit_temp = acerhdf_get_crit_temp,
338};
339
340
341/*
342 * cooling device callback functions
343 * get maximal fan cooling state
344 */
345static int acerhdf_get_max_state(struct thermal_cooling_device *cdev,
346 unsigned long *state)
347{
348 *state = 1;
349
350 return 0;
351}
352
353static int acerhdf_get_cur_state(struct thermal_cooling_device *cdev,
354 unsigned long *state)
355{
356 int err = 0, tmp;
357
358 err = acerhdf_get_fanstate(&tmp);
359 if (err)
360 return err;
361
362 *state = (tmp == ACERHDF_FAN_AUTO) ? 1 : 0;
363 return 0;
364}
365
366/* change current fan state - is overwritten when running in kernel mode */
367static int acerhdf_set_cur_state(struct thermal_cooling_device *cdev,
368 unsigned long state)
369{
370 int cur_temp, cur_state, err = 0;
371
372 if (!kernelmode)
373 return 0;
374
375 err = acerhdf_get_temp(&cur_temp);
376 if (err) {
377 pr_err("error reading temperature, hand off control to BIOS\n");
378 goto err_out;
379 }
380
381 err = acerhdf_get_fanstate(&cur_state);
382 if (err) {
383 pr_err("error reading fan state, hand off control to BIOS\n");
384 goto err_out;
385 }
386
387 if (state == 0) {
388 /* turn fan off only if below fanoff temperature */
389 if ((cur_state == ACERHDF_FAN_AUTO) &&
390 (cur_temp < fanoff))
391 acerhdf_change_fanstate(ACERHDF_FAN_OFF);
392 } else {
393 if (cur_state == ACERHDF_FAN_OFF)
394 acerhdf_change_fanstate(ACERHDF_FAN_AUTO);
395 }
396 return 0;
397
398err_out:
399 acerhdf_revert_to_bios_mode();
400 return -EINVAL;
401}
402
403/* bind fan callbacks to fan device */
404struct thermal_cooling_device_ops acerhdf_cooling_ops = {
405 .get_max_state = acerhdf_get_max_state,
406 .get_cur_state = acerhdf_get_cur_state,
407 .set_cur_state = acerhdf_set_cur_state,
408};
409
410/* suspend / resume functionality */
411static int acerhdf_suspend(struct platform_device *dev, pm_message_t state)
412{
413 if (kernelmode)
414 acerhdf_change_fanstate(ACERHDF_FAN_AUTO);
415
416 if (verbose)
417 pr_notice("going suspend\n");
418
419 return 0;
420}
421
422static int acerhdf_resume(struct platform_device *device)
423{
424 if (verbose)
425 pr_notice("resuming\n");
426
427 return 0;
428}
429
430static int __devinit acerhdf_probe(struct platform_device *device)
431{
432 return 0;
433}
434
435static int acerhdf_remove(struct platform_device *device)
436{
437 return 0;
438}
439
440struct platform_driver acerhdf_drv = {
441 .driver = {
442 .name = "acerhdf",
443 .owner = THIS_MODULE,
444 },
445 .probe = acerhdf_probe,
446 .remove = acerhdf_remove,
447 .suspend = acerhdf_suspend,
448 .resume = acerhdf_resume,
449};
450
451
452/* check hardware */
453static int acerhdf_check_hardware(void)
454{
455 char const *vendor, *version, *product;
456 int i;
457
458 /* get BIOS data */
459 vendor = dmi_get_system_info(DMI_SYS_VENDOR);
460 version = dmi_get_system_info(DMI_BIOS_VERSION);
461 product = dmi_get_system_info(DMI_PRODUCT_NAME);
462
463 pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER);
464
465 if (!force_bios[0]) {
466 if (strncmp(product, "AO", 2)) {
467 pr_err("no Aspire One hardware found\n");
468 return -EINVAL;
469 }
470 } else {
471 pr_info("forcing BIOS version: %s\n", version);
472 version = force_bios;
473 kernelmode = 0;
474 }
475
476 if (verbose)
477 pr_info("BIOS info: %s %s, product: %s\n",
478 vendor, version, product);
479
480 /* search BIOS version and vendor in BIOS settings table */
481 for (i = 0; bios_tbl[i].version[0]; i++) {
482 if (!strcmp(bios_tbl[i].vendor, vendor) &&
483 !strcmp(bios_tbl[i].version, version)) {
484 bios_cfg = &bios_tbl[i];
485 break;
486 }
487 }
488
489 if (!bios_cfg) {
490 pr_err("unknown (unsupported) BIOS version %s/%s, "
491 "please report, aborting!\n", vendor, version);
492 return -EINVAL;
493 }
494
495 /*
496 * if started with kernel mode off, prevent the kernel from switching
497 * off the fan
498 */
499 if (!kernelmode) {
500 pr_notice("Fan control off, to enable do:\n");
501 pr_notice("echo -n \"enabled\" > "
502 "/sys/class/thermal/thermal_zone0/mode\n");
503 }
504
505 return 0;
506}
507
508static int acerhdf_register_platform(void)
509{
510 int err = 0;
511
512 err = platform_driver_register(&acerhdf_drv);
513 if (err)
514 return err;
515
516 acerhdf_dev = platform_device_alloc("acerhdf", -1);
517 platform_device_add(acerhdf_dev);
518
519 return 0;
520}
521
522static void acerhdf_unregister_platform(void)
523{
524 if (!acerhdf_dev)
525 return;
526
527 platform_device_del(acerhdf_dev);
528 platform_driver_unregister(&acerhdf_drv);
529}
530
531static int acerhdf_register_thermal(void)
532{
533 cl_dev = thermal_cooling_device_register("acerhdf-fan", NULL,
534 &acerhdf_cooling_ops);
535
536 if (IS_ERR(cl_dev))
537 return -EINVAL;
538
539 thz_dev = thermal_zone_device_register("acerhdf", 1, NULL,
540 &acerhdf_dev_ops, 0, 0, 0,
541 (kernelmode) ? interval*1000 : 0);
542 if (IS_ERR(thz_dev))
543 return -EINVAL;
544
545 return 0;
546}
547
548static void acerhdf_unregister_thermal(void)
549{
550 if (cl_dev) {
551 thermal_cooling_device_unregister(cl_dev);
552 cl_dev = NULL;
553 }
554
555 if (thz_dev) {
556 thermal_zone_device_unregister(thz_dev);
557 thz_dev = NULL;
558 }
559}
560
561static int __init acerhdf_init(void)
562{
563 int err = 0;
564
565 err = acerhdf_check_hardware();
566 if (err)
567 goto out_err;
568
569 err = acerhdf_register_platform();
570 if (err)
571 goto err_unreg;
572
573 err = acerhdf_register_thermal();
574 if (err)
575 goto err_unreg;
576
577 return 0;
578
579err_unreg:
580 acerhdf_unregister_thermal();
581 acerhdf_unregister_platform();
582
583out_err:
584 return -ENODEV;
585}
586
587static void __exit acerhdf_exit(void)
588{
589 acerhdf_change_fanstate(ACERHDF_FAN_AUTO);
590 acerhdf_unregister_thermal();
591 acerhdf_unregister_platform();
592}
593
594MODULE_LICENSE("GPL");
595MODULE_AUTHOR("Peter Feuerer");
596MODULE_DESCRIPTION("Aspire One temperature and fan driver");
597MODULE_ALIAS("dmi:*:*Acer*:*:");
598MODULE_ALIAS("dmi:*:*Gateway*:*:");
599MODULE_ALIAS("dmi:*:*Packard Bell*:*:");
600
601module_init(acerhdf_init);
602module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index bfc1a8892a32..db657bbeec90 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -33,6 +33,8 @@
33 * Sam Lin - GPS support 33 * Sam Lin - GPS support
34 */ 34 */
35 35
36#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
37
36#include <linux/kernel.h> 38#include <linux/kernel.h>
37#include <linux/module.h> 39#include <linux/module.h>
38#include <linux/init.h> 40#include <linux/init.h>
@@ -53,9 +55,10 @@
53#define ASUS_HOTK_NAME "Asus Laptop Support" 55#define ASUS_HOTK_NAME "Asus Laptop Support"
54#define ASUS_HOTK_CLASS "hotkey" 56#define ASUS_HOTK_CLASS "hotkey"
55#define ASUS_HOTK_DEVICE_NAME "Hotkey" 57#define ASUS_HOTK_DEVICE_NAME "Hotkey"
56#define ASUS_HOTK_FILE "asus-laptop" 58#define ASUS_HOTK_FILE KBUILD_MODNAME
57#define ASUS_HOTK_PREFIX "\\_SB.ATKD." 59#define ASUS_HOTK_PREFIX "\\_SB.ATKD."
58 60
61
59/* 62/*
60 * Some events we use, same for all Asus 63 * Some events we use, same for all Asus
61 */ 64 */
@@ -207,13 +210,17 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids);
207 210
208static int asus_hotk_add(struct acpi_device *device); 211static int asus_hotk_add(struct acpi_device *device);
209static int asus_hotk_remove(struct acpi_device *device, int type); 212static int asus_hotk_remove(struct acpi_device *device, int type);
213static void asus_hotk_notify(struct acpi_device *device, u32 event);
214
210static struct acpi_driver asus_hotk_driver = { 215static struct acpi_driver asus_hotk_driver = {
211 .name = ASUS_HOTK_NAME, 216 .name = ASUS_HOTK_NAME,
212 .class = ASUS_HOTK_CLASS, 217 .class = ASUS_HOTK_CLASS,
213 .ids = asus_device_ids, 218 .ids = asus_device_ids,
219 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
214 .ops = { 220 .ops = {
215 .add = asus_hotk_add, 221 .add = asus_hotk_add,
216 .remove = asus_hotk_remove, 222 .remove = asus_hotk_remove,
223 .notify = asus_hotk_notify,
217 }, 224 },
218}; 225};
219 226
@@ -323,7 +330,7 @@ static int read_wireless_status(int mask)
323 330
324 rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status); 331 rv = acpi_evaluate_integer(wireless_status_handle, NULL, NULL, &status);
325 if (ACPI_FAILURE(rv)) 332 if (ACPI_FAILURE(rv))
326 printk(ASUS_WARNING "Error reading Wireless status\n"); 333 pr_warning("Error reading Wireless status\n");
327 else 334 else
328 return (status & mask) ? 1 : 0; 335 return (status & mask) ? 1 : 0;
329 336
@@ -337,7 +344,7 @@ static int read_gps_status(void)
337 344
338 rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status); 345 rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
339 if (ACPI_FAILURE(rv)) 346 if (ACPI_FAILURE(rv))
340 printk(ASUS_WARNING "Error reading GPS status\n"); 347 pr_warning("Error reading GPS status\n");
341 else 348 else
342 return status ? 1 : 0; 349 return status ? 1 : 0;
343 350
@@ -377,7 +384,7 @@ static void write_status(acpi_handle handle, int out, int mask)
377 } 384 }
378 385
379 if (write_acpi_int(handle, NULL, out, NULL)) 386 if (write_acpi_int(handle, NULL, out, NULL))
380 printk(ASUS_WARNING " write failed %x\n", mask); 387 pr_warning(" write failed %x\n", mask);
381} 388}
382 389
383/* /sys/class/led handlers */ 390/* /sys/class/led handlers */
@@ -420,7 +427,7 @@ static int set_lcd_state(int value)
420 NULL, NULL, NULL); 427 NULL, NULL, NULL);
421 428
422 if (ACPI_FAILURE(status)) 429 if (ACPI_FAILURE(status))
423 printk(ASUS_WARNING "Error switching LCD\n"); 430 pr_warning("Error switching LCD\n");
424 } 431 }
425 432
426 write_status(NULL, lcd, LCD_ON); 433 write_status(NULL, lcd, LCD_ON);
@@ -444,7 +451,7 @@ static int read_brightness(struct backlight_device *bd)
444 451
445 rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value); 452 rv = acpi_evaluate_integer(brightness_get_handle, NULL, NULL, &value);
446 if (ACPI_FAILURE(rv)) 453 if (ACPI_FAILURE(rv))
447 printk(ASUS_WARNING "Error reading brightness\n"); 454 pr_warning("Error reading brightness\n");
448 455
449 return value; 456 return value;
450} 457}
@@ -457,7 +464,7 @@ static int set_brightness(struct backlight_device *bd, int value)
457 /* 0 <= value <= 15 */ 464 /* 0 <= value <= 15 */
458 465
459 if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { 466 if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) {
460 printk(ASUS_WARNING "Error changing brightness\n"); 467 pr_warning("Error changing brightness\n");
461 ret = -EIO; 468 ret = -EIO;
462 } 469 }
463 470
@@ -587,7 +594,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr,
587 rv = parse_arg(buf, count, &value); 594 rv = parse_arg(buf, count, &value);
588 if (rv > 0) { 595 if (rv > 0) {
589 if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) 596 if (write_acpi_int(ledd_set_handle, NULL, value, NULL))
590 printk(ASUS_WARNING "LED display write failed\n"); 597 pr_warning("LED display write failed\n");
591 else 598 else
592 hotk->ledd_status = (u32) value; 599 hotk->ledd_status = (u32) value;
593 } 600 }
@@ -632,7 +639,7 @@ static void set_display(int value)
632{ 639{
633 /* no sanity check needed for now */ 640 /* no sanity check needed for now */
634 if (write_acpi_int(display_set_handle, NULL, value, NULL)) 641 if (write_acpi_int(display_set_handle, NULL, value, NULL))
635 printk(ASUS_WARNING "Error setting display\n"); 642 pr_warning("Error setting display\n");
636 return; 643 return;
637} 644}
638 645
@@ -647,7 +654,7 @@ static int read_display(void)
647 rv = acpi_evaluate_integer(display_get_handle, NULL, 654 rv = acpi_evaluate_integer(display_get_handle, NULL,
648 NULL, &value); 655 NULL, &value);
649 if (ACPI_FAILURE(rv)) 656 if (ACPI_FAILURE(rv))
650 printk(ASUS_WARNING "Error reading display status\n"); 657 pr_warning("Error reading display status\n");
651 } 658 }
652 659
653 value &= 0x0F; /* needed for some models, shouldn't hurt others */ 660 value &= 0x0F; /* needed for some models, shouldn't hurt others */
@@ -689,7 +696,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr,
689static void set_light_sens_switch(int value) 696static void set_light_sens_switch(int value)
690{ 697{
691 if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) 698 if (write_acpi_int(ls_switch_handle, NULL, value, NULL))
692 printk(ASUS_WARNING "Error setting light sensor switch\n"); 699 pr_warning("Error setting light sensor switch\n");
693 hotk->light_switch = value; 700 hotk->light_switch = value;
694} 701}
695 702
@@ -714,7 +721,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr,
714static void set_light_sens_level(int value) 721static void set_light_sens_level(int value)
715{ 722{
716 if (write_acpi_int(ls_level_handle, NULL, value, NULL)) 723 if (write_acpi_int(ls_level_handle, NULL, value, NULL))
717 printk(ASUS_WARNING "Error setting light sensor level\n"); 724 pr_warning("Error setting light sensor level\n");
718 hotk->light_level = value; 725 hotk->light_level = value;
719} 726}
720 727
@@ -812,7 +819,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
812 return -EINVAL; 819 return -EINVAL;
813} 820}
814 821
815static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) 822static void asus_hotk_notify(struct acpi_device *device, u32 event)
816{ 823{
817 static struct key_entry *key; 824 static struct key_entry *key;
818 u16 count; 825 u16 count;
@@ -975,11 +982,11 @@ static int asus_hotk_get_info(void)
975 */ 982 */
976 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info); 983 status = acpi_get_table(ACPI_SIG_DSDT, 1, &asus_info);
977 if (ACPI_FAILURE(status)) 984 if (ACPI_FAILURE(status))
978 printk(ASUS_WARNING "Couldn't get the DSDT table header\n"); 985 pr_warning("Couldn't get the DSDT table header\n");
979 986
980 /* We have to write 0 on init this far for all ASUS models */ 987 /* We have to write 0 on init this far for all ASUS models */
981 if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { 988 if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
982 printk(ASUS_ERR "Hotkey initialization failed\n"); 989 pr_err("Hotkey initialization failed\n");
983 return -ENODEV; 990 return -ENODEV;
984 } 991 }
985 992
@@ -987,9 +994,9 @@ static int asus_hotk_get_info(void)
987 status = 994 status =
988 acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result); 995 acpi_evaluate_integer(hotk->handle, "BSTS", NULL, &bsts_result);
989 if (ACPI_FAILURE(status)) 996 if (ACPI_FAILURE(status))
990 printk(ASUS_WARNING "Error calling BSTS\n"); 997 pr_warning("Error calling BSTS\n");
991 else if (bsts_result) 998 else if (bsts_result)
992 printk(ASUS_NOTICE "BSTS called, 0x%02x returned\n", 999 pr_notice("BSTS called, 0x%02x returned\n",
993 (uint) bsts_result); 1000 (uint) bsts_result);
994 1001
995 /* This too ... */ 1002 /* This too ... */
@@ -1020,7 +1027,7 @@ static int asus_hotk_get_info(void)
1020 return -ENOMEM; 1027 return -ENOMEM;
1021 1028
1022 if (*string) 1029 if (*string)
1023 printk(ASUS_NOTICE " %s model detected\n", string); 1030 pr_notice(" %s model detected\n", string);
1024 1031
1025 ASUS_HANDLE_INIT(mled_set); 1032 ASUS_HANDLE_INIT(mled_set);
1026 ASUS_HANDLE_INIT(tled_set); 1033 ASUS_HANDLE_INIT(tled_set);
@@ -1077,7 +1084,7 @@ static int asus_input_init(void)
1077 1084
1078 hotk->inputdev = input_allocate_device(); 1085 hotk->inputdev = input_allocate_device();
1079 if (!hotk->inputdev) { 1086 if (!hotk->inputdev) {
1080 printk(ASUS_INFO "Unable to allocate input device\n"); 1087 pr_info("Unable to allocate input device\n");
1081 return 0; 1088 return 0;
1082 } 1089 }
1083 hotk->inputdev->name = "Asus Laptop extra buttons"; 1090 hotk->inputdev->name = "Asus Laptop extra buttons";
@@ -1096,7 +1103,7 @@ static int asus_input_init(void)
1096 } 1103 }
1097 result = input_register_device(hotk->inputdev); 1104 result = input_register_device(hotk->inputdev);
1098 if (result) { 1105 if (result) {
1099 printk(ASUS_INFO "Unable to register input device\n"); 1106 pr_info("Unable to register input device\n");
1100 input_free_device(hotk->inputdev); 1107 input_free_device(hotk->inputdev);
1101 } 1108 }
1102 return result; 1109 return result;
@@ -1113,7 +1120,7 @@ static int asus_hotk_check(void)
1113 if (hotk->device->status.present) { 1120 if (hotk->device->status.present) {
1114 result = asus_hotk_get_info(); 1121 result = asus_hotk_get_info();
1115 } else { 1122 } else {
1116 printk(ASUS_ERR "Hotkey device not present, aborting\n"); 1123 pr_err("Hotkey device not present, aborting\n");
1117 return -EINVAL; 1124 return -EINVAL;
1118 } 1125 }
1119 1126
@@ -1124,13 +1131,12 @@ static int asus_hotk_found;
1124 1131
1125static int asus_hotk_add(struct acpi_device *device) 1132static int asus_hotk_add(struct acpi_device *device)
1126{ 1133{
1127 acpi_status status = AE_OK;
1128 int result; 1134 int result;
1129 1135
1130 if (!device) 1136 if (!device)
1131 return -EINVAL; 1137 return -EINVAL;
1132 1138
1133 printk(ASUS_NOTICE "Asus Laptop Support version %s\n", 1139 pr_notice("Asus Laptop Support version %s\n",
1134 ASUS_LAPTOP_VERSION); 1140 ASUS_LAPTOP_VERSION);
1135 1141
1136 hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL); 1142 hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
@@ -1149,15 +1155,6 @@ static int asus_hotk_add(struct acpi_device *device)
1149 1155
1150 asus_hotk_add_fs(); 1156 asus_hotk_add_fs();
1151 1157
1152 /*
1153 * We install the handler, it will receive the hotk in parameter, so, we
1154 * could add other data to the hotk struct
1155 */
1156 status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY,
1157 asus_hotk_notify, hotk);
1158 if (ACPI_FAILURE(status))
1159 printk(ASUS_ERR "Error installing notify handler\n");
1160
1161 asus_hotk_found = 1; 1158 asus_hotk_found = 1;
1162 1159
1163 /* WLED and BLED are on by default */ 1160 /* WLED and BLED are on by default */
@@ -1198,16 +1195,9 @@ end:
1198 1195
1199static int asus_hotk_remove(struct acpi_device *device, int type) 1196static int asus_hotk_remove(struct acpi_device *device, int type)
1200{ 1197{
1201 acpi_status status = 0;
1202
1203 if (!device || !acpi_driver_data(device)) 1198 if (!device || !acpi_driver_data(device))
1204 return -EINVAL; 1199 return -EINVAL;
1205 1200
1206 status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY,
1207 asus_hotk_notify);
1208 if (ACPI_FAILURE(status))
1209 printk(ASUS_ERR "Error removing notify handler\n");
1210
1211 kfree(hotk->name); 1201 kfree(hotk->name);
1212 kfree(hotk); 1202 kfree(hotk);
1213 1203
@@ -1260,8 +1250,7 @@ static int asus_backlight_init(struct device *dev)
1260 bd = backlight_device_register(ASUS_HOTK_FILE, dev, 1250 bd = backlight_device_register(ASUS_HOTK_FILE, dev,
1261 NULL, &asusbl_ops); 1251 NULL, &asusbl_ops);
1262 if (IS_ERR(bd)) { 1252 if (IS_ERR(bd)) {
1263 printk(ASUS_ERR 1253 pr_err("Could not register asus backlight device\n");
1264 "Could not register asus backlight device\n");
1265 asus_backlight_device = NULL; 1254 asus_backlight_device = NULL;
1266 return PTR_ERR(bd); 1255 return PTR_ERR(bd);
1267 } 1256 }
@@ -1334,7 +1323,6 @@ out:
1334 1323
1335static int __init asus_laptop_init(void) 1324static int __init asus_laptop_init(void)
1336{ 1325{
1337 struct device *dev;
1338 int result; 1326 int result;
1339 1327
1340 if (acpi_disabled) 1328 if (acpi_disabled)
@@ -1356,24 +1344,10 @@ static int __init asus_laptop_init(void)
1356 return -ENODEV; 1344 return -ENODEV;
1357 } 1345 }
1358 1346
1359 dev = acpi_get_physical_device(hotk->device->handle);
1360
1361 if (!acpi_video_backlight_support()) {
1362 result = asus_backlight_init(dev);
1363 if (result)
1364 goto fail_backlight;
1365 } else
1366 printk(ASUS_INFO "Brightness ignored, must be controlled by "
1367 "ACPI video driver\n");
1368
1369 result = asus_input_init(); 1347 result = asus_input_init();
1370 if (result) 1348 if (result)
1371 goto fail_input; 1349 goto fail_input;
1372 1350
1373 result = asus_led_init(dev);
1374 if (result)
1375 goto fail_led;
1376
1377 /* Register platform stuff */ 1351 /* Register platform stuff */
1378 result = platform_driver_register(&asuspf_driver); 1352 result = platform_driver_register(&asuspf_driver);
1379 if (result) 1353 if (result)
@@ -1394,8 +1368,27 @@ static int __init asus_laptop_init(void)
1394 if (result) 1368 if (result)
1395 goto fail_sysfs; 1369 goto fail_sysfs;
1396 1370
1371 result = asus_led_init(&asuspf_device->dev);
1372 if (result)
1373 goto fail_led;
1374
1375 if (!acpi_video_backlight_support()) {
1376 result = asus_backlight_init(&asuspf_device->dev);
1377 if (result)
1378 goto fail_backlight;
1379 } else
1380 pr_info("Brightness ignored, must be controlled by "
1381 "ACPI video driver\n");
1382
1397 return 0; 1383 return 0;
1398 1384
1385fail_backlight:
1386 asus_led_exit();
1387
1388fail_led:
1389 sysfs_remove_group(&asuspf_device->dev.kobj,
1390 &asuspf_attribute_group);
1391
1399fail_sysfs: 1392fail_sysfs:
1400 platform_device_del(asuspf_device); 1393 platform_device_del(asuspf_device);
1401 1394
@@ -1406,15 +1399,9 @@ fail_platform_device1:
1406 platform_driver_unregister(&asuspf_driver); 1399 platform_driver_unregister(&asuspf_driver);
1407 1400
1408fail_platform_driver: 1401fail_platform_driver:
1409 asus_led_exit();
1410
1411fail_led:
1412 asus_input_exit(); 1402 asus_input_exit();
1413 1403
1414fail_input: 1404fail_input:
1415 asus_backlight_exit();
1416
1417fail_backlight:
1418 1405
1419 return result; 1406 return result;
1420} 1407}
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index ba1f7497e4b9..ddf5240ade8c 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -455,6 +455,8 @@ static struct asus_hotk *hotk;
455 */ 455 */
456static int asus_hotk_add(struct acpi_device *device); 456static int asus_hotk_add(struct acpi_device *device);
457static int asus_hotk_remove(struct acpi_device *device, int type); 457static int asus_hotk_remove(struct acpi_device *device, int type);
458static void asus_hotk_notify(struct acpi_device *device, u32 event);
459
458static const struct acpi_device_id asus_device_ids[] = { 460static const struct acpi_device_id asus_device_ids[] = {
459 {"ATK0100", 0}, 461 {"ATK0100", 0},
460 {"", 0}, 462 {"", 0},
@@ -465,9 +467,11 @@ static struct acpi_driver asus_hotk_driver = {
465 .name = "asus_acpi", 467 .name = "asus_acpi",
466 .class = ACPI_HOTK_CLASS, 468 .class = ACPI_HOTK_CLASS,
467 .ids = asus_device_ids, 469 .ids = asus_device_ids,
470 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
468 .ops = { 471 .ops = {
469 .add = asus_hotk_add, 472 .add = asus_hotk_add,
470 .remove = asus_hotk_remove, 473 .remove = asus_hotk_remove,
474 .notify = asus_hotk_notify,
471 }, 475 },
472}; 476};
473 477
@@ -1101,12 +1105,20 @@ static int asus_hotk_remove_fs(struct acpi_device *device)
1101 return 0; 1105 return 0;
1102} 1106}
1103 1107
1104static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) 1108static void asus_hotk_notify(struct acpi_device *device, u32 event)
1105{ 1109{
1106 /* TODO Find a better way to handle events count. */ 1110 /* TODO Find a better way to handle events count. */
1107 if (!hotk) 1111 if (!hotk)
1108 return; 1112 return;
1109 1113
1114 /*
1115 * The BIOS *should* be sending us device events, but apparently
1116 * Asus uses system events instead, so just ignore any device
1117 * events we get.
1118 */
1119 if (event > ACPI_MAX_SYS_NOTIFY)
1120 return;
1121
1110 if ((event & ~((u32) BR_UP)) < 16) 1122 if ((event & ~((u32) BR_UP)) < 16)
1111 hotk->brightness = (event & ~((u32) BR_UP)); 1123 hotk->brightness = (event & ~((u32) BR_UP));
1112 else if ((event & ~((u32) BR_DOWN)) < 16) 1124 else if ((event & ~((u32) BR_DOWN)) < 16)
@@ -1346,15 +1358,6 @@ static int asus_hotk_add(struct acpi_device *device)
1346 if (result) 1358 if (result)
1347 goto end; 1359 goto end;
1348 1360
1349 /*
1350 * We install the handler, it will receive the hotk in parameter, so, we
1351 * could add other data to the hotk struct
1352 */
1353 status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
1354 asus_hotk_notify, hotk);
1355 if (ACPI_FAILURE(status))
1356 printk(KERN_ERR " Error installing notify handler\n");
1357
1358 /* For laptops without GPLV: init the hotk->brightness value */ 1361 /* For laptops without GPLV: init the hotk->brightness value */
1359 if ((!hotk->methods->brightness_get) 1362 if ((!hotk->methods->brightness_get)
1360 && (!hotk->methods->brightness_status) 1363 && (!hotk->methods->brightness_status)
@@ -1389,16 +1392,9 @@ end:
1389 1392
1390static int asus_hotk_remove(struct acpi_device *device, int type) 1393static int asus_hotk_remove(struct acpi_device *device, int type)
1391{ 1394{
1392 acpi_status status = 0;
1393
1394 if (!device || !acpi_driver_data(device)) 1395 if (!device || !acpi_driver_data(device))
1395 return -EINVAL; 1396 return -EINVAL;
1396 1397
1397 status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
1398 asus_hotk_notify);
1399 if (ACPI_FAILURE(status))
1400 printk(KERN_ERR "Asus ACPI: Error removing notify handler\n");
1401
1402 asus_hotk_remove_fs(device); 1398 asus_hotk_remove_fs(device);
1403 1399
1404 kfree(hotk); 1400 kfree(hotk);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 2fab94162147..0f900cc9fa7a 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -46,10 +46,53 @@ struct key_entry {
46 u16 keycode; 46 u16 keycode;
47}; 47};
48 48
49enum { KE_KEY, KE_SW, KE_END }; 49enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
50
51/*
52 * Certain keys are flagged as KE_IGNORE. All of these are either
53 * notifications (rather than requests for change) or are also sent
54 * via the keyboard controller so should not be sent again.
55 */
50 56
51static struct key_entry dell_wmi_keymap[] = { 57static struct key_entry dell_wmi_keymap[] = {
52 {KE_KEY, 0xe045, KEY_PROG1}, 58 {KE_KEY, 0xe045, KEY_PROG1},
59 {KE_KEY, 0xe009, KEY_EJECTCD},
60
61 /* These also contain the brightness level at offset 6 */
62 {KE_KEY, 0xe006, KEY_BRIGHTNESSUP},
63 {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN},
64
65 /* Battery health status button */
66 {KE_KEY, 0xe007, KEY_BATTERY},
67
68 /* This is actually for all radios. Although physically a
69 * switch, the notification does not provide an indication of
70 * state and so it should be reported as a key */
71 {KE_KEY, 0xe008, KEY_WLAN},
72
73 /* The next device is at offset 6, the active devices are at
74 offset 8 and the attached devices at offset 10 */
75 {KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE},
76
77 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
78
79 /* BIOS error detected */
80 {KE_IGNORE, 0xe00d, KEY_RESERVED},
81
82 /* Wifi Catcher */
83 {KE_KEY, 0xe011, KEY_PROG2},
84
85 /* Ambient light sensor toggle */
86 {KE_IGNORE, 0xe013, KEY_RESERVED},
87
88 {KE_IGNORE, 0xe020, KEY_MUTE},
89 {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN},
90 {KE_IGNORE, 0xe030, KEY_VOLUMEUP},
91 {KE_IGNORE, 0xe033, KEY_KBDILLUMUP},
92 {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN},
93 {KE_IGNORE, 0xe03a, KEY_CAPSLOCK},
94 {KE_IGNORE, 0xe045, KEY_NUMLOCK},
95 {KE_IGNORE, 0xe046, KEY_SCROLLLOCK},
53 {KE_END, 0} 96 {KE_END, 0}
54}; 97};
55 98
@@ -122,15 +165,20 @@ static void dell_wmi_notify(u32 value, void *context)
122 165
123 if (obj && obj->type == ACPI_TYPE_BUFFER) { 166 if (obj && obj->type == ACPI_TYPE_BUFFER) {
124 int *buffer = (int *)obj->buffer.pointer; 167 int *buffer = (int *)obj->buffer.pointer;
125 key = dell_wmi_get_entry_by_scancode(buffer[1]); 168 /*
169 * The upper bytes of the event may contain
170 * additional information, so mask them off for the
171 * scancode lookup
172 */
173 key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF);
126 if (key) { 174 if (key) {
127 input_report_key(dell_wmi_input_dev, key->keycode, 1); 175 input_report_key(dell_wmi_input_dev, key->keycode, 1);
128 input_sync(dell_wmi_input_dev); 176 input_sync(dell_wmi_input_dev);
129 input_report_key(dell_wmi_input_dev, key->keycode, 0); 177 input_report_key(dell_wmi_input_dev, key->keycode, 0);
130 input_sync(dell_wmi_input_dev); 178 input_sync(dell_wmi_input_dev);
131 } else 179 } else if (buffer[1] & 0xFFFF)
132 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n", 180 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
133 buffer[1]); 181 buffer[1] & 0xFFFF);
134 } 182 }
135} 183}
136 184
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 03bf522bd7ab..ec560f16d720 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -16,6 +16,8 @@
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 */ 17 */
18 18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
19#include <linux/kernel.h> 21#include <linux/kernel.h>
20#include <linux/module.h> 22#include <linux/module.h>
21#include <linux/init.h> 23#include <linux/init.h>
@@ -31,6 +33,7 @@
31#include <linux/input.h> 33#include <linux/input.h>
32#include <linux/rfkill.h> 34#include <linux/rfkill.h>
33#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/pci_hotplug.h>
34 37
35#define EEEPC_LAPTOP_VERSION "0.1" 38#define EEEPC_LAPTOP_VERSION "0.1"
36 39
@@ -40,11 +43,6 @@
40#define EEEPC_HOTK_DEVICE_NAME "Hotkey" 43#define EEEPC_HOTK_DEVICE_NAME "Hotkey"
41#define EEEPC_HOTK_HID "ASUS010" 44#define EEEPC_HOTK_HID "ASUS010"
42 45
43#define EEEPC_LOG EEEPC_HOTK_FILE ": "
44#define EEEPC_ERR KERN_ERR EEEPC_LOG
45#define EEEPC_WARNING KERN_WARNING EEEPC_LOG
46#define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG
47#define EEEPC_INFO KERN_INFO EEEPC_LOG
48 46
49/* 47/*
50 * Definitions for Asus EeePC 48 * Definitions for Asus EeePC
@@ -62,7 +60,10 @@ enum {
62 DISABLE_ASL_GPS = 0x0020, 60 DISABLE_ASL_GPS = 0x0020,
63 DISABLE_ASL_DISPLAYSWITCH = 0x0040, 61 DISABLE_ASL_DISPLAYSWITCH = 0x0040,
64 DISABLE_ASL_MODEM = 0x0080, 62 DISABLE_ASL_MODEM = 0x0080,
65 DISABLE_ASL_CARDREADER = 0x0100 63 DISABLE_ASL_CARDREADER = 0x0100,
64 DISABLE_ASL_3G = 0x0200,
65 DISABLE_ASL_WIMAX = 0x0400,
66 DISABLE_ASL_HWCF = 0x0800
66}; 67};
67 68
68enum { 69enum {
@@ -87,7 +88,13 @@ enum {
87 CM_ASL_USBPORT3, 88 CM_ASL_USBPORT3,
88 CM_ASL_MODEM, 89 CM_ASL_MODEM,
89 CM_ASL_CARDREADER, 90 CM_ASL_CARDREADER,
90 CM_ASL_LID 91 CM_ASL_3G,
92 CM_ASL_WIMAX,
93 CM_ASL_HWCF,
94 CM_ASL_LID,
95 CM_ASL_TYPE,
96 CM_ASL_PANELPOWER, /*P901*/
97 CM_ASL_TPD
91}; 98};
92 99
93static const char *cm_getv[] = { 100static const char *cm_getv[] = {
@@ -96,7 +103,8 @@ static const char *cm_getv[] = {
96 NULL, "PBLG", NULL, NULL, 103 NULL, "PBLG", NULL, NULL,
97 "CFVG", NULL, NULL, NULL, 104 "CFVG", NULL, NULL, NULL,
98 "USBG", NULL, NULL, "MODG", 105 "USBG", NULL, NULL, "MODG",
99 "CRDG", "LIDG" 106 "CRDG", "M3GG", "WIMG", "HWCF",
107 "LIDG", "TYPE", "PBPG", "TPDG"
100}; 108};
101 109
102static const char *cm_setv[] = { 110static const char *cm_setv[] = {
@@ -105,7 +113,8 @@ static const char *cm_setv[] = {
105 "SDSP", "PBLS", "HDPS", NULL, 113 "SDSP", "PBLS", "HDPS", NULL,
106 "CFVS", NULL, NULL, NULL, 114 "CFVS", NULL, NULL, NULL,
107 "USBG", NULL, NULL, "MODS", 115 "USBG", NULL, NULL, "MODS",
108 "CRDS", NULL 116 "CRDS", "M3GS", "WIMS", NULL,
117 NULL, NULL, "PBPS", "TPDS"
109}; 118};
110 119
111#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." 120#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
@@ -130,8 +139,10 @@ struct eeepc_hotk {
130 u16 event_count[128]; /* count for each event */ 139 u16 event_count[128]; /* count for each event */
131 struct input_dev *inputdev; 140 struct input_dev *inputdev;
132 u16 *keycode_map; 141 u16 *keycode_map;
133 struct rfkill *eeepc_wlan_rfkill; 142 struct rfkill *wlan_rfkill;
134 struct rfkill *eeepc_bluetooth_rfkill; 143 struct rfkill *bluetooth_rfkill;
144 struct rfkill *wwan3g_rfkill;
145 struct hotplug_slot *hotplug_slot;
135}; 146};
136 147
137/* The actual device the driver binds to */ 148/* The actual device the driver binds to */
@@ -180,6 +191,8 @@ static struct key_entry eeepc_keymap[] = {
180 */ 191 */
181static int eeepc_hotk_add(struct acpi_device *device); 192static int eeepc_hotk_add(struct acpi_device *device);
182static int eeepc_hotk_remove(struct acpi_device *device, int type); 193static int eeepc_hotk_remove(struct acpi_device *device, int type);
194static int eeepc_hotk_resume(struct acpi_device *device);
195static void eeepc_hotk_notify(struct acpi_device *device, u32 event);
183 196
184static const struct acpi_device_id eeepc_device_ids[] = { 197static const struct acpi_device_id eeepc_device_ids[] = {
185 {EEEPC_HOTK_HID, 0}, 198 {EEEPC_HOTK_HID, 0},
@@ -191,12 +204,24 @@ static struct acpi_driver eeepc_hotk_driver = {
191 .name = EEEPC_HOTK_NAME, 204 .name = EEEPC_HOTK_NAME,
192 .class = EEEPC_HOTK_CLASS, 205 .class = EEEPC_HOTK_CLASS,
193 .ids = eeepc_device_ids, 206 .ids = eeepc_device_ids,
207 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
194 .ops = { 208 .ops = {
195 .add = eeepc_hotk_add, 209 .add = eeepc_hotk_add,
196 .remove = eeepc_hotk_remove, 210 .remove = eeepc_hotk_remove,
211 .resume = eeepc_hotk_resume,
212 .notify = eeepc_hotk_notify,
197 }, 213 },
198}; 214};
199 215
216/* PCI hotplug ops */
217static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value);
218
219static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
220 .owner = THIS_MODULE,
221 .get_adapter_status = eeepc_get_adapter_status,
222 .get_power_status = eeepc_get_adapter_status,
223};
224
200/* The backlight device /sys/class/backlight */ 225/* The backlight device /sys/class/backlight */
201static struct backlight_device *eeepc_backlight_device; 226static struct backlight_device *eeepc_backlight_device;
202 227
@@ -258,20 +283,20 @@ static int set_acpi(int cm, int value)
258 if (method == NULL) 283 if (method == NULL)
259 return -ENODEV; 284 return -ENODEV;
260 if (write_acpi_int(ehotk->handle, method, value, NULL)) 285 if (write_acpi_int(ehotk->handle, method, value, NULL))
261 printk(EEEPC_WARNING "Error writing %s\n", method); 286 pr_warning("Error writing %s\n", method);
262 } 287 }
263 return 0; 288 return 0;
264} 289}
265 290
266static int get_acpi(int cm) 291static int get_acpi(int cm)
267{ 292{
268 int value = -1; 293 int value = -ENODEV;
269 if ((ehotk->cm_supported & (0x1 << cm))) { 294 if ((ehotk->cm_supported & (0x1 << cm))) {
270 const char *method = cm_getv[cm]; 295 const char *method = cm_getv[cm];
271 if (method == NULL) 296 if (method == NULL)
272 return -ENODEV; 297 return -ENODEV;
273 if (read_acpi_int(ehotk->handle, method, &value)) 298 if (read_acpi_int(ehotk->handle, method, &value))
274 printk(EEEPC_WARNING "Error reading %s\n", method); 299 pr_warning("Error reading %s\n", method);
275 } 300 }
276 return value; 301 return value;
277} 302}
@@ -316,6 +341,15 @@ static const struct rfkill_ops eeepc_rfkill_ops = {
316 .set_block = eeepc_rfkill_set, 341 .set_block = eeepc_rfkill_set,
317}; 342};
318 343
344static void __init eeepc_enable_camera(void)
345{
346 /*
347 * If the following call to set_acpi() fails, it's because there's no
348 * camera so we can ignore the error.
349 */
350 set_acpi(CM_ASL_CAMERA, 1);
351}
352
319/* 353/*
320 * Sys helpers 354 * Sys helpers
321 */ 355 */
@@ -334,13 +368,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count)
334 368
335 rv = parse_arg(buf, count, &value); 369 rv = parse_arg(buf, count, &value);
336 if (rv > 0) 370 if (rv > 0)
337 set_acpi(cm, value); 371 value = set_acpi(cm, value);
372 if (value < 0)
373 return value;
338 return rv; 374 return rv;
339} 375}
340 376
341static ssize_t show_sys_acpi(int cm, char *buf) 377static ssize_t show_sys_acpi(int cm, char *buf)
342{ 378{
343 return sprintf(buf, "%d\n", get_acpi(cm)); 379 int value = get_acpi(cm);
380
381 if (value < 0)
382 return value;
383 return sprintf(buf, "%d\n", value);
344} 384}
345 385
346#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ 386#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \
@@ -367,13 +407,88 @@ static ssize_t show_sys_acpi(int cm, char *buf)
367EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); 407EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA);
368EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); 408EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER);
369EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); 409EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH);
370EEEPC_CREATE_DEVICE_ATTR(cpufv, CM_ASL_CPUFV); 410
411struct eeepc_cpufv {
412 int num;
413 int cur;
414};
415
416static int get_cpufv(struct eeepc_cpufv *c)
417{
418 c->cur = get_acpi(CM_ASL_CPUFV);
419 c->num = (c->cur >> 8) & 0xff;
420 c->cur &= 0xff;
421 if (c->cur < 0 || c->num <= 0 || c->num > 12)
422 return -ENODEV;
423 return 0;
424}
425
426static ssize_t show_available_cpufv(struct device *dev,
427 struct device_attribute *attr,
428 char *buf)
429{
430 struct eeepc_cpufv c;
431 int i;
432 ssize_t len = 0;
433
434 if (get_cpufv(&c))
435 return -ENODEV;
436 for (i = 0; i < c.num; i++)
437 len += sprintf(buf + len, "%d ", i);
438 len += sprintf(buf + len, "\n");
439 return len;
440}
441
442static ssize_t show_cpufv(struct device *dev,
443 struct device_attribute *attr,
444 char *buf)
445{
446 struct eeepc_cpufv c;
447
448 if (get_cpufv(&c))
449 return -ENODEV;
450 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
451}
452
453static ssize_t store_cpufv(struct device *dev,
454 struct device_attribute *attr,
455 const char *buf, size_t count)
456{
457 struct eeepc_cpufv c;
458 int rv, value;
459
460 if (get_cpufv(&c))
461 return -ENODEV;
462 rv = parse_arg(buf, count, &value);
463 if (rv < 0)
464 return rv;
465 if (!rv || value < 0 || value >= c.num)
466 return -EINVAL;
467 set_acpi(CM_ASL_CPUFV, value);
468 return rv;
469}
470
471static struct device_attribute dev_attr_cpufv = {
472 .attr = {
473 .name = "cpufv",
474 .mode = 0644 },
475 .show = show_cpufv,
476 .store = store_cpufv
477};
478
479static struct device_attribute dev_attr_available_cpufv = {
480 .attr = {
481 .name = "available_cpufv",
482 .mode = 0444 },
483 .show = show_available_cpufv
484};
371 485
372static struct attribute *platform_attributes[] = { 486static struct attribute *platform_attributes[] = {
373 &dev_attr_camera.attr, 487 &dev_attr_camera.attr,
374 &dev_attr_cardr.attr, 488 &dev_attr_cardr.attr,
375 &dev_attr_disp.attr, 489 &dev_attr_disp.attr,
376 &dev_attr_cpufv.attr, 490 &dev_attr_cpufv.attr,
491 &dev_attr_available_cpufv.attr,
377 NULL 492 NULL
378}; 493};
379 494
@@ -439,6 +554,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
439 return -EINVAL; 554 return -EINVAL;
440} 555}
441 556
557static void cmsg_quirk(int cm, const char *name)
558{
559 int dummy;
560
561 /* Some BIOSes do not report cm although it is avaliable.
562 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
563 if (!(ehotk->cm_supported & (1 << cm))
564 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
565 pr_info("%s (%x) not reported by BIOS,"
566 " enabling anyway\n", name, 1 << cm);
567 ehotk->cm_supported |= 1 << cm;
568 }
569}
570
571static void cmsg_quirks(void)
572{
573 cmsg_quirk(CM_ASL_LID, "LID");
574 cmsg_quirk(CM_ASL_TYPE, "TYPE");
575 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
576 cmsg_quirk(CM_ASL_TPD, "TPD");
577}
578
442static int eeepc_hotk_check(void) 579static int eeepc_hotk_check(void)
443{ 580{
444 const struct key_entry *key; 581 const struct key_entry *key;
@@ -451,26 +588,24 @@ static int eeepc_hotk_check(void)
451 if (ehotk->device->status.present) { 588 if (ehotk->device->status.present) {
452 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, 589 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag,
453 &buffer)) { 590 &buffer)) {
454 printk(EEEPC_ERR "Hotkey initialization failed\n"); 591 pr_err("Hotkey initialization failed\n");
455 return -ENODEV; 592 return -ENODEV;
456 } else { 593 } else {
457 printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", 594 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
458 ehotk->init_flag);
459 } 595 }
460 /* get control methods supported */ 596 /* get control methods supported */
461 if (read_acpi_int(ehotk->handle, "CMSG" 597 if (read_acpi_int(ehotk->handle, "CMSG"
462 , &ehotk->cm_supported)) { 598 , &ehotk->cm_supported)) {
463 printk(EEEPC_ERR 599 pr_err("Get control methods supported failed\n");
464 "Get control methods supported failed\n");
465 return -ENODEV; 600 return -ENODEV;
466 } else { 601 } else {
467 printk(EEEPC_INFO 602 cmsg_quirks();
468 "Get control methods supported: 0x%x\n", 603 pr_info("Get control methods supported: 0x%x\n",
469 ehotk->cm_supported); 604 ehotk->cm_supported);
470 } 605 }
471 ehotk->inputdev = input_allocate_device(); 606 ehotk->inputdev = input_allocate_device();
472 if (!ehotk->inputdev) { 607 if (!ehotk->inputdev) {
473 printk(EEEPC_INFO "Unable to allocate input device\n"); 608 pr_info("Unable to allocate input device\n");
474 return 0; 609 return 0;
475 } 610 }
476 ehotk->inputdev->name = "Asus EeePC extra buttons"; 611 ehotk->inputdev->name = "Asus EeePC extra buttons";
@@ -489,12 +624,12 @@ static int eeepc_hotk_check(void)
489 } 624 }
490 result = input_register_device(ehotk->inputdev); 625 result = input_register_device(ehotk->inputdev);
491 if (result) { 626 if (result) {
492 printk(EEEPC_INFO "Unable to register input device\n"); 627 pr_info("Unable to register input device\n");
493 input_free_device(ehotk->inputdev); 628 input_free_device(ehotk->inputdev);
494 return 0; 629 return 0;
495 } 630 }
496 } else { 631 } else {
497 printk(EEEPC_ERR "Hotkey device not present, aborting\n"); 632 pr_err("Hotkey device not present, aborting\n");
498 return -EINVAL; 633 return -EINVAL;
499 } 634 }
500 return 0; 635 return 0;
@@ -512,17 +647,27 @@ static int notify_brn(void)
512 return -1; 647 return -1;
513} 648}
514 649
515static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 650static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
651 u8 *value)
652{
653 int val = get_acpi(CM_ASL_WLAN);
654
655 if (val == 1 || val == 0)
656 *value = val;
657 else
658 return -EINVAL;
659
660 return 0;
661}
662
663static void eeepc_rfkill_hotplug(void)
516{ 664{
517 struct pci_dev *dev; 665 struct pci_dev *dev;
518 struct pci_bus *bus = pci_find_bus(0, 1); 666 struct pci_bus *bus = pci_find_bus(0, 1);
519 bool blocked; 667 bool blocked;
520 668
521 if (event != ACPI_NOTIFY_BUS_CHECK)
522 return;
523
524 if (!bus) { 669 if (!bus) {
525 printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); 670 pr_warning("Unable to find PCI bus 1?\n");
526 return; 671 return;
527 } 672 }
528 673
@@ -538,7 +683,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
538 if (dev) { 683 if (dev) {
539 pci_bus_assign_resources(bus); 684 pci_bus_assign_resources(bus);
540 if (pci_bus_add_device(dev)) 685 if (pci_bus_add_device(dev))
541 printk(EEEPC_ERR "Unable to hotplug wifi\n"); 686 pr_err("Unable to hotplug wifi\n");
542 } 687 }
543 } else { 688 } else {
544 dev = pci_get_slot(bus, 0); 689 dev = pci_get_slot(bus, 0);
@@ -548,10 +693,18 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
548 } 693 }
549 } 694 }
550 695
551 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); 696 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked);
552} 697}
553 698
554static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) 699static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
700{
701 if (event != ACPI_NOTIFY_BUS_CHECK)
702 return;
703
704 eeepc_rfkill_hotplug();
705}
706
707static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
555{ 708{
556 static struct key_entry *key; 709 static struct key_entry *key;
557 u16 count; 710 u16 count;
@@ -559,6 +712,8 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data)
559 712
560 if (!ehotk) 713 if (!ehotk)
561 return; 714 return;
715 if (event > ACPI_MAX_SYS_NOTIFY)
716 return;
562 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) 717 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
563 brn = notify_brn(); 718 brn = notify_brn();
564 count = ehotk->event_count[event % 128]++; 719 count = ehotk->event_count[event % 128]++;
@@ -611,8 +766,7 @@ static int eeepc_register_rfkill_notifier(char *node)
611 eeepc_rfkill_notify, 766 eeepc_rfkill_notify,
612 NULL); 767 NULL);
613 if (ACPI_FAILURE(status)) 768 if (ACPI_FAILURE(status))
614 printk(EEEPC_WARNING 769 pr_warning("Failed to register notify on %s\n", node);
615 "Failed to register notify on %s\n", node);
616 } else 770 } else
617 return -ENODEV; 771 return -ENODEV;
618 772
@@ -631,20 +785,66 @@ static void eeepc_unregister_rfkill_notifier(char *node)
631 ACPI_SYSTEM_NOTIFY, 785 ACPI_SYSTEM_NOTIFY,
632 eeepc_rfkill_notify); 786 eeepc_rfkill_notify);
633 if (ACPI_FAILURE(status)) 787 if (ACPI_FAILURE(status))
634 printk(EEEPC_ERR 788 pr_err("Error removing rfkill notify handler %s\n",
635 "Error removing rfkill notify handler %s\n",
636 node); 789 node);
637 } 790 }
638} 791}
639 792
793static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
794{
795 kfree(hotplug_slot->info);
796 kfree(hotplug_slot);
797}
798
799static int eeepc_setup_pci_hotplug(void)
800{
801 int ret = -ENOMEM;
802 struct pci_bus *bus = pci_find_bus(0, 1);
803
804 if (!bus) {
805 pr_err("Unable to find wifi PCI bus\n");
806 return -ENODEV;
807 }
808
809 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
810 if (!ehotk->hotplug_slot)
811 goto error_slot;
812
813 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
814 GFP_KERNEL);
815 if (!ehotk->hotplug_slot->info)
816 goto error_info;
817
818 ehotk->hotplug_slot->private = ehotk;
819 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
820 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
821 eeepc_get_adapter_status(ehotk->hotplug_slot,
822 &ehotk->hotplug_slot->info->adapter_status);
823
824 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi");
825 if (ret) {
826 pr_err("Unable to register hotplug slot - %d\n", ret);
827 goto error_register;
828 }
829
830 return 0;
831
832error_register:
833 kfree(ehotk->hotplug_slot->info);
834error_info:
835 kfree(ehotk->hotplug_slot);
836 ehotk->hotplug_slot = NULL;
837error_slot:
838 return ret;
839}
840
640static int eeepc_hotk_add(struct acpi_device *device) 841static int eeepc_hotk_add(struct acpi_device *device)
641{ 842{
642 acpi_status status = AE_OK;
643 int result; 843 int result;
644 844
645 if (!device) 845 if (!device)
646 return -EINVAL; 846 return -EINVAL;
647 printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); 847 pr_notice(EEEPC_HOTK_NAME "\n");
648 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); 848 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
649 if (!ehotk) 849 if (!ehotk)
650 return -ENOMEM; 850 return -ENOMEM;
@@ -657,58 +857,9 @@ static int eeepc_hotk_add(struct acpi_device *device)
657 result = eeepc_hotk_check(); 857 result = eeepc_hotk_check();
658 if (result) 858 if (result)
659 goto ehotk_fail; 859 goto ehotk_fail;
660 status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
661 eeepc_hotk_notify, ehotk);
662 if (ACPI_FAILURE(status))
663 printk(EEEPC_ERR "Error installing notify handler\n");
664
665 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
666 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
667
668 if (get_acpi(CM_ASL_WLAN) != -1) {
669 ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan",
670 &device->dev,
671 RFKILL_TYPE_WLAN,
672 &eeepc_rfkill_ops,
673 (void *)CM_ASL_WLAN);
674
675 if (!ehotk->eeepc_wlan_rfkill)
676 goto wlan_fail;
677
678 rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill,
679 get_acpi(CM_ASL_WLAN) != 1);
680 result = rfkill_register(ehotk->eeepc_wlan_rfkill);
681 if (result)
682 goto wlan_fail;
683 }
684
685 if (get_acpi(CM_ASL_BLUETOOTH) != -1) {
686 ehotk->eeepc_bluetooth_rfkill =
687 rfkill_alloc("eeepc-bluetooth",
688 &device->dev,
689 RFKILL_TYPE_BLUETOOTH,
690 &eeepc_rfkill_ops,
691 (void *)CM_ASL_BLUETOOTH);
692
693 if (!ehotk->eeepc_bluetooth_rfkill)
694 goto bluetooth_fail;
695
696 rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill,
697 get_acpi(CM_ASL_BLUETOOTH) != 1);
698 result = rfkill_register(ehotk->eeepc_bluetooth_rfkill);
699 if (result)
700 goto bluetooth_fail;
701 }
702 860
703 return 0; 861 return 0;
704 862
705 bluetooth_fail:
706 rfkill_destroy(ehotk->eeepc_bluetooth_rfkill);
707 rfkill_unregister(ehotk->eeepc_wlan_rfkill);
708 wlan_fail:
709 rfkill_destroy(ehotk->eeepc_wlan_rfkill);
710 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
711 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
712 ehotk_fail: 863 ehotk_fail:
713 kfree(ehotk); 864 kfree(ehotk);
714 ehotk = NULL; 865 ehotk = NULL;
@@ -718,22 +869,39 @@ static int eeepc_hotk_add(struct acpi_device *device)
718 869
719static int eeepc_hotk_remove(struct acpi_device *device, int type) 870static int eeepc_hotk_remove(struct acpi_device *device, int type)
720{ 871{
721 acpi_status status = 0;
722
723 if (!device || !acpi_driver_data(device)) 872 if (!device || !acpi_driver_data(device))
724 return -EINVAL; 873 return -EINVAL;
725 status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY,
726 eeepc_hotk_notify);
727 if (ACPI_FAILURE(status))
728 printk(EEEPC_ERR "Error removing notify handler\n");
729
730 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
731 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
732 874
733 kfree(ehotk); 875 kfree(ehotk);
734 return 0; 876 return 0;
735} 877}
736 878
879static int eeepc_hotk_resume(struct acpi_device *device)
880{
881 if (ehotk->wlan_rfkill) {
882 bool wlan;
883
884 /* Workaround - it seems that _PTS disables the wireless
885 without notification or changing the value read by WLAN.
886 Normally this is fine because the correct value is restored
887 from the non-volatile storage on resume, but we need to do
888 it ourself if case suspend is aborted, or we lose wireless.
889 */
890 wlan = get_acpi(CM_ASL_WLAN);
891 set_acpi(CM_ASL_WLAN, wlan);
892
893 rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1);
894
895 eeepc_rfkill_hotplug();
896 }
897
898 if (ehotk->bluetooth_rfkill)
899 rfkill_set_sw_state(ehotk->bluetooth_rfkill,
900 get_acpi(CM_ASL_BLUETOOTH) != 1);
901
902 return 0;
903}
904
737/* 905/*
738 * Hwmon 906 * Hwmon
739 */ 907 */
@@ -850,10 +1018,16 @@ static void eeepc_backlight_exit(void)
850 1018
851static void eeepc_rfkill_exit(void) 1019static void eeepc_rfkill_exit(void)
852{ 1020{
853 if (ehotk->eeepc_wlan_rfkill) 1021 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6");
854 rfkill_unregister(ehotk->eeepc_wlan_rfkill); 1022 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7");
855 if (ehotk->eeepc_bluetooth_rfkill) 1023 if (ehotk->wlan_rfkill)
856 rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); 1024 rfkill_unregister(ehotk->wlan_rfkill);
1025 if (ehotk->bluetooth_rfkill)
1026 rfkill_unregister(ehotk->bluetooth_rfkill);
1027 if (ehotk->wwan3g_rfkill)
1028 rfkill_unregister(ehotk->wwan3g_rfkill);
1029 if (ehotk->hotplug_slot)
1030 pci_hp_deregister(ehotk->hotplug_slot);
857} 1031}
858 1032
859static void eeepc_input_exit(void) 1033static void eeepc_input_exit(void)
@@ -888,6 +1062,75 @@ static void __exit eeepc_laptop_exit(void)
888 platform_driver_unregister(&platform_driver); 1062 platform_driver_unregister(&platform_driver);
889} 1063}
890 1064
1065static int eeepc_new_rfkill(struct rfkill **rfkill,
1066 const char *name, struct device *dev,
1067 enum rfkill_type type, int cm)
1068{
1069 int result;
1070
1071 result = get_acpi(cm);
1072 if (result < 0)
1073 return result;
1074
1075 *rfkill = rfkill_alloc(name, dev, type,
1076 &eeepc_rfkill_ops, (void *)(unsigned long)cm);
1077
1078 if (!*rfkill)
1079 return -EINVAL;
1080
1081 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1);
1082 result = rfkill_register(*rfkill);
1083 if (result) {
1084 rfkill_destroy(*rfkill);
1085 *rfkill = NULL;
1086 return result;
1087 }
1088 return 0;
1089}
1090
1091
1092static int eeepc_rfkill_init(struct device *dev)
1093{
1094 int result = 0;
1095
1096 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6");
1097 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7");
1098
1099 result = eeepc_new_rfkill(&ehotk->wlan_rfkill,
1100 "eeepc-wlan", dev,
1101 RFKILL_TYPE_WLAN, CM_ASL_WLAN);
1102
1103 if (result && result != -ENODEV)
1104 goto exit;
1105
1106 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1107 "eeepc-bluetooth", dev,
1108 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1109
1110 if (result && result != -ENODEV)
1111 goto exit;
1112
1113 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill,
1114 "eeepc-wwan3g", dev,
1115 RFKILL_TYPE_WWAN, CM_ASL_3G);
1116
1117 if (result && result != -ENODEV)
1118 goto exit;
1119
1120 result = eeepc_setup_pci_hotplug();
1121 /*
1122 * If we get -EBUSY then something else is handling the PCI hotplug -
1123 * don't fail in this case
1124 */
1125 if (result == -EBUSY)
1126 result = 0;
1127
1128exit:
1129 if (result && result != -ENODEV)
1130 eeepc_rfkill_exit();
1131 return result;
1132}
1133
891static int eeepc_backlight_init(struct device *dev) 1134static int eeepc_backlight_init(struct device *dev)
892{ 1135{
893 struct backlight_device *bd; 1136 struct backlight_device *bd;
@@ -895,8 +1138,7 @@ static int eeepc_backlight_init(struct device *dev)
895 bd = backlight_device_register(EEEPC_HOTK_FILE, dev, 1138 bd = backlight_device_register(EEEPC_HOTK_FILE, dev,
896 NULL, &eeepcbl_ops); 1139 NULL, &eeepcbl_ops);
897 if (IS_ERR(bd)) { 1140 if (IS_ERR(bd)) {
898 printk(EEEPC_ERR 1141 pr_err("Could not register eeepc backlight device\n");
899 "Could not register eeepc backlight device\n");
900 eeepc_backlight_device = NULL; 1142 eeepc_backlight_device = NULL;
901 return PTR_ERR(bd); 1143 return PTR_ERR(bd);
902 } 1144 }
@@ -915,8 +1157,7 @@ static int eeepc_hwmon_init(struct device *dev)
915 1157
916 hwmon = hwmon_device_register(dev); 1158 hwmon = hwmon_device_register(dev);
917 if (IS_ERR(hwmon)) { 1159 if (IS_ERR(hwmon)) {
918 printk(EEEPC_ERR 1160 pr_err("Could not register eeepc hwmon device\n");
919 "Could not register eeepc hwmon device\n");
920 eeepc_hwmon_device = NULL; 1161 eeepc_hwmon_device = NULL;
921 return PTR_ERR(hwmon); 1162 return PTR_ERR(hwmon);
922 } 1163 }
@@ -942,19 +1183,9 @@ static int __init eeepc_laptop_init(void)
942 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1183 acpi_bus_unregister_driver(&eeepc_hotk_driver);
943 return -ENODEV; 1184 return -ENODEV;
944 } 1185 }
945 dev = acpi_get_physical_device(ehotk->device->handle);
946 1186
947 if (!acpi_video_backlight_support()) { 1187 eeepc_enable_camera();
948 result = eeepc_backlight_init(dev);
949 if (result)
950 goto fail_backlight;
951 } else
952 printk(EEEPC_INFO "Backlight controlled by ACPI video "
953 "driver\n");
954 1188
955 result = eeepc_hwmon_init(dev);
956 if (result)
957 goto fail_hwmon;
958 /* Register platform stuff */ 1189 /* Register platform stuff */
959 result = platform_driver_register(&platform_driver); 1190 result = platform_driver_register(&platform_driver);
960 if (result) 1191 if (result)
@@ -971,7 +1202,33 @@ static int __init eeepc_laptop_init(void)
971 &platform_attribute_group); 1202 &platform_attribute_group);
972 if (result) 1203 if (result)
973 goto fail_sysfs; 1204 goto fail_sysfs;
1205
1206 dev = &platform_device->dev;
1207
1208 if (!acpi_video_backlight_support()) {
1209 result = eeepc_backlight_init(dev);
1210 if (result)
1211 goto fail_backlight;
1212 } else
1213 pr_info("Backlight controlled by ACPI video "
1214 "driver\n");
1215
1216 result = eeepc_hwmon_init(dev);
1217 if (result)
1218 goto fail_hwmon;
1219
1220 result = eeepc_rfkill_init(dev);
1221 if (result)
1222 goto fail_rfkill;
1223
974 return 0; 1224 return 0;
1225fail_rfkill:
1226 eeepc_hwmon_exit();
1227fail_hwmon:
1228 eeepc_backlight_exit();
1229fail_backlight:
1230 sysfs_remove_group(&platform_device->dev.kobj,
1231 &platform_attribute_group);
975fail_sysfs: 1232fail_sysfs:
976 platform_device_del(platform_device); 1233 platform_device_del(platform_device);
977fail_platform_device2: 1234fail_platform_device2:
@@ -979,12 +1236,7 @@ fail_platform_device2:
979fail_platform_device1: 1236fail_platform_device1:
980 platform_driver_unregister(&platform_driver); 1237 platform_driver_unregister(&platform_driver);
981fail_platform_driver: 1238fail_platform_driver:
982 eeepc_hwmon_exit();
983fail_hwmon:
984 eeepc_backlight_exit();
985fail_backlight:
986 eeepc_input_exit(); 1239 eeepc_input_exit();
987 eeepc_rfkill_exit();
988 return result; 1240 return result;
989} 1241}
990 1242
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 16fffe44e333..4ac2311c00af 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -47,7 +47,7 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
47#define HPWMI_DISPLAY_QUERY 0x1 47#define HPWMI_DISPLAY_QUERY 0x1
48#define HPWMI_HDDTEMP_QUERY 0x2 48#define HPWMI_HDDTEMP_QUERY 0x2
49#define HPWMI_ALS_QUERY 0x3 49#define HPWMI_ALS_QUERY 0x3
50#define HPWMI_DOCK_QUERY 0x4 50#define HPWMI_HARDWARE_QUERY 0x4
51#define HPWMI_WIRELESS_QUERY 0x5 51#define HPWMI_WIRELESS_QUERY 0x5
52#define HPWMI_HOTKEY_QUERY 0xc 52#define HPWMI_HOTKEY_QUERY 0xc
53 53
@@ -75,10 +75,9 @@ struct key_entry {
75 u16 keycode; 75 u16 keycode;
76}; 76};
77 77
78enum { KE_KEY, KE_SW, KE_END }; 78enum { KE_KEY, KE_END };
79 79
80static struct key_entry hp_wmi_keymap[] = { 80static struct key_entry hp_wmi_keymap[] = {
81 {KE_SW, 0x01, SW_DOCK},
82 {KE_KEY, 0x02, KEY_BRIGHTNESSUP}, 81 {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
83 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN}, 82 {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
84 {KE_KEY, 0x20e6, KEY_PROG1}, 83 {KE_KEY, 0x20e6, KEY_PROG1},
@@ -151,7 +150,22 @@ static int hp_wmi_als_state(void)
151 150
152static int hp_wmi_dock_state(void) 151static int hp_wmi_dock_state(void)
153{ 152{
154 return hp_wmi_perform_query(HPWMI_DOCK_QUERY, 0, 0); 153 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0);
154
155 if (ret < 0)
156 return ret;
157
158 return ret & 0x1;
159}
160
161static int hp_wmi_tablet_state(void)
162{
163 int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, 0);
164
165 if (ret < 0)
166 return ret;
167
168 return (ret & 0x4) ? 1 : 0;
155} 169}
156 170
157static int hp_wmi_set_block(void *data, bool blocked) 171static int hp_wmi_set_block(void *data, bool blocked)
@@ -232,6 +246,15 @@ static ssize_t show_dock(struct device *dev, struct device_attribute *attr,
232 return sprintf(buf, "%d\n", value); 246 return sprintf(buf, "%d\n", value);
233} 247}
234 248
249static ssize_t show_tablet(struct device *dev, struct device_attribute *attr,
250 char *buf)
251{
252 int value = hp_wmi_tablet_state();
253 if (value < 0)
254 return -EINVAL;
255 return sprintf(buf, "%d\n", value);
256}
257
235static ssize_t set_als(struct device *dev, struct device_attribute *attr, 258static ssize_t set_als(struct device *dev, struct device_attribute *attr,
236 const char *buf, size_t count) 259 const char *buf, size_t count)
237{ 260{
@@ -244,6 +267,7 @@ static DEVICE_ATTR(display, S_IRUGO, show_display, NULL);
244static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL); 267static DEVICE_ATTR(hddtemp, S_IRUGO, show_hddtemp, NULL);
245static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); 268static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
246static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); 269static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
270static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
247 271
248static struct key_entry *hp_wmi_get_entry_by_scancode(int code) 272static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
249{ 273{
@@ -326,13 +350,13 @@ static void hp_wmi_notify(u32 value, void *context)
326 key->keycode, 0); 350 key->keycode, 0);
327 input_sync(hp_wmi_input_dev); 351 input_sync(hp_wmi_input_dev);
328 break; 352 break;
329 case KE_SW:
330 input_report_switch(hp_wmi_input_dev,
331 key->keycode,
332 hp_wmi_dock_state());
333 input_sync(hp_wmi_input_dev);
334 break;
335 } 353 }
354 } else if (eventcode == 0x1) {
355 input_report_switch(hp_wmi_input_dev, SW_DOCK,
356 hp_wmi_dock_state());
357 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
358 hp_wmi_tablet_state());
359 input_sync(hp_wmi_input_dev);
336 } else if (eventcode == 0x5) { 360 } else if (eventcode == 0x5) {
337 if (wifi_rfkill) 361 if (wifi_rfkill)
338 rfkill_set_sw_state(wifi_rfkill, 362 rfkill_set_sw_state(wifi_rfkill,
@@ -369,18 +393,19 @@ static int __init hp_wmi_input_setup(void)
369 set_bit(EV_KEY, hp_wmi_input_dev->evbit); 393 set_bit(EV_KEY, hp_wmi_input_dev->evbit);
370 set_bit(key->keycode, hp_wmi_input_dev->keybit); 394 set_bit(key->keycode, hp_wmi_input_dev->keybit);
371 break; 395 break;
372 case KE_SW:
373 set_bit(EV_SW, hp_wmi_input_dev->evbit);
374 set_bit(key->keycode, hp_wmi_input_dev->swbit);
375
376 /* Set initial dock state */
377 input_report_switch(hp_wmi_input_dev, key->keycode,
378 hp_wmi_dock_state());
379 input_sync(hp_wmi_input_dev);
380 break;
381 } 396 }
382 } 397 }
383 398
399 set_bit(EV_SW, hp_wmi_input_dev->evbit);
400 set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
401 set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
402
403 /* Set initial hardware state */
404 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
405 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
406 hp_wmi_tablet_state());
407 input_sync(hp_wmi_input_dev);
408
384 err = input_register_device(hp_wmi_input_dev); 409 err = input_register_device(hp_wmi_input_dev);
385 410
386 if (err) { 411 if (err) {
@@ -397,6 +422,7 @@ static void cleanup_sysfs(struct platform_device *device)
397 device_remove_file(&device->dev, &dev_attr_hddtemp); 422 device_remove_file(&device->dev, &dev_attr_hddtemp);
398 device_remove_file(&device->dev, &dev_attr_als); 423 device_remove_file(&device->dev, &dev_attr_als);
399 device_remove_file(&device->dev, &dev_attr_dock); 424 device_remove_file(&device->dev, &dev_attr_dock);
425 device_remove_file(&device->dev, &dev_attr_tablet);
400} 426}
401 427
402static int __init hp_wmi_bios_setup(struct platform_device *device) 428static int __init hp_wmi_bios_setup(struct platform_device *device)
@@ -416,6 +442,9 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
416 err = device_create_file(&device->dev, &dev_attr_dock); 442 err = device_create_file(&device->dev, &dev_attr_dock);
417 if (err) 443 if (err)
418 goto add_sysfs_error; 444 goto add_sysfs_error;
445 err = device_create_file(&device->dev, &dev_attr_tablet);
446 if (err)
447 goto add_sysfs_error;
419 448
420 if (wireless & 0x1) { 449 if (wireless & 0x1) {
421 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 450 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
@@ -485,23 +514,17 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
485 514
486static int hp_wmi_resume_handler(struct platform_device *device) 515static int hp_wmi_resume_handler(struct platform_device *device)
487{ 516{
488 struct key_entry *key;
489
490 /* 517 /*
491 * Docking state may have changed while suspended, so trigger 518 * Hardware state may have changed while suspended, so trigger
492 * an input event for the current state. As this is a switch, 519 * input events for the current state. As this is a switch,
493 * the input layer will only actually pass it on if the state 520 * the input layer will only actually pass it on if the state
494 * changed. 521 * changed.
495 */ 522 */
496 for (key = hp_wmi_keymap; key->type != KE_END; key++) { 523
497 switch (key->type) { 524 input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
498 case KE_SW: 525 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
499 input_report_switch(hp_wmi_input_dev, key->keycode, 526 hp_wmi_tablet_state());
500 hp_wmi_dock_state()); 527 input_sync(hp_wmi_input_dev);
501 input_sync(hp_wmi_input_dev);
502 break;
503 }
504 }
505 528
506 return 0; 529 return 0;
507} 530}
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 86e958539f46..a463fd72c495 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -22,7 +22,7 @@
22 */ 22 */
23 23
24#define TPACPI_VERSION "0.23" 24#define TPACPI_VERSION "0.23"
25#define TPACPI_SYSFS_VERSION 0x020300 25#define TPACPI_SYSFS_VERSION 0x020400
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -257,6 +257,8 @@ static struct {
257 u32 wan:1; 257 u32 wan:1;
258 u32 uwb:1; 258 u32 uwb:1;
259 u32 fan_ctrl_status_undef:1; 259 u32 fan_ctrl_status_undef:1;
260 u32 second_fan:1;
261 u32 beep_needs_two_args:1;
260 u32 input_device_registered:1; 262 u32 input_device_registered:1;
261 u32 platform_drv_registered:1; 263 u32 platform_drv_registered:1;
262 u32 platform_drv_attrs_registered:1; 264 u32 platform_drv_attrs_registered:1;
@@ -277,8 +279,10 @@ struct thinkpad_id_data {
277 char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ 279 char *bios_version_str; /* Something like 1ZET51WW (1.03z) */
278 char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ 280 char *ec_version_str; /* Something like 1ZHT51WW-1.04a */
279 281
280 u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ 282 u16 bios_model; /* 1Y = 0x5931, 0 = unknown */
281 u16 ec_model; 283 u16 ec_model;
284 u16 bios_release; /* 1ZETK1WW = 0x314b, 0 = unknown */
285 u16 ec_release;
282 286
283 char *model_str; /* ThinkPad T43 */ 287 char *model_str; /* ThinkPad T43 */
284 char *nummodel_str; /* 9384A9C for a 9384-A9C model */ 288 char *nummodel_str; /* 9384A9C for a 9384-A9C model */
@@ -355,6 +359,73 @@ static void tpacpi_log_usertask(const char * const what)
355 } \ 359 } \
356 } while (0) 360 } while (0)
357 361
362/*
363 * Quirk handling helpers
364 *
365 * ThinkPad IDs and versions seen in the field so far
366 * are two-characters from the set [0-9A-Z], i.e. base 36.
367 *
368 * We use values well outside that range as specials.
369 */
370
371#define TPACPI_MATCH_ANY 0xffffU
372#define TPACPI_MATCH_UNKNOWN 0U
373
374/* TPID('1', 'Y') == 0x5931 */
375#define TPID(__c1, __c2) (((__c2) << 8) | (__c1))
376
377#define TPACPI_Q_IBM(__id1, __id2, __quirk) \
378 { .vendor = PCI_VENDOR_ID_IBM, \
379 .bios = TPID(__id1, __id2), \
380 .ec = TPACPI_MATCH_ANY, \
381 .quirks = (__quirk) }
382
383#define TPACPI_Q_LNV(__id1, __id2, __quirk) \
384 { .vendor = PCI_VENDOR_ID_LENOVO, \
385 .bios = TPID(__id1, __id2), \
386 .ec = TPACPI_MATCH_ANY, \
387 .quirks = (__quirk) }
388
389struct tpacpi_quirk {
390 unsigned int vendor;
391 u16 bios;
392 u16 ec;
393 unsigned long quirks;
394};
395
396/**
397 * tpacpi_check_quirks() - search BIOS/EC version on a list
398 * @qlist: array of &struct tpacpi_quirk
399 * @qlist_size: number of elements in @qlist
400 *
401 * Iterates over a quirks list until one is found that matches the
402 * ThinkPad's vendor, BIOS and EC model.
403 *
404 * Returns 0 if nothing matches, otherwise returns the quirks field of
405 * the matching &struct tpacpi_quirk entry.
406 *
407 * The match criteria is: vendor, ec and bios much match.
408 */
409static unsigned long __init tpacpi_check_quirks(
410 const struct tpacpi_quirk *qlist,
411 unsigned int qlist_size)
412{
413 while (qlist_size) {
414 if ((qlist->vendor == thinkpad_id.vendor ||
415 qlist->vendor == TPACPI_MATCH_ANY) &&
416 (qlist->bios == thinkpad_id.bios_model ||
417 qlist->bios == TPACPI_MATCH_ANY) &&
418 (qlist->ec == thinkpad_id.ec_model ||
419 qlist->ec == TPACPI_MATCH_ANY))
420 return qlist->quirks;
421
422 qlist_size--;
423 qlist++;
424 }
425 return 0;
426}
427
428
358/**************************************************************************** 429/****************************************************************************
359 **************************************************************************** 430 ****************************************************************************
360 * 431 *
@@ -1163,8 +1234,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1163{ 1234{
1164 struct tpacpi_rfk *atp_rfk; 1235 struct tpacpi_rfk *atp_rfk;
1165 int res; 1236 int res;
1166 bool initial_sw_state = false; 1237 bool sw_state = false;
1167 int initial_sw_status; 1238 int sw_status;
1168 1239
1169 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); 1240 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
1170 1241
@@ -1185,17 +1256,17 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1185 atp_rfk->id = id; 1256 atp_rfk->id = id;
1186 atp_rfk->ops = tp_rfkops; 1257 atp_rfk->ops = tp_rfkops;
1187 1258
1188 initial_sw_status = (tp_rfkops->get_status)(); 1259 sw_status = (tp_rfkops->get_status)();
1189 if (initial_sw_status < 0) { 1260 if (sw_status < 0) {
1190 printk(TPACPI_ERR 1261 printk(TPACPI_ERR
1191 "failed to read initial state for %s, error %d\n", 1262 "failed to read initial state for %s, error %d\n",
1192 name, initial_sw_status); 1263 name, sw_status);
1193 } else { 1264 } else {
1194 initial_sw_state = (initial_sw_status == TPACPI_RFK_RADIO_OFF); 1265 sw_state = (sw_status == TPACPI_RFK_RADIO_OFF);
1195 if (set_default) { 1266 if (set_default) {
1196 /* try to keep the initial state, since we ask the 1267 /* try to keep the initial state, since we ask the
1197 * firmware to preserve it across S5 in NVRAM */ 1268 * firmware to preserve it across S5 in NVRAM */
1198 rfkill_set_sw_state(atp_rfk->rfkill, initial_sw_state); 1269 rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
1199 } 1270 }
1200 } 1271 }
1201 rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); 1272 rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state());
@@ -2880,7 +2951,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
2880 /* update bright_acpimode... */ 2951 /* update bright_acpimode... */
2881 tpacpi_check_std_acpi_brightness_support(); 2952 tpacpi_check_std_acpi_brightness_support();
2882 2953
2883 if (tp_features.bright_acpimode) { 2954 if (tp_features.bright_acpimode && acpi_video_backlight_support()) {
2884 printk(TPACPI_INFO 2955 printk(TPACPI_INFO
2885 "This ThinkPad has standard ACPI backlight " 2956 "This ThinkPad has standard ACPI backlight "
2886 "brightness control, supported by the ACPI " 2957 "brightness control, supported by the ACPI "
@@ -4773,7 +4844,7 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */
4773 "LED", /* all others */ 4844 "LED", /* all others */
4774 ); /* R30, R31 */ 4845 ); /* R30, R31 */
4775 4846
4776#define TPACPI_LED_NUMLEDS 8 4847#define TPACPI_LED_NUMLEDS 16
4777static struct tpacpi_led_classdev *tpacpi_leds; 4848static struct tpacpi_led_classdev *tpacpi_leds;
4778static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; 4849static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS];
4779static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = { 4850static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
@@ -4786,15 +4857,20 @@ static const char * const tpacpi_led_names[TPACPI_LED_NUMLEDS] = {
4786 "tpacpi::dock_batt", 4857 "tpacpi::dock_batt",
4787 "tpacpi::unknown_led", 4858 "tpacpi::unknown_led",
4788 "tpacpi::standby", 4859 "tpacpi::standby",
4860 "tpacpi::dock_status1",
4861 "tpacpi::dock_status2",
4862 "tpacpi::unknown_led2",
4863 "tpacpi::unknown_led3",
4864 "tpacpi::thinkvantage",
4789}; 4865};
4790#define TPACPI_SAFE_LEDS 0x0081U 4866#define TPACPI_SAFE_LEDS 0x1081U
4791 4867
4792static inline bool tpacpi_is_led_restricted(const unsigned int led) 4868static inline bool tpacpi_is_led_restricted(const unsigned int led)
4793{ 4869{
4794#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS 4870#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
4795 return false; 4871 return false;
4796#else 4872#else
4797 return (TPACPI_SAFE_LEDS & (1 << led)) == 0; 4873 return (1U & (TPACPI_SAFE_LEDS >> led)) == 0;
4798#endif 4874#endif
4799} 4875}
4800 4876
@@ -4956,6 +5032,10 @@ static int __init tpacpi_init_led(unsigned int led)
4956 5032
4957 tpacpi_leds[led].led = led; 5033 tpacpi_leds[led].led = led;
4958 5034
5035 /* LEDs with no name don't get registered */
5036 if (!tpacpi_led_names[led])
5037 return 0;
5038
4959 tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set; 5039 tpacpi_leds[led].led_classdev.brightness_set = &led_sysfs_set;
4960 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set; 5040 tpacpi_leds[led].led_classdev.blink_set = &led_sysfs_blink_set;
4961 if (led_supported == TPACPI_LED_570) 5041 if (led_supported == TPACPI_LED_570)
@@ -4974,10 +5054,59 @@ static int __init tpacpi_init_led(unsigned int led)
4974 return rc; 5054 return rc;
4975} 5055}
4976 5056
5057static const struct tpacpi_quirk led_useful_qtable[] __initconst = {
5058 TPACPI_Q_IBM('1', 'E', 0x009f), /* A30 */
5059 TPACPI_Q_IBM('1', 'N', 0x009f), /* A31 */
5060 TPACPI_Q_IBM('1', 'G', 0x009f), /* A31 */
5061
5062 TPACPI_Q_IBM('1', 'I', 0x0097), /* T30 */
5063 TPACPI_Q_IBM('1', 'R', 0x0097), /* T40, T41, T42, R50, R51 */
5064 TPACPI_Q_IBM('7', '0', 0x0097), /* T43, R52 */
5065 TPACPI_Q_IBM('1', 'Y', 0x0097), /* T43 */
5066 TPACPI_Q_IBM('1', 'W', 0x0097), /* R50e */
5067 TPACPI_Q_IBM('1', 'V', 0x0097), /* R51 */
5068 TPACPI_Q_IBM('7', '8', 0x0097), /* R51e */
5069 TPACPI_Q_IBM('7', '6', 0x0097), /* R52 */
5070
5071 TPACPI_Q_IBM('1', 'K', 0x00bf), /* X30 */
5072 TPACPI_Q_IBM('1', 'Q', 0x00bf), /* X31, X32 */
5073 TPACPI_Q_IBM('1', 'U', 0x00bf), /* X40 */
5074 TPACPI_Q_IBM('7', '4', 0x00bf), /* X41 */
5075 TPACPI_Q_IBM('7', '5', 0x00bf), /* X41t */
5076
5077 TPACPI_Q_IBM('7', '9', 0x1f97), /* T60 (1) */
5078 TPACPI_Q_IBM('7', '7', 0x1f97), /* Z60* (1) */
5079 TPACPI_Q_IBM('7', 'F', 0x1f97), /* Z61* (1) */
5080 TPACPI_Q_IBM('7', 'B', 0x1fb7), /* X60 (1) */
5081
5082 /* (1) - may have excess leds enabled on MSB */
5083
5084 /* Defaults (order matters, keep last, don't reorder!) */
5085 { /* Lenovo */
5086 .vendor = PCI_VENDOR_ID_LENOVO,
5087 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
5088 .quirks = 0x1fffU,
5089 },
5090 { /* IBM ThinkPads with no EC version string */
5091 .vendor = PCI_VENDOR_ID_IBM,
5092 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_UNKNOWN,
5093 .quirks = 0x00ffU,
5094 },
5095 { /* IBM ThinkPads with EC version string */
5096 .vendor = PCI_VENDOR_ID_IBM,
5097 .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY,
5098 .quirks = 0x00bfU,
5099 },
5100};
5101
5102#undef TPACPI_LEDQ_IBM
5103#undef TPACPI_LEDQ_LNV
5104
4977static int __init led_init(struct ibm_init_struct *iibm) 5105static int __init led_init(struct ibm_init_struct *iibm)
4978{ 5106{
4979 unsigned int i; 5107 unsigned int i;
4980 int rc; 5108 int rc;
5109 unsigned long useful_leds;
4981 5110
4982 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); 5111 vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n");
4983 5112
@@ -4999,6 +5128,9 @@ static int __init led_init(struct ibm_init_struct *iibm)
4999 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", 5128 vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n",
5000 str_supported(led_supported), led_supported); 5129 str_supported(led_supported), led_supported);
5001 5130
5131 if (led_supported == TPACPI_LED_NONE)
5132 return 1;
5133
5002 tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, 5134 tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS,
5003 GFP_KERNEL); 5135 GFP_KERNEL);
5004 if (!tpacpi_leds) { 5136 if (!tpacpi_leds) {
@@ -5006,8 +5138,12 @@ static int __init led_init(struct ibm_init_struct *iibm)
5006 return -ENOMEM; 5138 return -ENOMEM;
5007 } 5139 }
5008 5140
5141 useful_leds = tpacpi_check_quirks(led_useful_qtable,
5142 ARRAY_SIZE(led_useful_qtable));
5143
5009 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { 5144 for (i = 0; i < TPACPI_LED_NUMLEDS; i++) {
5010 if (!tpacpi_is_led_restricted(i)) { 5145 if (!tpacpi_is_led_restricted(i) &&
5146 test_bit(i, &useful_leds)) {
5011 rc = tpacpi_init_led(i); 5147 rc = tpacpi_init_led(i);
5012 if (rc < 0) { 5148 if (rc < 0) {
5013 led_exit(); 5149 led_exit();
@@ -5017,12 +5153,11 @@ static int __init led_init(struct ibm_init_struct *iibm)
5017 } 5153 }
5018 5154
5019#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS 5155#ifdef CONFIG_THINKPAD_ACPI_UNSAFE_LEDS
5020 if (led_supported != TPACPI_LED_NONE) 5156 printk(TPACPI_NOTICE
5021 printk(TPACPI_NOTICE 5157 "warning: userspace override of important "
5022 "warning: userspace override of important " 5158 "firmware LEDs is enabled\n");
5023 "firmware LEDs is enabled\n");
5024#endif 5159#endif
5025 return (led_supported != TPACPI_LED_NONE)? 0 : 1; 5160 return 0;
5026} 5161}
5027 5162
5028#define str_led_status(s) \ 5163#define str_led_status(s) \
@@ -5052,7 +5187,7 @@ static int led_read(char *p)
5052 } 5187 }
5053 5188
5054 len += sprintf(p + len, "commands:\t" 5189 len += sprintf(p + len, "commands:\t"
5055 "<led> on, <led> off, <led> blink (<led> is 0-7)\n"); 5190 "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
5056 5191
5057 return len; 5192 return len;
5058} 5193}
@@ -5067,7 +5202,7 @@ static int led_write(char *buf)
5067 return -ENODEV; 5202 return -ENODEV;
5068 5203
5069 while ((cmd = next_cmd(&buf))) { 5204 while ((cmd = next_cmd(&buf))) {
5070 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7) 5205 if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 15)
5071 return -EINVAL; 5206 return -EINVAL;
5072 5207
5073 if (strstr(cmd, "off")) { 5208 if (strstr(cmd, "off")) {
@@ -5101,8 +5236,17 @@ static struct ibm_struct led_driver_data = {
5101 5236
5102TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ 5237TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */
5103 5238
5239#define TPACPI_BEEP_Q1 0x0001
5240
5241static const struct tpacpi_quirk beep_quirk_table[] __initconst = {
5242 TPACPI_Q_IBM('I', 'M', TPACPI_BEEP_Q1), /* 570 */
5243 TPACPI_Q_IBM('I', 'U', TPACPI_BEEP_Q1), /* 570E - unverified */
5244};
5245
5104static int __init beep_init(struct ibm_init_struct *iibm) 5246static int __init beep_init(struct ibm_init_struct *iibm)
5105{ 5247{
5248 unsigned long quirks;
5249
5106 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); 5250 vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n");
5107 5251
5108 TPACPI_ACPIHANDLE_INIT(beep); 5252 TPACPI_ACPIHANDLE_INIT(beep);
@@ -5110,6 +5254,11 @@ static int __init beep_init(struct ibm_init_struct *iibm)
5110 vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n", 5254 vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n",
5111 str_supported(beep_handle != NULL)); 5255 str_supported(beep_handle != NULL));
5112 5256
5257 quirks = tpacpi_check_quirks(beep_quirk_table,
5258 ARRAY_SIZE(beep_quirk_table));
5259
5260 tp_features.beep_needs_two_args = !!(quirks & TPACPI_BEEP_Q1);
5261
5113 return (beep_handle)? 0 : 1; 5262 return (beep_handle)? 0 : 1;
5114} 5263}
5115 5264
@@ -5141,8 +5290,15 @@ static int beep_write(char *buf)
5141 /* beep_cmd set */ 5290 /* beep_cmd set */
5142 } else 5291 } else
5143 return -EINVAL; 5292 return -EINVAL;
5144 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd", beep_cmd, 0)) 5293 if (tp_features.beep_needs_two_args) {
5145 return -EIO; 5294 if (!acpi_evalf(beep_handle, NULL, NULL, "vdd",
5295 beep_cmd, 0))
5296 return -EIO;
5297 } else {
5298 if (!acpi_evalf(beep_handle, NULL, NULL, "vd",
5299 beep_cmd))
5300 return -EIO;
5301 }
5146 } 5302 }
5147 5303
5148 return 0; 5304 return 0;
@@ -5569,6 +5725,10 @@ static struct ibm_struct ecdump_driver_data = {
5569 * Bit 3-0: backlight brightness level 5725 * Bit 3-0: backlight brightness level
5570 * 5726 *
5571 * brightness_get_raw returns status data in the HBRV layout 5727 * brightness_get_raw returns status data in the HBRV layout
5728 *
5729 * WARNING: The X61 has been verified to use HBRV for something else, so
5730 * this should be used _only_ on IBM ThinkPads, and maybe with some careful
5731 * testing on the very early *60 Lenovo models...
5572 */ 5732 */
5573 5733
5574enum { 5734enum {
@@ -5869,6 +6029,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
5869 brightness_mode); 6029 brightness_mode);
5870 } 6030 }
5871 6031
6032 /* Safety */
6033 if (thinkpad_id.vendor != PCI_VENDOR_ID_IBM &&
6034 (brightness_mode == TPACPI_BRGHT_MODE_ECNVRAM ||
6035 brightness_mode == TPACPI_BRGHT_MODE_EC))
6036 return -EINVAL;
6037
5872 if (tpacpi_brightness_get_raw(&b) < 0) 6038 if (tpacpi_brightness_get_raw(&b) < 0)
5873 return 1; 6039 return 1;
5874 6040
@@ -6161,6 +6327,21 @@ static struct ibm_struct volume_driver_data = {
6161 * For firmware bugs, refer to: 6327 * For firmware bugs, refer to:
6162 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues 6328 * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues
6163 * 6329 *
6330 * ----
6331 *
6332 * ThinkPad EC register 0x31 bit 0 (only on select models)
6333 *
6334 * When bit 0 of EC register 0x31 is zero, the tachometer registers
6335 * show the speed of the main fan. When bit 0 of EC register 0x31
6336 * is one, the tachometer registers show the speed of the auxiliary
6337 * fan.
6338 *
6339 * Fan control seems to affect both fans, regardless of the state
6340 * of this bit.
6341 *
6342 * So far, only the firmware for the X60/X61 non-tablet versions
6343 * seem to support this (firmware TP-7M).
6344 *
6164 * TPACPI_FAN_WR_ACPI_FANS: 6345 * TPACPI_FAN_WR_ACPI_FANS:
6165 * ThinkPad X31, X40, X41. Not available in the X60. 6346 * ThinkPad X31, X40, X41. Not available in the X60.
6166 * 6347 *
@@ -6187,6 +6368,8 @@ enum { /* Fan control constants */
6187 fan_status_offset = 0x2f, /* EC register 0x2f */ 6368 fan_status_offset = 0x2f, /* EC register 0x2f */
6188 fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) 6369 fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM)
6189 * 0x84 must be read before 0x85 */ 6370 * 0x84 must be read before 0x85 */
6371 fan_select_offset = 0x31, /* EC register 0x31 (Firmware 7M)
6372 bit 0 selects which fan is active */
6190 6373
6191 TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ 6374 TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */
6192 TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ 6375 TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */
@@ -6249,30 +6432,18 @@ TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */
6249 * We assume 0x07 really means auto mode while this quirk is active, 6432 * We assume 0x07 really means auto mode while this quirk is active,
6250 * as this is far more likely than the ThinkPad being in level 7, 6433 * as this is far more likely than the ThinkPad being in level 7,
6251 * which is only used by the firmware during thermal emergencies. 6434 * which is only used by the firmware during thermal emergencies.
6435 *
6436 * Enable for TP-1Y (T43), TP-78 (R51e), TP-76 (R52),
6437 * TP-70 (T43, R52), which are known to be buggy.
6252 */ 6438 */
6253 6439
6254static void fan_quirk1_detect(void) 6440static void fan_quirk1_setup(void)
6255{ 6441{
6256 /* In some ThinkPads, neither the EC nor the ACPI
6257 * DSDT initialize the HFSP register, and it ends up
6258 * being initially set to 0x07 when it *could* be
6259 * either 0x07 or 0x80.
6260 *
6261 * Enable for TP-1Y (T43), TP-78 (R51e),
6262 * TP-76 (R52), TP-70 (T43, R52), which are known
6263 * to be buggy. */
6264 if (fan_control_initial_status == 0x07) { 6442 if (fan_control_initial_status == 0x07) {
6265 switch (thinkpad_id.ec_model) { 6443 printk(TPACPI_NOTICE
6266 case 0x5931: /* TP-1Y */ 6444 "fan_init: initial fan status is unknown, "
6267 case 0x3837: /* TP-78 */ 6445 "assuming it is in auto mode\n");
6268 case 0x3637: /* TP-76 */ 6446 tp_features.fan_ctrl_status_undef = 1;
6269 case 0x3037: /* TP-70 */
6270 printk(TPACPI_NOTICE
6271 "fan_init: initial fan status is unknown, "
6272 "assuming it is in auto mode\n");
6273 tp_features.fan_ctrl_status_undef = 1;
6274 ;;
6275 }
6276 } 6447 }
6277} 6448}
6278 6449
@@ -6292,6 +6463,38 @@ static void fan_quirk1_handle(u8 *fan_status)
6292 } 6463 }
6293} 6464}
6294 6465
6466/* Select main fan on X60/X61, NOOP on others */
6467static bool fan_select_fan1(void)
6468{
6469 if (tp_features.second_fan) {
6470 u8 val;
6471
6472 if (ec_read(fan_select_offset, &val) < 0)
6473 return false;
6474 val &= 0xFEU;
6475 if (ec_write(fan_select_offset, val) < 0)
6476 return false;
6477 }
6478 return true;
6479}
6480
6481/* Select secondary fan on X60/X61 */
6482static bool fan_select_fan2(void)
6483{
6484 u8 val;
6485
6486 if (!tp_features.second_fan)
6487 return false;
6488
6489 if (ec_read(fan_select_offset, &val) < 0)
6490 return false;
6491 val |= 0x01U;
6492 if (ec_write(fan_select_offset, val) < 0)
6493 return false;
6494
6495 return true;
6496}
6497
6295/* 6498/*
6296 * Call with fan_mutex held 6499 * Call with fan_mutex held
6297 */ 6500 */
@@ -6369,6 +6572,8 @@ static int fan_get_speed(unsigned int *speed)
6369 switch (fan_status_access_mode) { 6572 switch (fan_status_access_mode) {
6370 case TPACPI_FAN_RD_TPEC: 6573 case TPACPI_FAN_RD_TPEC:
6371 /* all except 570, 600e/x, 770e, 770x */ 6574 /* all except 570, 600e/x, 770e, 770x */
6575 if (unlikely(!fan_select_fan1()))
6576 return -EIO;
6372 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || 6577 if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
6373 !acpi_ec_read(fan_rpm_offset + 1, &hi))) 6578 !acpi_ec_read(fan_rpm_offset + 1, &hi)))
6374 return -EIO; 6579 return -EIO;
@@ -6385,6 +6590,34 @@ static int fan_get_speed(unsigned int *speed)
6385 return 0; 6590 return 0;
6386} 6591}
6387 6592
6593static int fan2_get_speed(unsigned int *speed)
6594{
6595 u8 hi, lo;
6596 bool rc;
6597
6598 switch (fan_status_access_mode) {
6599 case TPACPI_FAN_RD_TPEC:
6600 /* all except 570, 600e/x, 770e, 770x */
6601 if (unlikely(!fan_select_fan2()))
6602 return -EIO;
6603 rc = !acpi_ec_read(fan_rpm_offset, &lo) ||
6604 !acpi_ec_read(fan_rpm_offset + 1, &hi);
6605 fan_select_fan1(); /* play it safe */
6606 if (rc)
6607 return -EIO;
6608
6609 if (likely(speed))
6610 *speed = (hi << 8) | lo;
6611
6612 break;
6613
6614 default:
6615 return -ENXIO;
6616 }
6617
6618 return 0;
6619}
6620
6388static int fan_set_level(int level) 6621static int fan_set_level(int level)
6389{ 6622{
6390 if (!fan_control_allowed) 6623 if (!fan_control_allowed)
@@ -6790,6 +7023,25 @@ static struct device_attribute dev_attr_fan_fan1_input =
6790 __ATTR(fan1_input, S_IRUGO, 7023 __ATTR(fan1_input, S_IRUGO,
6791 fan_fan1_input_show, NULL); 7024 fan_fan1_input_show, NULL);
6792 7025
7026/* sysfs fan fan2_input ------------------------------------------------ */
7027static ssize_t fan_fan2_input_show(struct device *dev,
7028 struct device_attribute *attr,
7029 char *buf)
7030{
7031 int res;
7032 unsigned int speed;
7033
7034 res = fan2_get_speed(&speed);
7035 if (res < 0)
7036 return res;
7037
7038 return snprintf(buf, PAGE_SIZE, "%u\n", speed);
7039}
7040
7041static struct device_attribute dev_attr_fan_fan2_input =
7042 __ATTR(fan2_input, S_IRUGO,
7043 fan_fan2_input_show, NULL);
7044
6793/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ 7045/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */
6794static ssize_t fan_fan_watchdog_show(struct device_driver *drv, 7046static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
6795 char *buf) 7047 char *buf)
@@ -6823,6 +7075,7 @@ static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO,
6823static struct attribute *fan_attributes[] = { 7075static struct attribute *fan_attributes[] = {
6824 &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, 7076 &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr,
6825 &dev_attr_fan_fan1_input.attr, 7077 &dev_attr_fan_fan1_input.attr,
7078 NULL, /* for fan2_input */
6826 NULL 7079 NULL
6827}; 7080};
6828 7081
@@ -6830,9 +7083,36 @@ static const struct attribute_group fan_attr_group = {
6830 .attrs = fan_attributes, 7083 .attrs = fan_attributes,
6831}; 7084};
6832 7085
7086#define TPACPI_FAN_Q1 0x0001 /* Unitialized HFSP */
7087#define TPACPI_FAN_2FAN 0x0002 /* EC 0x31 bit 0 selects fan2 */
7088
7089#define TPACPI_FAN_QI(__id1, __id2, __quirks) \
7090 { .vendor = PCI_VENDOR_ID_IBM, \
7091 .bios = TPACPI_MATCH_ANY, \
7092 .ec = TPID(__id1, __id2), \
7093 .quirks = __quirks }
7094
7095#define TPACPI_FAN_QL(__id1, __id2, __quirks) \
7096 { .vendor = PCI_VENDOR_ID_LENOVO, \
7097 .bios = TPACPI_MATCH_ANY, \
7098 .ec = TPID(__id1, __id2), \
7099 .quirks = __quirks }
7100
7101static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
7102 TPACPI_FAN_QI('1', 'Y', TPACPI_FAN_Q1),
7103 TPACPI_FAN_QI('7', '8', TPACPI_FAN_Q1),
7104 TPACPI_FAN_QI('7', '6', TPACPI_FAN_Q1),
7105 TPACPI_FAN_QI('7', '0', TPACPI_FAN_Q1),
7106 TPACPI_FAN_QL('7', 'M', TPACPI_FAN_2FAN),
7107};
7108
7109#undef TPACPI_FAN_QL
7110#undef TPACPI_FAN_QI
7111
6833static int __init fan_init(struct ibm_init_struct *iibm) 7112static int __init fan_init(struct ibm_init_struct *iibm)
6834{ 7113{
6835 int rc; 7114 int rc;
7115 unsigned long quirks;
6836 7116
6837 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN, 7117 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
6838 "initializing fan subdriver\n"); 7118 "initializing fan subdriver\n");
@@ -6843,12 +7123,16 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6843 fan_control_commands = 0; 7123 fan_control_commands = 0;
6844 fan_watchdog_maxinterval = 0; 7124 fan_watchdog_maxinterval = 0;
6845 tp_features.fan_ctrl_status_undef = 0; 7125 tp_features.fan_ctrl_status_undef = 0;
7126 tp_features.second_fan = 0;
6846 fan_control_desired_level = 7; 7127 fan_control_desired_level = 7;
6847 7128
6848 TPACPI_ACPIHANDLE_INIT(fans); 7129 TPACPI_ACPIHANDLE_INIT(fans);
6849 TPACPI_ACPIHANDLE_INIT(gfan); 7130 TPACPI_ACPIHANDLE_INIT(gfan);
6850 TPACPI_ACPIHANDLE_INIT(sfan); 7131 TPACPI_ACPIHANDLE_INIT(sfan);
6851 7132
7133 quirks = tpacpi_check_quirks(fan_quirk_table,
7134 ARRAY_SIZE(fan_quirk_table));
7135
6852 if (gfan_handle) { 7136 if (gfan_handle) {
6853 /* 570, 600e/x, 770e, 770x */ 7137 /* 570, 600e/x, 770e, 770x */
6854 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; 7138 fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN;
@@ -6858,7 +7142,13 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6858 if (likely(acpi_ec_read(fan_status_offset, 7142 if (likely(acpi_ec_read(fan_status_offset,
6859 &fan_control_initial_status))) { 7143 &fan_control_initial_status))) {
6860 fan_status_access_mode = TPACPI_FAN_RD_TPEC; 7144 fan_status_access_mode = TPACPI_FAN_RD_TPEC;
6861 fan_quirk1_detect(); 7145 if (quirks & TPACPI_FAN_Q1)
7146 fan_quirk1_setup();
7147 if (quirks & TPACPI_FAN_2FAN) {
7148 tp_features.second_fan = 1;
7149 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
7150 "secondary fan support enabled\n");
7151 }
6862 } else { 7152 } else {
6863 printk(TPACPI_ERR 7153 printk(TPACPI_ERR
6864 "ThinkPad ACPI EC access misbehaving, " 7154 "ThinkPad ACPI EC access misbehaving, "
@@ -6914,6 +7204,11 @@ static int __init fan_init(struct ibm_init_struct *iibm)
6914 7204
6915 if (fan_status_access_mode != TPACPI_FAN_NONE || 7205 if (fan_status_access_mode != TPACPI_FAN_NONE ||
6916 fan_control_access_mode != TPACPI_FAN_WR_NONE) { 7206 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
7207 if (tp_features.second_fan) {
7208 /* attach second fan tachometer */
7209 fan_attributes[ARRAY_SIZE(fan_attributes)-2] =
7210 &dev_attr_fan_fan2_input.attr;
7211 }
6917 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, 7212 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
6918 &fan_attr_group); 7213 &fan_attr_group);
6919 if (rc < 0) 7214 if (rc < 0)
@@ -7385,6 +7680,24 @@ err_out:
7385 7680
7386/* Probing */ 7681/* Probing */
7387 7682
7683static bool __pure __init tpacpi_is_fw_digit(const char c)
7684{
7685 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z');
7686}
7687
7688/* Most models: xxyTkkWW (#.##c); Ancient 570/600 and -SL lacks (#.##c) */
7689static bool __pure __init tpacpi_is_valid_fw_id(const char* const s,
7690 const char t)
7691{
7692 return s && strlen(s) >= 8 &&
7693 tpacpi_is_fw_digit(s[0]) &&
7694 tpacpi_is_fw_digit(s[1]) &&
7695 s[2] == t && s[3] == 'T' &&
7696 tpacpi_is_fw_digit(s[4]) &&
7697 tpacpi_is_fw_digit(s[5]) &&
7698 s[6] == 'W' && s[7] == 'W';
7699}
7700
7388/* returns 0 - probe ok, or < 0 - probe error. 7701/* returns 0 - probe ok, or < 0 - probe error.
7389 * Probe ok doesn't mean thinkpad found. 7702 * Probe ok doesn't mean thinkpad found.
7390 * On error, kfree() cleanup on tp->* is not performed, caller must do it */ 7703 * On error, kfree() cleanup on tp->* is not performed, caller must do it */
@@ -7411,10 +7724,15 @@ static int __must_check __init get_thinkpad_model_data(
7411 tp->bios_version_str = kstrdup(s, GFP_KERNEL); 7724 tp->bios_version_str = kstrdup(s, GFP_KERNEL);
7412 if (s && !tp->bios_version_str) 7725 if (s && !tp->bios_version_str)
7413 return -ENOMEM; 7726 return -ENOMEM;
7414 if (!tp->bios_version_str) 7727
7728 /* Really ancient ThinkPad 240X will fail this, which is fine */
7729 if (!tpacpi_is_valid_fw_id(tp->bios_version_str, 'E'))
7415 return 0; 7730 return 0;
7731
7416 tp->bios_model = tp->bios_version_str[0] 7732 tp->bios_model = tp->bios_version_str[0]
7417 | (tp->bios_version_str[1] << 8); 7733 | (tp->bios_version_str[1] << 8);
7734 tp->bios_release = (tp->bios_version_str[4] << 8)
7735 | tp->bios_version_str[5];
7418 7736
7419 /* 7737 /*
7420 * ThinkPad T23 or newer, A31 or newer, R50e or newer, 7738 * ThinkPad T23 or newer, A31 or newer, R50e or newer,
@@ -7433,8 +7751,21 @@ static int __must_check __init get_thinkpad_model_data(
7433 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); 7751 tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL);
7434 if (!tp->ec_version_str) 7752 if (!tp->ec_version_str)
7435 return -ENOMEM; 7753 return -ENOMEM;
7436 tp->ec_model = ec_fw_string[0] 7754
7437 | (ec_fw_string[1] << 8); 7755 if (tpacpi_is_valid_fw_id(ec_fw_string, 'H')) {
7756 tp->ec_model = ec_fw_string[0]
7757 | (ec_fw_string[1] << 8);
7758 tp->ec_release = (ec_fw_string[4] << 8)
7759 | ec_fw_string[5];
7760 } else {
7761 printk(TPACPI_NOTICE
7762 "ThinkPad firmware release %s "
7763 "doesn't match the known patterns\n",
7764 ec_fw_string);
7765 printk(TPACPI_NOTICE
7766 "please report this to %s\n",
7767 TPACPI_MAIL);
7768 }
7438 break; 7769 break;
7439 } 7770 }
7440 } 7771 }