aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-18 23:24:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-18 23:24:55 -0500
commit385336e321c41b5174055c0194b60c19a27cc5c5 (patch)
treea0b1a7c27bdf97b26130610e6e02565146b54738
parentebcffcda311c357c18985c9a13ae2a32f9a0f655 (diff)
parent200db647112d9a0f1dce273604f949f916bd2426 (diff)
Merge tag 'platform-drivers-x86-v3.19-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86
Pull x86 platform driver update from Darren Hart: - thinkpad-acpi: Switch to software mute, cleanups - acerhdf: Bang-bang thermal governor, new models, cleanups - dell-laptop: New keyboard backlight support and documentation - toshiba_acpi: Keyboard backlight updates, hotkey handling - dell-wmi: Keypress filtering, WMI event processing - eeepc-laptop: Multiple cleanups, improved error handling, documentation - hp_wireless: Inform the user if hp_wireless_input_setup()/add() fails - misc: Code cleanups, quirks, various new IDs * tag 'platform-drivers-x86-v3.19-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (33 commits) platform/x86/acerhdf: Still depends on THERMAL Documentation: Add entry for dell-laptop sysfs interface acpi: Remove _OSI(Linux) for ThinkPads thinkpad-acpi: Try to use full software mute control acerhdf: minor clean up acerhdf: added critical trip point acerhdf: Use bang-bang thermal governor acerhdf: Adding support for new models acerhdf: Adding support for "manual mode" dell-smo8800: Add more ACPI ids and change description of driver platform: x86: dell-laptop: Add support for keyboard backlight toshiba_acpi: Add keyboard backlight mode change event toshiba_acpi: Change notify funtion to handle more events toshiba_acpi: Move hotkey enabling code to its own function dell-wmi: Don't report keypresses on keybord illumination change dell-wmi: Don't report keypresses for radio state changes hp_wireless: Inform the user if hp_wireless_input_setup()/add() fails toshiba-acpi: Add missing ID (TOS6207) Sony-laptop: Deletion of an unnecessary check before the function call "pci_dev_put" platform: x86: Deletion of checks before backlight_device_unregister() ...
-rw-r--r--Documentation/ABI/testing/sysfs-platform-dell-laptop60
-rw-r--r--drivers/acpi/blacklist.c54
-rw-r--r--drivers/platform/x86/Kconfig7
-rw-r--r--drivers/platform/x86/acerhdf.c265
-rw-r--r--drivers/platform/x86/asus-laptop.c3
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c9
-rw-r--r--drivers/platform/x86/asus-wmi.c3
-rw-r--r--drivers/platform/x86/dell-laptop.c1057
-rw-r--r--drivers/platform/x86/dell-smo8800.c10
-rw-r--r--drivers/platform/x86/dell-wmi.c176
-rw-r--r--drivers/platform/x86/eeepc-laptop.c213
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c6
-rw-r--r--drivers/platform/x86/hp-wireless.c3
-rw-r--r--drivers/platform/x86/hp_accel.c1
-rw-r--r--drivers/platform/x86/ideapad-laptop.c3
-rw-r--r--drivers/platform/x86/intel_ips.c2
-rw-r--r--drivers/platform/x86/intel_oaktrail.c3
-rw-r--r--drivers/platform/x86/msi-laptop.c2
-rw-r--r--drivers/platform/x86/msi-wmi.c3
-rw-r--r--drivers/platform/x86/sony-laptop.c6
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c116
-rw-r--r--drivers/platform/x86/toshiba_acpi.c166
22 files changed, 1767 insertions, 401 deletions
diff --git a/Documentation/ABI/testing/sysfs-platform-dell-laptop b/Documentation/ABI/testing/sysfs-platform-dell-laptop
new file mode 100644
index 000000000000..7969443ef0ef
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-dell-laptop
@@ -0,0 +1,60 @@
1What: /sys/class/leds/dell::kbd_backlight/als_setting
2Date: December 2014
3KernelVersion: 3.19
4Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>,
5 Pali Rohár <pali.rohar@gmail.com>
6Description:
7 This file allows to control the automatic keyboard
8 illumination mode on some systems that have an ambient
9 light sensor. Write 1 to this file to enable the auto
10 mode, 0 to disable it.
11
12What: /sys/class/leds/dell::kbd_backlight/start_triggers
13Date: December 2014
14KernelVersion: 3.19
15Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>,
16 Pali Rohár <pali.rohar@gmail.com>
17Description:
18 This file allows to control the input triggers that
19 turn on the keyboard backlight illumination that is
20 disabled because of inactivity.
21 Read the file to see the triggers available. The ones
22 enabled are preceded by '+', those disabled by '-'.
23
24 To enable a trigger, write its name preceded by '+' to
25 this file. To disable a trigger, write its name preceded
26 by '-' instead.
27
28 For example, to enable the keyboard as trigger run:
29 echo +keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers
30 To disable it:
31 echo -keyboard > /sys/class/leds/dell::kbd_backlight/start_triggers
32
33 Note that not all the available triggers can be configured.
34
35What: /sys/class/leds/dell::kbd_backlight/stop_timeout
36Date: December 2014
37KernelVersion: 3.19
38Contact: Gabriele Mazzotta <gabriele.mzt@gmail.com>,
39 Pali Rohár <pali.rohar@gmail.com>
40Description:
41 This file allows to specify the interval after which the
42 keyboard illumination is disabled because of inactivity.
43 The timeouts are expressed in seconds, minutes, hours and
44 days, for which the symbols are 's', 'm', 'h' and 'd'
45 respectively.
46
47 To configure the timeout, write to this file a value along
48 with any the above units. If no unit is specified, the value
49 is assumed to be expressed in seconds.
50
51 For example, to set the timeout to 10 minutes run:
52 echo 10m > /sys/class/leds/dell::kbd_backlight/stop_timeout
53
54 Note that when this file is read, the returned value might be
55 expressed in a different unit than the one used when the timeout
56 was set.
57
58 Also note that only some timeouts are supported and that
59 some systems might fall back to a specific timeout in case
60 an invalid timeout is written to this file.
diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c
index 7556e7c4a055..9b693d54c743 100644
--- a/drivers/acpi/blacklist.c
+++ b/drivers/acpi/blacklist.c
@@ -305,60 +305,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
305 */ 305 */
306 306
307 /* 307 /*
308 * Lenovo has a mix of systems OSI(Linux) situations
309 * and thus we can not wildcard the vendor.
310 *
311 * _OSI(Linux) helps sound
312 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
313 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
314 * T400, T500
315 * _OSI(Linux) has Linux specific hooks
316 * DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
317 * _OSI(Linux) is a NOP:
318 * DMI_MATCH(DMI_PRODUCT_VERSION, "3000 N100"),
319 * DMI_MATCH(DMI_PRODUCT_VERSION, "LENOVO3000 V100"),
320 */
321 {
322 .callback = dmi_enable_osi_linux,
323 .ident = "Lenovo ThinkPad R61",
324 .matches = {
325 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
326 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad R61"),
327 },
328 },
329 {
330 .callback = dmi_enable_osi_linux,
331 .ident = "Lenovo ThinkPad T61",
332 .matches = {
333 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
334 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T61"),
335 },
336 },
337 {
338 .callback = dmi_enable_osi_linux,
339 .ident = "Lenovo ThinkPad X61",
340 .matches = {
341 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
342 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X61"),
343 },
344 },
345 {
346 .callback = dmi_enable_osi_linux,
347 .ident = "Lenovo ThinkPad T400",
348 .matches = {
349 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
350 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T400"),
351 },
352 },
353 {
354 .callback = dmi_enable_osi_linux,
355 .ident = "Lenovo ThinkPad T500",
356 .matches = {
357 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
358 DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T500"),
359 },
360 },
361 /*
362 * Without this this EEEpc exports a non working WMI interface, with 308 * Without this this EEEpc exports a non working WMI interface, with
363 * this it exports a working "good old" eeepc_laptop interface, fixing 309 * this it exports a working "good old" eeepc_laptop interface, fixing
364 * both brightness control, and rfkill not working. 310 * both brightness control, and rfkill not working.
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index a2eabe6ff9ad..638e797037da 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -38,7 +38,8 @@ config ACER_WMI
38 38
39config ACERHDF 39config ACERHDF
40 tristate "Acer Aspire One temperature and fan driver" 40 tristate "Acer Aspire One temperature and fan driver"
41 depends on THERMAL && ACPI 41 depends on ACPI && THERMAL
42 select THERMAL_GOV_BANG_BANG
42 ---help--- 43 ---help---
43 This is a driver for Acer Aspire One netbooks. It allows to access 44 This is a driver for Acer Aspire One netbooks. It allows to access
44 the temperature sensor and to control the fan. 45 the temperature sensor and to control the fan.
@@ -128,10 +129,10 @@ config DELL_WMI_AIO
128 be called dell-wmi-aio. 129 be called dell-wmi-aio.
129 130
130config DELL_SMO8800 131config DELL_SMO8800
131 tristate "Dell Latitude freefall driver (ACPI SMO8800/SMO8810)" 132 tristate "Dell Latitude freefall driver (ACPI SMO88XX)"
132 depends on ACPI 133 depends on ACPI
133 ---help--- 134 ---help---
134 Say Y here if you want to support SMO8800/SMO8810 freefall device 135 Say Y here if you want to support SMO88XX freefall devices
135 on Dell Latitude laptops. 136 on Dell Latitude laptops.
136 137
137 To compile this driver as a module, choose M here: the module will 138 To compile this driver as a module, choose M here: the module will
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index aaf37c5f12f9..594c918b553d 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -50,7 +50,7 @@
50 */ 50 */
51#undef START_IN_KERNEL_MODE 51#undef START_IN_KERNEL_MODE
52 52
53#define DRV_VER "0.5.26" 53#define DRV_VER "0.7.0"
54 54
55/* 55/*
56 * According to the Atom N270 datasheet, 56 * According to the Atom N270 datasheet,
@@ -119,116 +119,152 @@ struct fancmd {
119 u8 cmd_auto; 119 u8 cmd_auto;
120}; 120};
121 121
122struct manualcmd {
123 u8 mreg;
124 u8 moff;
125};
126
127/* default register and command to disable fan in manual mode */
128static const struct manualcmd mcmd = {
129 .mreg = 0x94,
130 .moff = 0xff,
131};
132
122/* BIOS settings */ 133/* BIOS settings */
123struct bios_settings_t { 134struct bios_settings {
124 const char *vendor; 135 const char *vendor;
125 const char *product; 136 const char *product;
126 const char *version; 137 const char *version;
127 unsigned char fanreg; 138 u8 fanreg;
128 unsigned char tempreg; 139 u8 tempreg;
129 struct fancmd cmd; 140 struct fancmd cmd;
141 int mcmd_enable;
130}; 142};
131 143
132/* Register addresses and values for different BIOS versions */ 144/* Register addresses and values for different BIOS versions */
133static const struct bios_settings_t bios_tbl[] = { 145static const struct bios_settings bios_tbl[] = {
134 /* AOA110 */ 146 /* AOA110 */
135 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, 147 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00}, 0},
136 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, 148 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00}, 0},
137 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, 149 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00}, 0},
138 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, 150 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00}, 0},
139 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, 151 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00}, 0},
140 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, 152 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00}, 0},
141 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, 153 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00}, 0},
142 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, 154 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00}, 0},
143 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, 155 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00}, 0},
144 /* AOA150 */ 156 /* AOA150 */
145 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, 157 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x1f, 0x00}, 0},
146 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, 158 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00}, 0},
147 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, 159 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00}, 0},
148 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, 160 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00}, 0},
149 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, 161 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00}, 0},
150 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, 162 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00}, 0},
151 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, 163 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00}, 0},
152 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, 164 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00}, 0},
153 /* LT1005u */ 165 /* LT1005u */
154 {"Acer", "LT-10Q", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, 166 {"Acer", "LT-10Q", "v0.3310", 0x55, 0x58, {0x20, 0x00}, 0},
155 /* Acer 1410 */ 167 /* Acer 1410 */
156 {"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 168 {"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00}, 0},
157 {"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 169 {"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00}, 0},
158 {"Acer", "Aspire 1410", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 170 {"Acer", "Aspire 1410", "v0.3115", 0x55, 0x58, {0x9e, 0x00}, 0},
159 {"Acer", "Aspire 1410", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 171 {"Acer", "Aspire 1410", "v0.3117", 0x55, 0x58, {0x9e, 0x00}, 0},
160 {"Acer", "Aspire 1410", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 172 {"Acer", "Aspire 1410", "v0.3119", 0x55, 0x58, {0x9e, 0x00}, 0},
161 {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 173 {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x00}, 0},
162 {"Acer", "Aspire 1410", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 174 {"Acer", "Aspire 1410", "v1.3204", 0x55, 0x58, {0x9e, 0x00}, 0},
163 {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 175 {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00}, 0},
164 {"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 176 {"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00}, 0},
165 {"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 177 {"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00}, 0},
166 {"Acer", "Aspire 1410", "v1.3314", 0x55, 0x58, {0x9e, 0x00} }, 178 {"Acer", "Aspire 1410", "v1.3314", 0x55, 0x58, {0x9e, 0x00}, 0},
167 /* Acer 1810xx */ 179 /* Acer 1810xx */
168 {"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 180 {"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00}, 0},
169 {"Acer", "Aspire 1810T", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 181 {"Acer", "Aspire 1810T", "v0.3108", 0x55, 0x58, {0x9e, 0x00}, 0},
170 {"Acer", "Aspire 1810TZ", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 182 {"Acer", "Aspire 1810TZ", "v0.3113", 0x55, 0x58, {0x9e, 0x00}, 0},
171 {"Acer", "Aspire 1810T", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 183 {"Acer", "Aspire 1810T", "v0.3113", 0x55, 0x58, {0x9e, 0x00}, 0},
172 {"Acer", "Aspire 1810TZ", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 184 {"Acer", "Aspire 1810TZ", "v0.3115", 0x55, 0x58, {0x9e, 0x00}, 0},
173 {"Acer", "Aspire 1810T", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 185 {"Acer", "Aspire 1810T", "v0.3115", 0x55, 0x58, {0x9e, 0x00}, 0},
174 {"Acer", "Aspire 1810TZ", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 186 {"Acer", "Aspire 1810TZ", "v0.3117", 0x55, 0x58, {0x9e, 0x00}, 0},
175 {"Acer", "Aspire 1810T", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 187 {"Acer", "Aspire 1810T", "v0.3117", 0x55, 0x58, {0x9e, 0x00}, 0},
176 {"Acer", "Aspire 1810TZ", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 188 {"Acer", "Aspire 1810TZ", "v0.3119", 0x55, 0x58, {0x9e, 0x00}, 0},
177 {"Acer", "Aspire 1810T", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 189 {"Acer", "Aspire 1810T", "v0.3119", 0x55, 0x58, {0x9e, 0x00}, 0},
178 {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 190 {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x00}, 0},
179 {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 191 {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x00}, 0},
180 {"Acer", "Aspire 1810TZ", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 192 {"Acer", "Aspire 1810TZ", "v1.3204", 0x55, 0x58, {0x9e, 0x00}, 0},
181 {"Acer", "Aspire 1810T", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 193 {"Acer", "Aspire 1810T", "v1.3204", 0x55, 0x58, {0x9e, 0x00}, 0},
182 {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 194 {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x00}, 0},
183 {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 195 {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x00}, 0},
184 {"Acer", "Aspire 1810TZ", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 196 {"Acer", "Aspire 1810TZ", "v1.3308", 0x55, 0x58, {0x9e, 0x00}, 0},
185 {"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 197 {"Acer", "Aspire 1810T", "v1.3308", 0x55, 0x58, {0x9e, 0x00}, 0},
186 {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 198 {"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00}, 0},
187 {"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} }, 199 {"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00}, 0},
188 {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} }, 200 {"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00}, 0},
189 {"Acer", "Aspire 1810T", "v1.3314", 0x55, 0x58, {0x9e, 0x00} }, 201 {"Acer", "Aspire 1810T", "v1.3314", 0x55, 0x58, {0x9e, 0x00}, 0},
202 /* Acer 5755G */
203 {"Acer", "Aspire 5755G", "V1.20", 0xab, 0xb4, {0x00, 0x08}, 0},
204 {"Acer", "Aspire 5755G", "V1.21", 0xab, 0xb3, {0x00, 0x08}, 0},
205 /* Acer 521 */
206 {"Acer", "AO521", "V1.11", 0x55, 0x58, {0x1f, 0x00}, 0},
190 /* Acer 531 */ 207 /* Acer 531 */
191 {"Acer", "AO531h", "v0.3104", 0x55, 0x58, {0x20, 0x00} }, 208 {"Acer", "AO531h", "v0.3104", 0x55, 0x58, {0x20, 0x00}, 0},
192 {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} }, 209 {"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00}, 0},
193 {"Acer", "AO531h", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, 210 {"Acer", "AO531h", "v0.3304", 0x55, 0x58, {0x20, 0x00}, 0},
194 /* Acer 751 */ 211 /* Acer 751 */
195 {"Acer", "AO751h", "V0.3212", 0x55, 0x58, {0x21, 0x00} }, 212 {"Acer", "AO751h", "V0.3206", 0x55, 0x58, {0x21, 0x00}, 0},
213 {"Acer", "AO751h", "V0.3212", 0x55, 0x58, {0x21, 0x00}, 0},
214 /* Acer 753 */
215 {"Acer", "Aspire One 753", "V1.24", 0x93, 0xac, {0x14, 0x04}, 1},
196 /* Acer 1825 */ 216 /* Acer 1825 */
197 {"Acer", "Aspire 1825PTZ", "V1.3118", 0x55, 0x58, {0x9e, 0x00} }, 217 {"Acer", "Aspire 1825PTZ", "V1.3118", 0x55, 0x58, {0x9e, 0x00}, 0},
198 {"Acer", "Aspire 1825PTZ", "V1.3127", 0x55, 0x58, {0x9e, 0x00} }, 218 {"Acer", "Aspire 1825PTZ", "V1.3127", 0x55, 0x58, {0x9e, 0x00}, 0},
219 /* Acer Extensa 5420 */
220 {"Acer", "Extensa 5420", "V1.17", 0x93, 0xac, {0x14, 0x04}, 1},
221 /* Acer Aspire 5315 */
222 {"Acer", "Aspire 5315", "V1.19", 0x93, 0xac, {0x14, 0x04}, 1},
223 /* Acer Aspire 5739 */
224 {"Acer", "Aspire 5739G", "V1.3311", 0x55, 0x58, {0x20, 0x00}, 0},
199 /* Acer TravelMate 7730 */ 225 /* Acer TravelMate 7730 */
200 {"Acer", "TravelMate 7730G", "v0.3509", 0x55, 0x58, {0xaf, 0x00} }, 226 {"Acer", "TravelMate 7730G", "v0.3509", 0x55, 0x58, {0xaf, 0x00}, 0},
227 /* Acer TravelMate TM8573T */
228 {"Acer", "TM8573T", "V1.13", 0x93, 0xa8, {0x14, 0x04}, 1},
201 /* Gateway */ 229 /* Gateway */
202 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, 230 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00}, 0},
203 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, 231 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00}, 0},
204 {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00} }, 232 {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00}, 0},
205 {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00} }, 233 {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00}, 0},
206 {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00} }, 234 {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00}, 0},
207 {"Gateway", "LT31", "v1.3303t", 0x55, 0x58, {0x9e, 0x00} }, 235 {"Gateway", "LT31", "v1.3303t", 0x55, 0x58, {0x9e, 0x00}, 0},
208 /* Packard Bell */ 236 /* Packard Bell */
209 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, 237 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00}, 0},
210 {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, 238 {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00}, 0},
211 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, 239 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00}, 0},
212 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, 240 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00}, 0},
213 {"Packard Bell", "ENBFT", "V1.3118", 0x55, 0x58, {0x9e, 0x00} }, 241 {"Packard Bell", "ENBFT", "V1.3118", 0x55, 0x58, {0x9e, 0x00}, 0},
214 {"Packard Bell", "ENBFT", "V1.3127", 0x55, 0x58, {0x9e, 0x00} }, 242 {"Packard Bell", "ENBFT", "V1.3127", 0x55, 0x58, {0x9e, 0x00}, 0},
215 {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00} }, 243 {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00}, 0},
216 {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00} }, 244 {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00}, 0},
217 {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00} }, 245 {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00}, 0},
218 {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00} }, 246 {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00}, 0},
219 {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00} }, 247 {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00}, 0},
220 {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00} }, 248 {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00}, 0},
221 {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00} }, 249 {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00}, 0},
222 {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00} }, 250 {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00}, 0},
223 {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00} }, 251 {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00}, 0},
224 {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00} }, 252 {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00}, 0},
225 {"Packard Bell", "DOTMA", "v1.3303t", 0x55, 0x58, {0x9e, 0x00} }, 253 {"Packard Bell", "DOTMA", "v1.3303t", 0x55, 0x58, {0x9e, 0x00}, 0},
226 {"Packard Bell", "DOTVR46", "v1.3308", 0x55, 0x58, {0x9e, 0x00} }, 254 {"Packard Bell", "DOTVR46", "v1.3308", 0x55, 0x58, {0x9e, 0x00}, 0},
227 /* pewpew-terminator */ 255 /* pewpew-terminator */
228 {"", "", "", 0, 0, {0, 0} } 256 {"", "", "", 0, 0, {0, 0}, 0}
229}; 257};
230 258
231static const struct bios_settings_t *bios_cfg __read_mostly; 259static const struct bios_settings *bios_cfg __read_mostly;
260
261/*
262 * this struct is used to instruct thermal layer to use bang_bang instead of
263 * default governor for acerhdf
264 */
265static struct thermal_zone_params acerhdf_zone_params = {
266 .governor_name = "bang_bang",
267};
232 268
233static int acerhdf_get_temp(int *temp) 269static int acerhdf_get_temp(int *temp)
234{ 270{
@@ -275,6 +311,12 @@ static void acerhdf_change_fanstate(int state)
275 fanstate = state; 311 fanstate = state;
276 312
277 ec_write(bios_cfg->fanreg, cmd); 313 ec_write(bios_cfg->fanreg, cmd);
314
315 if (bios_cfg->mcmd_enable && state == ACERHDF_FAN_OFF) {
316 if (verbose)
317 pr_notice("turning off fan manually\n");
318 ec_write(mcmd.mreg, mcmd.moff);
319 }
278} 320}
279 321
280static void acerhdf_check_param(struct thermal_zone_device *thermal) 322static void acerhdf_check_param(struct thermal_zone_device *thermal)
@@ -401,6 +443,21 @@ static int acerhdf_get_trip_type(struct thermal_zone_device *thermal, int trip,
401{ 443{
402 if (trip == 0) 444 if (trip == 0)
403 *type = THERMAL_TRIP_ACTIVE; 445 *type = THERMAL_TRIP_ACTIVE;
446 else if (trip == 1)
447 *type = THERMAL_TRIP_CRITICAL;
448 else
449 return -EINVAL;
450
451 return 0;
452}
453
454static int acerhdf_get_trip_hyst(struct thermal_zone_device *thermal, int trip,
455 unsigned long *temp)
456{
457 if (trip != 0)
458 return -EINVAL;
459
460 *temp = fanon - fanoff;
404 461
405 return 0; 462 return 0;
406} 463}
@@ -410,6 +467,10 @@ static int acerhdf_get_trip_temp(struct thermal_zone_device *thermal, int trip,
410{ 467{
411 if (trip == 0) 468 if (trip == 0)
412 *temp = fanon; 469 *temp = fanon;
470 else if (trip == 1)
471 *temp = ACERHDF_TEMP_CRIT;
472 else
473 return -EINVAL;
413 474
414 return 0; 475 return 0;
415} 476}
@@ -429,6 +490,7 @@ static struct thermal_zone_device_ops acerhdf_dev_ops = {
429 .get_mode = acerhdf_get_mode, 490 .get_mode = acerhdf_get_mode,
430 .set_mode = acerhdf_set_mode, 491 .set_mode = acerhdf_set_mode,
431 .get_trip_type = acerhdf_get_trip_type, 492 .get_trip_type = acerhdf_get_trip_type,
493 .get_trip_hyst = acerhdf_get_trip_hyst,
432 .get_trip_temp = acerhdf_get_trip_temp, 494 .get_trip_temp = acerhdf_get_trip_temp,
433 .get_crit_temp = acerhdf_get_crit_temp, 495 .get_crit_temp = acerhdf_get_crit_temp,
434}; 496};
@@ -481,9 +543,7 @@ static int acerhdf_set_cur_state(struct thermal_cooling_device *cdev,
481 } 543 }
482 544
483 if (state == 0) { 545 if (state == 0) {
484 /* turn fan off only if below fanoff temperature */ 546 if (cur_state == ACERHDF_FAN_AUTO)
485 if ((cur_state == ACERHDF_FAN_AUTO) &&
486 (cur_temp < fanoff))
487 acerhdf_change_fanstate(ACERHDF_FAN_OFF); 547 acerhdf_change_fanstate(ACERHDF_FAN_OFF);
488 } else { 548 } else {
489 if (cur_state == ACERHDF_FAN_OFF) 549 if (cur_state == ACERHDF_FAN_OFF)
@@ -558,7 +618,7 @@ static int str_starts_with(const char *str, const char *start)
558static int acerhdf_check_hardware(void) 618static int acerhdf_check_hardware(void)
559{ 619{
560 char const *vendor, *version, *product; 620 char const *vendor, *version, *product;
561 const struct bios_settings_t *bt = NULL; 621 const struct bios_settings *bt = NULL;
562 622
563 /* get BIOS data */ 623 /* get BIOS data */
564 vendor = dmi_get_system_info(DMI_SYS_VENDOR); 624 vendor = dmi_get_system_info(DMI_SYS_VENDOR);
@@ -660,12 +720,20 @@ static int acerhdf_register_thermal(void)
660 if (IS_ERR(cl_dev)) 720 if (IS_ERR(cl_dev))
661 return -EINVAL; 721 return -EINVAL;
662 722
663 thz_dev = thermal_zone_device_register("acerhdf", 1, 0, NULL, 723 thz_dev = thermal_zone_device_register("acerhdf", 2, 0, NULL,
664 &acerhdf_dev_ops, NULL, 0, 724 &acerhdf_dev_ops,
725 &acerhdf_zone_params, 0,
665 (kernelmode) ? interval*1000 : 0); 726 (kernelmode) ? interval*1000 : 0);
666 if (IS_ERR(thz_dev)) 727 if (IS_ERR(thz_dev))
667 return -EINVAL; 728 return -EINVAL;
668 729
730 if (strcmp(thz_dev->governor->name,
731 acerhdf_zone_params.governor_name)) {
732 pr_err("Didn't get thermal governor %s, perhaps not compiled into thermal subsystem.\n",
733 acerhdf_zone_params.governor_name);
734 return -EINVAL;
735 }
736
669 return 0; 737 return 0;
670} 738}
671 739
@@ -722,9 +790,15 @@ MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
722MODULE_ALIAS("dmi:*:*Acer*:pnAO751h*:"); 790MODULE_ALIAS("dmi:*:*Acer*:pnAO751h*:");
723MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:"); 791MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
724MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:"); 792MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
793MODULE_ALIAS("dmi:*:*Acer*:pnAspire*5755G:");
725MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1825PTZ:"); 794MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1825PTZ:");
795MODULE_ALIAS("dmi:*:*Acer*:pnAO521*:");
726MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:"); 796MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
797MODULE_ALIAS("dmi:*:*Acer*:pnAspire*5739G:");
798MODULE_ALIAS("dmi:*:*Acer*:pnAspire*One*753:");
799MODULE_ALIAS("dmi:*:*Acer*:pnAspire*5315:");
727MODULE_ALIAS("dmi:*:*Acer*:TravelMate*7730G:"); 800MODULE_ALIAS("dmi:*:*Acer*:TravelMate*7730G:");
801MODULE_ALIAS("dmi:*:*Acer*:TM8573T:");
728MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); 802MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
729MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); 803MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
730MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:"); 804MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
@@ -733,6 +807,7 @@ MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
733MODULE_ALIAS("dmi:*:*Packard*Bell*:pnENBFT*:"); 807MODULE_ALIAS("dmi:*:*Packard*Bell*:pnENBFT*:");
734MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:"); 808MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
735MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTVR46*:"); 809MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTVR46*:");
810MODULE_ALIAS("dmi:*:*Acer*:pnExtensa 5420*:");
736 811
737module_init(acerhdf_init); 812module_init(acerhdf_init);
738module_exit(acerhdf_exit); 813module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index 05647f1a427e..f71700e0d132 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -843,8 +843,7 @@ static int asus_backlight_init(struct asus_laptop *asus)
843 843
844static void asus_backlight_exit(struct asus_laptop *asus) 844static void asus_backlight_exit(struct asus_laptop *asus)
845{ 845{
846 if (asus->backlight_device) 846 backlight_device_unregister(asus->backlight_device);
847 backlight_device_unregister(asus->backlight_device);
848 asus->backlight_device = NULL; 847 asus->backlight_device = NULL;
849} 848}
850 849
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index c1a6cd66af42..abdaed34c728 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -191,6 +191,15 @@ static const struct dmi_system_id asus_quirks[] = {
191 }, 191 },
192 { 192 {
193 .callback = dmi_matched, 193 .callback = dmi_matched,
194 .ident = "ASUSTeK COMPUTER INC. X551CA",
195 .matches = {
196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
197 DMI_MATCH(DMI_PRODUCT_NAME, "X551CA"),
198 },
199 .driver_data = &quirk_asus_wapf4,
200 },
201 {
202 .callback = dmi_matched,
194 .ident = "ASUSTeK COMPUTER INC. X55A", 203 .ident = "ASUSTeK COMPUTER INC. X55A",
195 .matches = { 204 .matches = {
196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 205 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 21fc932da3a1..7543a56e0f45 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -1308,8 +1308,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
1308 1308
1309static void asus_wmi_backlight_exit(struct asus_wmi *asus) 1309static void asus_wmi_backlight_exit(struct asus_wmi *asus)
1310{ 1310{
1311 if (asus->backlight_device) 1311 backlight_device_unregister(asus->backlight_device);
1312 backlight_device_unregister(asus->backlight_device);
1313 1312
1314 asus->backlight_device = NULL; 1313 asus->backlight_device = NULL;
1315} 1314}
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index f6a28d7161f5..9411eae39a4e 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -2,9 +2,11 @@
2 * Driver for Dell laptop extras 2 * Driver for Dell laptop extras
3 * 3 *
4 * Copyright (c) Red Hat <mjg@redhat.com> 4 * Copyright (c) Red Hat <mjg@redhat.com>
5 * Copyright (c) 2014 Gabriele Mazzotta <gabriele.mzt@gmail.com>
6 * Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com>
5 * 7 *
6 * Based on documentation in the libsmbios package, Copyright (C) 2005 Dell 8 * Based on documentation in the libsmbios package:
7 * Inc. 9 * Copyright (C) 2005-2014 Dell Inc.
8 * 10 *
9 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
@@ -32,6 +34,13 @@
32#include "../../firmware/dcdbas.h" 34#include "../../firmware/dcdbas.h"
33 35
34#define BRIGHTNESS_TOKEN 0x7d 36#define BRIGHTNESS_TOKEN 0x7d
37#define KBD_LED_OFF_TOKEN 0x01E1
38#define KBD_LED_ON_TOKEN 0x01E2
39#define KBD_LED_AUTO_TOKEN 0x01E3
40#define KBD_LED_AUTO_25_TOKEN 0x02EA
41#define KBD_LED_AUTO_50_TOKEN 0x02EB
42#define KBD_LED_AUTO_75_TOKEN 0x02EC
43#define KBD_LED_AUTO_100_TOKEN 0x02F6
35 44
36/* This structure will be modified by the firmware when we enter 45/* This structure will be modified by the firmware when we enter
37 * system management mode, hence the volatiles */ 46 * system management mode, hence the volatiles */
@@ -62,6 +71,13 @@ struct calling_interface_structure {
62 71
63struct quirk_entry { 72struct quirk_entry {
64 u8 touchpad_led; 73 u8 touchpad_led;
74
75 int needs_kbd_timeouts;
76 /*
77 * Ordered list of timeouts expressed in seconds.
78 * The list must end with -1
79 */
80 int kbd_timeouts[];
65}; 81};
66 82
67static struct quirk_entry *quirks; 83static struct quirk_entry *quirks;
@@ -76,6 +92,15 @@ static int __init dmi_matched(const struct dmi_system_id *dmi)
76 return 1; 92 return 1;
77} 93}
78 94
95/*
96 * These values come from Windows utility provided by Dell. If any other value
97 * is used then BIOS silently set timeout to 0 without any error message.
98 */
99static struct quirk_entry quirk_dell_xps13_9333 = {
100 .needs_kbd_timeouts = 1,
101 .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 },
102};
103
79static int da_command_address; 104static int da_command_address;
80static int da_command_code; 105static int da_command_code;
81static int da_num_tokens; 106static int da_num_tokens;
@@ -267,6 +292,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
267 }, 292 },
268 .driver_data = &quirk_dell_vostro_v130, 293 .driver_data = &quirk_dell_vostro_v130,
269 }, 294 },
295 {
296 .callback = dmi_matched,
297 .ident = "Dell XPS13 9333",
298 .matches = {
299 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
300 DMI_MATCH(DMI_PRODUCT_NAME, "XPS13 9333"),
301 },
302 .driver_data = &quirk_dell_xps13_9333,
303 },
270 { } 304 { }
271}; 305};
272 306
@@ -331,17 +365,29 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
331 } 365 }
332} 366}
333 367
334static int find_token_location(int tokenid) 368static int find_token_id(int tokenid)
335{ 369{
336 int i; 370 int i;
371
337 for (i = 0; i < da_num_tokens; i++) { 372 for (i = 0; i < da_num_tokens; i++) {
338 if (da_tokens[i].tokenID == tokenid) 373 if (da_tokens[i].tokenID == tokenid)
339 return da_tokens[i].location; 374 return i;
340 } 375 }
341 376
342 return -1; 377 return -1;
343} 378}
344 379
380static int find_token_location(int tokenid)
381{
382 int id;
383
384 id = find_token_id(tokenid);
385 if (id == -1)
386 return -1;
387
388 return da_tokens[id].location;
389}
390
345static struct calling_interface_buffer * 391static struct calling_interface_buffer *
346dell_send_request(struct calling_interface_buffer *buffer, int class, 392dell_send_request(struct calling_interface_buffer *buffer, int class,
347 int select) 393 int select)
@@ -362,6 +408,20 @@ dell_send_request(struct calling_interface_buffer *buffer, int class,
362 return buffer; 408 return buffer;
363} 409}
364 410
411static inline int dell_smi_error(int value)
412{
413 switch (value) {
414 case 0: /* Completed successfully */
415 return 0;
416 case -1: /* Completed with error */
417 return -EIO;
418 case -2: /* Function not supported */
419 return -ENXIO;
420 default: /* Unknown error */
421 return -EINVAL;
422 }
423}
424
365/* Derived from information in DellWirelessCtl.cpp: 425/* Derived from information in DellWirelessCtl.cpp:
366 Class 17, select 11 is radio control. It returns an array of 32-bit values. 426 Class 17, select 11 is radio control. It returns an array of 32-bit values.
367 427
@@ -563,7 +623,7 @@ static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
563{ 623{
564 static bool extended; 624 static bool extended;
565 625
566 if (str & 0x20) 626 if (str & I8042_STR_AUXDATA)
567 return false; 627 return false;
568 628
569 if (unlikely(data == 0xe0)) { 629 if (unlikely(data == 0xe0)) {
@@ -716,7 +776,7 @@ static int dell_send_intensity(struct backlight_device *bd)
716 else 776 else
717 dell_send_request(buffer, 1, 1); 777 dell_send_request(buffer, 1, 1);
718 778
719out: 779 out:
720 release_buffer(); 780 release_buffer();
721 return ret; 781 return ret;
722} 782}
@@ -740,7 +800,7 @@ static int dell_get_intensity(struct backlight_device *bd)
740 800
741 ret = buffer->output[1]; 801 ret = buffer->output[1];
742 802
743out: 803 out:
744 release_buffer(); 804 release_buffer();
745 return ret; 805 return ret;
746} 806}
@@ -789,6 +849,984 @@ static void touchpad_led_exit(void)
789 led_classdev_unregister(&touchpad_led); 849 led_classdev_unregister(&touchpad_led);
790} 850}
791 851
852/*
853 * Derived from information in smbios-keyboard-ctl:
854 *
855 * cbClass 4
856 * cbSelect 11
857 * Keyboard illumination
858 * cbArg1 determines the function to be performed
859 *
860 * cbArg1 0x0 = Get Feature Information
861 * cbRES1 Standard return codes (0, -1, -2)
862 * cbRES2, word0 Bitmap of user-selectable modes
863 * bit 0 Always off (All systems)
864 * bit 1 Always on (Travis ATG, Siberia)
865 * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG)
866 * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off
867 * bit 4 Auto: Input-activity-based On; input-activity based Off
868 * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off
869 * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off
870 * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off
871 * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off
872 * bits 9-15 Reserved for future use
873 * cbRES2, byte2 Reserved for future use
874 * cbRES2, byte3 Keyboard illumination type
875 * 0 Reserved
876 * 1 Tasklight
877 * 2 Backlight
878 * 3-255 Reserved for future use
879 * cbRES3, byte0 Supported auto keyboard illumination trigger bitmap.
880 * bit 0 Any keystroke
881 * bit 1 Touchpad activity
882 * bit 2 Pointing stick
883 * bit 3 Any mouse
884 * bits 4-7 Reserved for future use
885 * cbRES3, byte1 Supported timeout unit bitmap
886 * bit 0 Seconds
887 * bit 1 Minutes
888 * bit 2 Hours
889 * bit 3 Days
890 * bits 4-7 Reserved for future use
891 * cbRES3, byte2 Number of keyboard light brightness levels
892 * cbRES4, byte0 Maximum acceptable seconds value (0 if seconds not supported).
893 * cbRES4, byte1 Maximum acceptable minutes value (0 if minutes not supported).
894 * cbRES4, byte2 Maximum acceptable hours value (0 if hours not supported).
895 * cbRES4, byte3 Maximum acceptable days value (0 if days not supported)
896 *
897 * cbArg1 0x1 = Get Current State
898 * cbRES1 Standard return codes (0, -1, -2)
899 * cbRES2, word0 Bitmap of current mode state
900 * bit 0 Always off (All systems)
901 * bit 1 Always on (Travis ATG, Siberia)
902 * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG)
903 * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off
904 * bit 4 Auto: Input-activity-based On; input-activity based Off
905 * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off
906 * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off
907 * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off
908 * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off
909 * bits 9-15 Reserved for future use
910 * Note: Only One bit can be set
911 * cbRES2, byte2 Currently active auto keyboard illumination triggers.
912 * bit 0 Any keystroke
913 * bit 1 Touchpad activity
914 * bit 2 Pointing stick
915 * bit 3 Any mouse
916 * bits 4-7 Reserved for future use
917 * cbRES2, byte3 Current Timeout
918 * bits 7:6 Timeout units indicator:
919 * 00b Seconds
920 * 01b Minutes
921 * 10b Hours
922 * 11b Days
923 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
924 * NOTE: A value of 0 means always on (no timeout) if any bits of RES3 byte
925 * are set upon return from the [Get feature information] call.
926 * cbRES3, byte0 Current setting of ALS value that turns the light on or off.
927 * cbRES3, byte1 Current ALS reading
928 * cbRES3, byte2 Current keyboard light level.
929 *
930 * cbArg1 0x2 = Set New State
931 * cbRES1 Standard return codes (0, -1, -2)
932 * cbArg2, word0 Bitmap of current mode state
933 * bit 0 Always off (All systems)
934 * bit 1 Always on (Travis ATG, Siberia)
935 * bit 2 Auto: ALS-based On; ALS-based Off (Travis ATG)
936 * bit 3 Auto: ALS- and input-activity-based On; input-activity based Off
937 * bit 4 Auto: Input-activity-based On; input-activity based Off
938 * bit 5 Auto: Input-activity-based On (illumination level 25%); input-activity based Off
939 * bit 6 Auto: Input-activity-based On (illumination level 50%); input-activity based Off
940 * bit 7 Auto: Input-activity-based On (illumination level 75%); input-activity based Off
941 * bit 8 Auto: Input-activity-based On (illumination level 100%); input-activity based Off
942 * bits 9-15 Reserved for future use
943 * Note: Only One bit can be set
944 * cbArg2, byte2 Desired auto keyboard illumination triggers. Must remain inactive to allow
945 * keyboard to turn off automatically.
946 * bit 0 Any keystroke
947 * bit 1 Touchpad activity
948 * bit 2 Pointing stick
949 * bit 3 Any mouse
950 * bits 4-7 Reserved for future use
951 * cbArg2, byte3 Desired Timeout
952 * bits 7:6 Timeout units indicator:
953 * 00b Seconds
954 * 01b Minutes
955 * 10b Hours
956 * 11b Days
957 * bits 5:0 Timeout value (0-63) in sec/min/hr/day
958 * cbArg3, byte0 Desired setting of ALS value that turns the light on or off.
959 * cbArg3, byte2 Desired keyboard light level.
960 */
961
962
963enum kbd_timeout_unit {
964 KBD_TIMEOUT_SECONDS = 0,
965 KBD_TIMEOUT_MINUTES,
966 KBD_TIMEOUT_HOURS,
967 KBD_TIMEOUT_DAYS,
968};
969
970enum kbd_mode_bit {
971 KBD_MODE_BIT_OFF = 0,
972 KBD_MODE_BIT_ON,
973 KBD_MODE_BIT_ALS,
974 KBD_MODE_BIT_TRIGGER_ALS,
975 KBD_MODE_BIT_TRIGGER,
976 KBD_MODE_BIT_TRIGGER_25,
977 KBD_MODE_BIT_TRIGGER_50,
978 KBD_MODE_BIT_TRIGGER_75,
979 KBD_MODE_BIT_TRIGGER_100,
980};
981
982#define kbd_is_als_mode_bit(bit) \
983 ((bit) == KBD_MODE_BIT_ALS || (bit) == KBD_MODE_BIT_TRIGGER_ALS)
984#define kbd_is_trigger_mode_bit(bit) \
985 ((bit) >= KBD_MODE_BIT_TRIGGER_ALS && (bit) <= KBD_MODE_BIT_TRIGGER_100)
986#define kbd_is_level_mode_bit(bit) \
987 ((bit) >= KBD_MODE_BIT_TRIGGER_25 && (bit) <= KBD_MODE_BIT_TRIGGER_100)
988
989struct kbd_info {
990 u16 modes;
991 u8 type;
992 u8 triggers;
993 u8 levels;
994 u8 seconds;
995 u8 minutes;
996 u8 hours;
997 u8 days;
998};
999
1000struct kbd_state {
1001 u8 mode_bit;
1002 u8 triggers;
1003 u8 timeout_value;
1004 u8 timeout_unit;
1005 u8 als_setting;
1006 u8 als_value;
1007 u8 level;
1008};
1009
1010static const int kbd_tokens[] = {
1011 KBD_LED_OFF_TOKEN,
1012 KBD_LED_AUTO_25_TOKEN,
1013 KBD_LED_AUTO_50_TOKEN,
1014 KBD_LED_AUTO_75_TOKEN,
1015 KBD_LED_AUTO_100_TOKEN,
1016 KBD_LED_ON_TOKEN,
1017};
1018
1019static u16 kbd_token_bits;
1020
1021static struct kbd_info kbd_info;
1022static bool kbd_als_supported;
1023static bool kbd_triggers_supported;
1024
1025static u8 kbd_mode_levels[16];
1026static int kbd_mode_levels_count;
1027
1028static u8 kbd_previous_level;
1029static u8 kbd_previous_mode_bit;
1030
1031static bool kbd_led_present;
1032
1033/*
1034 * NOTE: there are three ways to set the keyboard backlight level.
1035 * First, via kbd_state.mode_bit (assigning KBD_MODE_BIT_TRIGGER_* value).
1036 * Second, via kbd_state.level (assigning numerical value <= kbd_info.levels).
1037 * Third, via SMBIOS tokens (KBD_LED_* in kbd_tokens)
1038 *
1039 * There are laptops which support only one of these methods. If we want to
1040 * support as many machines as possible we need to implement all three methods.
1041 * The first two methods use the kbd_state structure. The third uses SMBIOS
1042 * tokens. If kbd_info.levels == 0, the machine does not support setting the
1043 * keyboard backlight level via kbd_state.level.
1044 */
1045
1046static int kbd_get_info(struct kbd_info *info)
1047{
1048 u8 units;
1049 int ret;
1050
1051 get_buffer();
1052
1053 buffer->input[0] = 0x0;
1054 dell_send_request(buffer, 4, 11);
1055 ret = buffer->output[0];
1056
1057 if (ret) {
1058 ret = dell_smi_error(ret);
1059 goto out;
1060 }
1061
1062 info->modes = buffer->output[1] & 0xFFFF;
1063 info->type = (buffer->output[1] >> 24) & 0xFF;
1064 info->triggers = buffer->output[2] & 0xFF;
1065 units = (buffer->output[2] >> 8) & 0xFF;
1066 info->levels = (buffer->output[2] >> 16) & 0xFF;
1067
1068 if (units & BIT(0))
1069 info->seconds = (buffer->output[3] >> 0) & 0xFF;
1070 if (units & BIT(1))
1071 info->minutes = (buffer->output[3] >> 8) & 0xFF;
1072 if (units & BIT(2))
1073 info->hours = (buffer->output[3] >> 16) & 0xFF;
1074 if (units & BIT(3))
1075 info->days = (buffer->output[3] >> 24) & 0xFF;
1076
1077 out:
1078 release_buffer();
1079 return ret;
1080}
1081
1082static unsigned int kbd_get_max_level(void)
1083{
1084 if (kbd_info.levels != 0)
1085 return kbd_info.levels;
1086 if (kbd_mode_levels_count > 0)
1087 return kbd_mode_levels_count - 1;
1088 return 0;
1089}
1090
1091static int kbd_get_level(struct kbd_state *state)
1092{
1093 int i;
1094
1095 if (kbd_info.levels != 0)
1096 return state->level;
1097
1098 if (kbd_mode_levels_count > 0) {
1099 for (i = 0; i < kbd_mode_levels_count; ++i)
1100 if (kbd_mode_levels[i] == state->mode_bit)
1101 return i;
1102 return 0;
1103 }
1104
1105 return -EINVAL;
1106}
1107
1108static int kbd_set_level(struct kbd_state *state, u8 level)
1109{
1110 if (kbd_info.levels != 0) {
1111 if (level != 0)
1112 kbd_previous_level = level;
1113 if (state->level == level)
1114 return 0;
1115 state->level = level;
1116 if (level != 0 && state->mode_bit == KBD_MODE_BIT_OFF)
1117 state->mode_bit = kbd_previous_mode_bit;
1118 else if (level == 0 && state->mode_bit != KBD_MODE_BIT_OFF) {
1119 kbd_previous_mode_bit = state->mode_bit;
1120 state->mode_bit = KBD_MODE_BIT_OFF;
1121 }
1122 return 0;
1123 }
1124
1125 if (kbd_mode_levels_count > 0 && level < kbd_mode_levels_count) {
1126 if (level != 0)
1127 kbd_previous_level = level;
1128 state->mode_bit = kbd_mode_levels[level];
1129 return 0;
1130 }
1131
1132 return -EINVAL;
1133}
1134
1135static int kbd_get_state(struct kbd_state *state)
1136{
1137 int ret;
1138
1139 get_buffer();
1140
1141 buffer->input[0] = 0x1;
1142 dell_send_request(buffer, 4, 11);
1143 ret = buffer->output[0];
1144
1145 if (ret) {
1146 ret = dell_smi_error(ret);
1147 goto out;
1148 }
1149
1150 state->mode_bit = ffs(buffer->output[1] & 0xFFFF);
1151 if (state->mode_bit != 0)
1152 state->mode_bit--;
1153
1154 state->triggers = (buffer->output[1] >> 16) & 0xFF;
1155 state->timeout_value = (buffer->output[1] >> 24) & 0x3F;
1156 state->timeout_unit = (buffer->output[1] >> 30) & 0x3;
1157 state->als_setting = buffer->output[2] & 0xFF;
1158 state->als_value = (buffer->output[2] >> 8) & 0xFF;
1159 state->level = (buffer->output[2] >> 16) & 0xFF;
1160
1161 out:
1162 release_buffer();
1163 return ret;
1164}
1165
1166static int kbd_set_state(struct kbd_state *state)
1167{
1168 int ret;
1169
1170 get_buffer();
1171 buffer->input[0] = 0x2;
1172 buffer->input[1] = BIT(state->mode_bit) & 0xFFFF;
1173 buffer->input[1] |= (state->triggers & 0xFF) << 16;
1174 buffer->input[1] |= (state->timeout_value & 0x3F) << 24;
1175 buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
1176 buffer->input[2] = state->als_setting & 0xFF;
1177 buffer->input[2] |= (state->level & 0xFF) << 16;
1178 dell_send_request(buffer, 4, 11);
1179 ret = buffer->output[0];
1180 release_buffer();
1181
1182 return dell_smi_error(ret);
1183}
1184
1185static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old)
1186{
1187 int ret;
1188
1189 ret = kbd_set_state(state);
1190 if (ret == 0)
1191 return 0;
1192
1193 /*
1194 * When setting the new state fails,try to restore the previous one.
1195 * This is needed on some machines where BIOS sets a default state when
1196 * setting a new state fails. This default state could be all off.
1197 */
1198
1199 if (kbd_set_state(old))
1200 pr_err("Setting old previous keyboard state failed\n");
1201
1202 return ret;
1203}
1204
1205static int kbd_set_token_bit(u8 bit)
1206{
1207 int id;
1208 int ret;
1209
1210 if (bit >= ARRAY_SIZE(kbd_tokens))
1211 return -EINVAL;
1212
1213 id = find_token_id(kbd_tokens[bit]);
1214 if (id == -1)
1215 return -EINVAL;
1216
1217 get_buffer();
1218 buffer->input[0] = da_tokens[id].location;
1219 buffer->input[1] = da_tokens[id].value;
1220 dell_send_request(buffer, 1, 0);
1221 ret = buffer->output[0];
1222 release_buffer();
1223
1224 return dell_smi_error(ret);
1225}
1226
1227static int kbd_get_token_bit(u8 bit)
1228{
1229 int id;
1230 int ret;
1231 int val;
1232
1233 if (bit >= ARRAY_SIZE(kbd_tokens))
1234 return -EINVAL;
1235
1236 id = find_token_id(kbd_tokens[bit]);
1237 if (id == -1)
1238 return -EINVAL;
1239
1240 get_buffer();
1241 buffer->input[0] = da_tokens[id].location;
1242 dell_send_request(buffer, 0, 0);
1243 ret = buffer->output[0];
1244 val = buffer->output[1];
1245 release_buffer();
1246
1247 if (ret)
1248 return dell_smi_error(ret);
1249
1250 return (val == da_tokens[id].value);
1251}
1252
1253static int kbd_get_first_active_token_bit(void)
1254{
1255 int i;
1256 int ret;
1257
1258 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) {
1259 ret = kbd_get_token_bit(i);
1260 if (ret == 1)
1261 return i;
1262 }
1263
1264 return ret;
1265}
1266
1267static int kbd_get_valid_token_counts(void)
1268{
1269 return hweight16(kbd_token_bits);
1270}
1271
1272static inline int kbd_init_info(void)
1273{
1274 struct kbd_state state;
1275 int ret;
1276 int i;
1277
1278 ret = kbd_get_info(&kbd_info);
1279 if (ret)
1280 return ret;
1281
1282 kbd_get_state(&state);
1283
1284 /* NOTE: timeout value is stored in 6 bits so max value is 63 */
1285 if (kbd_info.seconds > 63)
1286 kbd_info.seconds = 63;
1287 if (kbd_info.minutes > 63)
1288 kbd_info.minutes = 63;
1289 if (kbd_info.hours > 63)
1290 kbd_info.hours = 63;
1291 if (kbd_info.days > 63)
1292 kbd_info.days = 63;
1293
1294 /* NOTE: On tested machines ON mode did not work and caused
1295 * problems (turned backlight off) so do not use it
1296 */
1297 kbd_info.modes &= ~BIT(KBD_MODE_BIT_ON);
1298
1299 kbd_previous_level = kbd_get_level(&state);
1300 kbd_previous_mode_bit = state.mode_bit;
1301
1302 if (kbd_previous_level == 0 && kbd_get_max_level() != 0)
1303 kbd_previous_level = 1;
1304
1305 if (kbd_previous_mode_bit == KBD_MODE_BIT_OFF) {
1306 kbd_previous_mode_bit =
1307 ffs(kbd_info.modes & ~BIT(KBD_MODE_BIT_OFF));
1308 if (kbd_previous_mode_bit != 0)
1309 kbd_previous_mode_bit--;
1310 }
1311
1312 if (kbd_info.modes & (BIT(KBD_MODE_BIT_ALS) |
1313 BIT(KBD_MODE_BIT_TRIGGER_ALS)))
1314 kbd_als_supported = true;
1315
1316 if (kbd_info.modes & (
1317 BIT(KBD_MODE_BIT_TRIGGER_ALS) | BIT(KBD_MODE_BIT_TRIGGER) |
1318 BIT(KBD_MODE_BIT_TRIGGER_25) | BIT(KBD_MODE_BIT_TRIGGER_50) |
1319 BIT(KBD_MODE_BIT_TRIGGER_75) | BIT(KBD_MODE_BIT_TRIGGER_100)
1320 ))
1321 kbd_triggers_supported = true;
1322
1323 /* kbd_mode_levels[0] is reserved, see below */
1324 for (i = 0; i < 16; ++i)
1325 if (kbd_is_level_mode_bit(i) && (BIT(i) & kbd_info.modes))
1326 kbd_mode_levels[1 + kbd_mode_levels_count++] = i;
1327
1328 /*
1329 * Find the first supported mode and assign to kbd_mode_levels[0].
1330 * This should be 0 (off), but we cannot depend on the BIOS to
1331 * support 0.
1332 */
1333 if (kbd_mode_levels_count > 0) {
1334 for (i = 0; i < 16; ++i) {
1335 if (BIT(i) & kbd_info.modes) {
1336 kbd_mode_levels[0] = i;
1337 break;
1338 }
1339 }
1340 kbd_mode_levels_count++;
1341 }
1342
1343 return 0;
1344
1345}
1346
1347static inline void kbd_init_tokens(void)
1348{
1349 int i;
1350
1351 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i)
1352 if (find_token_id(kbd_tokens[i]) != -1)
1353 kbd_token_bits |= BIT(i);
1354}
1355
1356static void kbd_init(void)
1357{
1358 int ret;
1359
1360 ret = kbd_init_info();
1361 kbd_init_tokens();
1362
1363 if (kbd_token_bits != 0 || ret == 0)
1364 kbd_led_present = true;
1365}
1366
1367static ssize_t kbd_led_timeout_store(struct device *dev,
1368 struct device_attribute *attr,
1369 const char *buf, size_t count)
1370{
1371 struct kbd_state new_state;
1372 struct kbd_state state;
1373 bool convert;
1374 int value;
1375 int ret;
1376 char ch;
1377 u8 unit;
1378 int i;
1379
1380 ret = sscanf(buf, "%d %c", &value, &ch);
1381 if (ret < 1)
1382 return -EINVAL;
1383 else if (ret == 1)
1384 ch = 's';
1385
1386 if (value < 0)
1387 return -EINVAL;
1388
1389 convert = false;
1390
1391 switch (ch) {
1392 case 's':
1393 if (value > kbd_info.seconds)
1394 convert = true;
1395 unit = KBD_TIMEOUT_SECONDS;
1396 break;
1397 case 'm':
1398 if (value > kbd_info.minutes)
1399 convert = true;
1400 unit = KBD_TIMEOUT_MINUTES;
1401 break;
1402 case 'h':
1403 if (value > kbd_info.hours)
1404 convert = true;
1405 unit = KBD_TIMEOUT_HOURS;
1406 break;
1407 case 'd':
1408 if (value > kbd_info.days)
1409 convert = true;
1410 unit = KBD_TIMEOUT_DAYS;
1411 break;
1412 default:
1413 return -EINVAL;
1414 }
1415
1416 if (quirks && quirks->needs_kbd_timeouts)
1417 convert = true;
1418
1419 if (convert) {
1420 /* Convert value from current units to seconds */
1421 switch (unit) {
1422 case KBD_TIMEOUT_DAYS:
1423 value *= 24;
1424 case KBD_TIMEOUT_HOURS:
1425 value *= 60;
1426 case KBD_TIMEOUT_MINUTES:
1427 value *= 60;
1428 unit = KBD_TIMEOUT_SECONDS;
1429 }
1430
1431 if (quirks && quirks->needs_kbd_timeouts) {
1432 for (i = 0; quirks->kbd_timeouts[i] != -1; i++) {
1433 if (value <= quirks->kbd_timeouts[i]) {
1434 value = quirks->kbd_timeouts[i];
1435 break;
1436 }
1437 }
1438 }
1439
1440 if (value <= kbd_info.seconds && kbd_info.seconds) {
1441 unit = KBD_TIMEOUT_SECONDS;
1442 } else if (value / 60 <= kbd_info.minutes && kbd_info.minutes) {
1443 value /= 60;
1444 unit = KBD_TIMEOUT_MINUTES;
1445 } else if (value / (60 * 60) <= kbd_info.hours && kbd_info.hours) {
1446 value /= (60 * 60);
1447 unit = KBD_TIMEOUT_HOURS;
1448 } else if (value / (60 * 60 * 24) <= kbd_info.days && kbd_info.days) {
1449 value /= (60 * 60 * 24);
1450 unit = KBD_TIMEOUT_DAYS;
1451 } else {
1452 return -EINVAL;
1453 }
1454 }
1455
1456 ret = kbd_get_state(&state);
1457 if (ret)
1458 return ret;
1459
1460 new_state = state;
1461 new_state.timeout_value = value;
1462 new_state.timeout_unit = unit;
1463
1464 ret = kbd_set_state_safe(&new_state, &state);
1465 if (ret)
1466 return ret;
1467
1468 return count;
1469}
1470
1471static ssize_t kbd_led_timeout_show(struct device *dev,
1472 struct device_attribute *attr, char *buf)
1473{
1474 struct kbd_state state;
1475 int ret;
1476 int len;
1477
1478 ret = kbd_get_state(&state);
1479 if (ret)
1480 return ret;
1481
1482 len = sprintf(buf, "%d", state.timeout_value);
1483
1484 switch (state.timeout_unit) {
1485 case KBD_TIMEOUT_SECONDS:
1486 return len + sprintf(buf+len, "s\n");
1487 case KBD_TIMEOUT_MINUTES:
1488 return len + sprintf(buf+len, "m\n");
1489 case KBD_TIMEOUT_HOURS:
1490 return len + sprintf(buf+len, "h\n");
1491 case KBD_TIMEOUT_DAYS:
1492 return len + sprintf(buf+len, "d\n");
1493 default:
1494 return -EINVAL;
1495 }
1496
1497 return len;
1498}
1499
1500static DEVICE_ATTR(stop_timeout, S_IRUGO | S_IWUSR,
1501 kbd_led_timeout_show, kbd_led_timeout_store);
1502
1503static const char * const kbd_led_triggers[] = {
1504 "keyboard",
1505 "touchpad",
1506 /*"trackstick"*/ NULL, /* NOTE: trackstick is just alias for touchpad */
1507 "mouse",
1508};
1509
1510static ssize_t kbd_led_triggers_store(struct device *dev,
1511 struct device_attribute *attr,
1512 const char *buf, size_t count)
1513{
1514 struct kbd_state new_state;
1515 struct kbd_state state;
1516 bool triggers_enabled = false;
1517 bool als_enabled = false;
1518 bool disable_als = false;
1519 bool enable_als = false;
1520 int trigger_bit = -1;
1521 char trigger[21];
1522 int i, ret;
1523
1524 ret = sscanf(buf, "%20s", trigger);
1525 if (ret != 1)
1526 return -EINVAL;
1527
1528 if (trigger[0] != '+' && trigger[0] != '-')
1529 return -EINVAL;
1530
1531 ret = kbd_get_state(&state);
1532 if (ret)
1533 return ret;
1534
1535 if (kbd_als_supported)
1536 als_enabled = kbd_is_als_mode_bit(state.mode_bit);
1537
1538 if (kbd_triggers_supported)
1539 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
1540
1541 if (kbd_als_supported) {
1542 if (strcmp(trigger, "+als") == 0) {
1543 if (als_enabled)
1544 return count;
1545 enable_als = true;
1546 } else if (strcmp(trigger, "-als") == 0) {
1547 if (!als_enabled)
1548 return count;
1549 disable_als = true;
1550 }
1551 }
1552
1553 if (enable_als || disable_als) {
1554 new_state = state;
1555 if (enable_als) {
1556 if (triggers_enabled)
1557 new_state.mode_bit = KBD_MODE_BIT_TRIGGER_ALS;
1558 else
1559 new_state.mode_bit = KBD_MODE_BIT_ALS;
1560 } else {
1561 if (triggers_enabled) {
1562 new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
1563 kbd_set_level(&new_state, kbd_previous_level);
1564 } else {
1565 new_state.mode_bit = KBD_MODE_BIT_ON;
1566 }
1567 }
1568 if (!(kbd_info.modes & BIT(new_state.mode_bit)))
1569 return -EINVAL;
1570 ret = kbd_set_state_safe(&new_state, &state);
1571 if (ret)
1572 return ret;
1573 kbd_previous_mode_bit = new_state.mode_bit;
1574 return count;
1575 }
1576
1577 if (kbd_triggers_supported) {
1578 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) {
1579 if (!(kbd_info.triggers & BIT(i)))
1580 continue;
1581 if (!kbd_led_triggers[i])
1582 continue;
1583 if (strcmp(trigger+1, kbd_led_triggers[i]) != 0)
1584 continue;
1585 if (trigger[0] == '+' &&
1586 triggers_enabled && (state.triggers & BIT(i)))
1587 return count;
1588 if (trigger[0] == '-' &&
1589 (!triggers_enabled || !(state.triggers & BIT(i))))
1590 return count;
1591 trigger_bit = i;
1592 break;
1593 }
1594 }
1595
1596 if (trigger_bit != -1) {
1597 new_state = state;
1598 if (trigger[0] == '+')
1599 new_state.triggers |= BIT(trigger_bit);
1600 else {
1601 new_state.triggers &= ~BIT(trigger_bit);
1602 /* NOTE: trackstick bit (2) must be disabled when
1603 * disabling touchpad bit (1), otherwise touchpad
1604 * bit (1) will not be disabled */
1605 if (trigger_bit == 1)
1606 new_state.triggers &= ~BIT(2);
1607 }
1608 if ((kbd_info.triggers & new_state.triggers) !=
1609 new_state.triggers)
1610 return -EINVAL;
1611 if (new_state.triggers && !triggers_enabled) {
1612 if (als_enabled)
1613 new_state.mode_bit = KBD_MODE_BIT_TRIGGER_ALS;
1614 else {
1615 new_state.mode_bit = KBD_MODE_BIT_TRIGGER;
1616 kbd_set_level(&new_state, kbd_previous_level);
1617 }
1618 } else if (new_state.triggers == 0) {
1619 if (als_enabled)
1620 new_state.mode_bit = KBD_MODE_BIT_ALS;
1621 else
1622 kbd_set_level(&new_state, 0);
1623 }
1624 if (!(kbd_info.modes & BIT(new_state.mode_bit)))
1625 return -EINVAL;
1626 ret = kbd_set_state_safe(&new_state, &state);
1627 if (ret)
1628 return ret;
1629 if (new_state.mode_bit != KBD_MODE_BIT_OFF)
1630 kbd_previous_mode_bit = new_state.mode_bit;
1631 return count;
1632 }
1633
1634 return -EINVAL;
1635}
1636
1637static ssize_t kbd_led_triggers_show(struct device *dev,
1638 struct device_attribute *attr, char *buf)
1639{
1640 struct kbd_state state;
1641 bool triggers_enabled;
1642 int level, i, ret;
1643 int len = 0;
1644
1645 ret = kbd_get_state(&state);
1646 if (ret)
1647 return ret;
1648
1649 len = 0;
1650
1651 if (kbd_triggers_supported) {
1652 triggers_enabled = kbd_is_trigger_mode_bit(state.mode_bit);
1653 level = kbd_get_level(&state);
1654 for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); ++i) {
1655 if (!(kbd_info.triggers & BIT(i)))
1656 continue;
1657 if (!kbd_led_triggers[i])
1658 continue;
1659 if ((triggers_enabled || level <= 0) &&
1660 (state.triggers & BIT(i)))
1661 buf[len++] = '+';
1662 else
1663 buf[len++] = '-';
1664 len += sprintf(buf+len, "%s ", kbd_led_triggers[i]);
1665 }
1666 }
1667
1668 if (kbd_als_supported) {
1669 if (kbd_is_als_mode_bit(state.mode_bit))
1670 len += sprintf(buf+len, "+als ");
1671 else
1672 len += sprintf(buf+len, "-als ");
1673 }
1674
1675 if (len)
1676 buf[len - 1] = '\n';
1677
1678 return len;
1679}
1680
1681static DEVICE_ATTR(start_triggers, S_IRUGO | S_IWUSR,
1682 kbd_led_triggers_show, kbd_led_triggers_store);
1683
1684static ssize_t kbd_led_als_store(struct device *dev,
1685 struct device_attribute *attr,
1686 const char *buf, size_t count)
1687{
1688 struct kbd_state state;
1689 struct kbd_state new_state;
1690 u8 setting;
1691 int ret;
1692
1693 ret = kstrtou8(buf, 10, &setting);
1694 if (ret)
1695 return ret;
1696
1697 ret = kbd_get_state(&state);
1698 if (ret)
1699 return ret;
1700
1701 new_state = state;
1702 new_state.als_setting = setting;
1703
1704 ret = kbd_set_state_safe(&new_state, &state);
1705 if (ret)
1706 return ret;
1707
1708 return count;
1709}
1710
1711static ssize_t kbd_led_als_show(struct device *dev,
1712 struct device_attribute *attr, char *buf)
1713{
1714 struct kbd_state state;
1715 int ret;
1716
1717 ret = kbd_get_state(&state);
1718 if (ret)
1719 return ret;
1720
1721 return sprintf(buf, "%d\n", state.als_setting);
1722}
1723
1724static DEVICE_ATTR(als_setting, S_IRUGO | S_IWUSR,
1725 kbd_led_als_show, kbd_led_als_store);
1726
1727static struct attribute *kbd_led_attrs[] = {
1728 &dev_attr_stop_timeout.attr,
1729 &dev_attr_start_triggers.attr,
1730 &dev_attr_als_setting.attr,
1731 NULL,
1732};
1733ATTRIBUTE_GROUPS(kbd_led);
1734
1735static enum led_brightness kbd_led_level_get(struct led_classdev *led_cdev)
1736{
1737 int ret;
1738 u16 num;
1739 struct kbd_state state;
1740
1741 if (kbd_get_max_level()) {
1742 ret = kbd_get_state(&state);
1743 if (ret)
1744 return 0;
1745 ret = kbd_get_level(&state);
1746 if (ret < 0)
1747 return 0;
1748 return ret;
1749 }
1750
1751 if (kbd_get_valid_token_counts()) {
1752 ret = kbd_get_first_active_token_bit();
1753 if (ret < 0)
1754 return 0;
1755 for (num = kbd_token_bits; num != 0 && ret > 0; --ret)
1756 num &= num - 1; /* clear the first bit set */
1757 if (num == 0)
1758 return 0;
1759 return ffs(num) - 1;
1760 }
1761
1762 pr_warn("Keyboard brightness level control not supported\n");
1763 return 0;
1764}
1765
1766static void kbd_led_level_set(struct led_classdev *led_cdev,
1767 enum led_brightness value)
1768{
1769 struct kbd_state state;
1770 struct kbd_state new_state;
1771 u16 num;
1772
1773 if (kbd_get_max_level()) {
1774 if (kbd_get_state(&state))
1775 return;
1776 new_state = state;
1777 if (kbd_set_level(&new_state, value))
1778 return;
1779 kbd_set_state_safe(&new_state, &state);
1780 return;
1781 }
1782
1783 if (kbd_get_valid_token_counts()) {
1784 for (num = kbd_token_bits; num != 0 && value > 0; --value)
1785 num &= num - 1; /* clear the first bit set */
1786 if (num == 0)
1787 return;
1788 kbd_set_token_bit(ffs(num) - 1);
1789 return;
1790 }
1791
1792 pr_warn("Keyboard brightness level control not supported\n");
1793}
1794
1795static struct led_classdev kbd_led = {
1796 .name = "dell::kbd_backlight",
1797 .brightness_set = kbd_led_level_set,
1798 .brightness_get = kbd_led_level_get,
1799 .groups = kbd_led_groups,
1800};
1801
1802static int __init kbd_led_init(struct device *dev)
1803{
1804 kbd_init();
1805 if (!kbd_led_present)
1806 return -ENODEV;
1807 kbd_led.max_brightness = kbd_get_max_level();
1808 if (!kbd_led.max_brightness) {
1809 kbd_led.max_brightness = kbd_get_valid_token_counts();
1810 if (kbd_led.max_brightness)
1811 kbd_led.max_brightness--;
1812 }
1813 return led_classdev_register(dev, &kbd_led);
1814}
1815
1816static void brightness_set_exit(struct led_classdev *led_cdev,
1817 enum led_brightness value)
1818{
1819 /* Don't change backlight level on exit */
1820};
1821
1822static void kbd_led_exit(void)
1823{
1824 if (!kbd_led_present)
1825 return;
1826 kbd_led.brightness_set = brightness_set_exit;
1827 led_classdev_unregister(&kbd_led);
1828}
1829
792static int __init dell_init(void) 1830static int __init dell_init(void)
793{ 1831{
794 int max_intensity = 0; 1832 int max_intensity = 0;
@@ -841,6 +1879,8 @@ static int __init dell_init(void)
841 if (quirks && quirks->touchpad_led) 1879 if (quirks && quirks->touchpad_led)
842 touchpad_led_init(&platform_device->dev); 1880 touchpad_led_init(&platform_device->dev);
843 1881
1882 kbd_led_init(&platform_device->dev);
1883
844 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL); 1884 dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
845 if (dell_laptop_dir != NULL) 1885 if (dell_laptop_dir != NULL)
846 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL, 1886 debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
@@ -908,6 +1948,7 @@ static void __exit dell_exit(void)
908 debugfs_remove_recursive(dell_laptop_dir); 1948 debugfs_remove_recursive(dell_laptop_dir);
909 if (quirks && quirks->touchpad_led) 1949 if (quirks && quirks->touchpad_led)
910 touchpad_led_exit(); 1950 touchpad_led_exit();
1951 kbd_led_exit();
911 i8042_remove_filter(dell_laptop_i8042_filter); 1952 i8042_remove_filter(dell_laptop_i8042_filter);
912 cancel_delayed_work_sync(&dell_rfkill_work); 1953 cancel_delayed_work_sync(&dell_rfkill_work);
913 backlight_device_unregister(dell_backlight_device); 1954 backlight_device_unregister(dell_backlight_device);
@@ -924,5 +1965,7 @@ module_init(dell_init);
924module_exit(dell_exit); 1965module_exit(dell_exit);
925 1966
926MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 1967MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
1968MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>");
1969MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
927MODULE_DESCRIPTION("Dell laptop driver"); 1970MODULE_DESCRIPTION("Dell laptop driver");
928MODULE_LICENSE("GPL"); 1971MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index a653716055d1..0aec4fd4c48e 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * dell-smo8800.c - Dell Latitude ACPI SMO8800/SMO8810 freefall sensor driver 2 * dell-smo8800.c - Dell Latitude ACPI SMO88XX freefall sensor driver
3 * 3 *
4 * Copyright (C) 2012 Sonal Santan <sonal.santan@gmail.com> 4 * Copyright (C) 2012 Sonal Santan <sonal.santan@gmail.com>
5 * Copyright (C) 2014 Pali Rohár <pali.rohar@gmail.com> 5 * Copyright (C) 2014 Pali Rohár <pali.rohar@gmail.com>
@@ -209,7 +209,13 @@ static int smo8800_remove(struct acpi_device *device)
209 209
210static const struct acpi_device_id smo8800_ids[] = { 210static const struct acpi_device_id smo8800_ids[] = {
211 { "SMO8800", 0 }, 211 { "SMO8800", 0 },
212 { "SMO8801", 0 },
212 { "SMO8810", 0 }, 213 { "SMO8810", 0 },
214 { "SMO8811", 0 },
215 { "SMO8820", 0 },
216 { "SMO8821", 0 },
217 { "SMO8830", 0 },
218 { "SMO8831", 0 },
213 { "", 0 }, 219 { "", 0 },
214}; 220};
215 221
@@ -228,6 +234,6 @@ static struct acpi_driver smo8800_driver = {
228 234
229module_acpi_driver(smo8800_driver); 235module_acpi_driver(smo8800_driver);
230 236
231MODULE_DESCRIPTION("Dell Latitude freefall driver (ACPI SMO8800/SMO8810)"); 237MODULE_DESCRIPTION("Dell Latitude freefall driver (ACPI SMO88XX)");
232MODULE_LICENSE("GPL"); 238MODULE_LICENSE("GPL");
233MODULE_AUTHOR("Sonal Santan, Pali Rohár"); 239MODULE_AUTHOR("Sonal Santan, Pali Rohár");
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 25721bf20092..6512a06bc053 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -65,10 +65,8 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
65 /* Battery health status button */ 65 /* Battery health status button */
66 { KE_KEY, 0xe007, { KEY_BATTERY } }, 66 { KE_KEY, 0xe007, { KEY_BATTERY } },
67 67
68 /* This is actually for all radios. Although physically a 68 /* Radio devices state change */
69 * switch, the notification does not provide an indication of 69 { KE_IGNORE, 0xe008, { KEY_RFKILL } },
70 * state and so it should be reported as a key */
71 { KE_KEY, 0xe008, { KEY_WLAN } },
72 70
73 /* The next device is at offset 6, the active devices are at 71 /* The next device is at offset 6, the active devices are at
74 offset 8 and the attached devices at offset 10 */ 72 offset 8 and the attached devices at offset 10 */
@@ -145,57 +143,154 @@ static const u16 bios_to_linux_keycode[256] __initconst = {
145 143
146static struct input_dev *dell_wmi_input_dev; 144static struct input_dev *dell_wmi_input_dev;
147 145
146static void dell_wmi_process_key(int reported_key)
147{
148 const struct key_entry *key;
149
150 key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
151 reported_key);
152 if (!key) {
153 pr_info("Unknown key %x pressed\n", reported_key);
154 return;
155 }
156
157 pr_debug("Key %x pressed\n", reported_key);
158
159 /* Don't report brightness notifications that will also come via ACPI */
160 if ((key->keycode == KEY_BRIGHTNESSUP ||
161 key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video)
162 return;
163
164 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
165}
166
148static void dell_wmi_notify(u32 value, void *context) 167static void dell_wmi_notify(u32 value, void *context)
149{ 168{
150 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 169 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
151 union acpi_object *obj; 170 union acpi_object *obj;
152 acpi_status status; 171 acpi_status status;
172 acpi_size buffer_size;
173 u16 *buffer_entry, *buffer_end;
174 int len, i;
153 175
154 status = wmi_get_event_data(value, &response); 176 status = wmi_get_event_data(value, &response);
155 if (status != AE_OK) { 177 if (status != AE_OK) {
156 pr_info("bad event status 0x%x\n", status); 178 pr_warn("bad event status 0x%x\n", status);
157 return; 179 return;
158 } 180 }
159 181
160 obj = (union acpi_object *)response.pointer; 182 obj = (union acpi_object *)response.pointer;
183 if (!obj) {
184 pr_warn("no response\n");
185 return;
186 }
161 187
162 if (obj && obj->type == ACPI_TYPE_BUFFER) { 188 if (obj->type != ACPI_TYPE_BUFFER) {
163 const struct key_entry *key; 189 pr_warn("bad response type %x\n", obj->type);
164 int reported_key; 190 kfree(obj);
165 u16 *buffer_entry = (u16 *)obj->buffer.pointer; 191 return;
166 int buffer_size = obj->buffer.length/2; 192 }
167
168 if (buffer_size >= 2 && dell_new_hk_type && buffer_entry[1] != 0x10) {
169 pr_info("Received unknown WMI event (0x%x)\n",
170 buffer_entry[1]);
171 kfree(obj);
172 return;
173 }
174 193
175 if (buffer_size >= 3 && (dell_new_hk_type || buffer_entry[1] == 0x0)) 194 pr_debug("Received WMI event (%*ph)\n",
176 reported_key = (int)buffer_entry[2]; 195 obj->buffer.length, obj->buffer.pointer);
196
197 buffer_entry = (u16 *)obj->buffer.pointer;
198 buffer_size = obj->buffer.length/2;
199
200 if (!dell_new_hk_type) {
201 if (buffer_size >= 3 && buffer_entry[1] == 0x0)
202 dell_wmi_process_key(buffer_entry[2]);
177 else if (buffer_size >= 2) 203 else if (buffer_size >= 2)
178 reported_key = (int)buffer_entry[1] & 0xffff; 204 dell_wmi_process_key(buffer_entry[1]);
179 else { 205 else
180 pr_info("Received unknown WMI event\n"); 206 pr_info("Received unknown WMI event\n");
181 kfree(obj); 207 kfree(obj);
182 return; 208 return;
209 }
210
211 buffer_end = buffer_entry + buffer_size;
212
213 while (buffer_entry < buffer_end) {
214
215 len = buffer_entry[0];
216 if (len == 0)
217 break;
218
219 len++;
220
221 if (buffer_entry + len > buffer_end) {
222 pr_warn("Invalid length of WMI event\n");
223 break;
183 } 224 }
184 225
185 key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev, 226 pr_debug("Process buffer (%*ph)\n", len*2, buffer_entry);
186 reported_key); 227
187 if (!key) { 228 switch (buffer_entry[1]) {
188 pr_info("Unknown key %x pressed\n", reported_key); 229 case 0x00:
189 } else if ((key->keycode == KEY_BRIGHTNESSUP || 230 for (i = 2; i < len; ++i) {
190 key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video) { 231 switch (buffer_entry[i]) {
191 /* Don't report brightness notifications that will also 232 case 0xe043:
192 * come via ACPI */ 233 /* NIC Link is Up */
193 ; 234 pr_debug("NIC Link is Up\n");
194 } else { 235 break;
195 sparse_keymap_report_entry(dell_wmi_input_dev, key, 236 case 0xe044:
196 1, true); 237 /* NIC Link is Down */
238 pr_debug("NIC Link is Down\n");
239 break;
240 case 0xe045:
241 /* Unknown event but defined in DSDT */
242 default:
243 /* Unknown event */
244 pr_info("Unknown WMI event type 0x00: "
245 "0x%x\n", (int)buffer_entry[i]);
246 break;
247 }
248 }
249 break;
250 case 0x10:
251 /* Keys pressed */
252 for (i = 2; i < len; ++i)
253 dell_wmi_process_key(buffer_entry[i]);
254 break;
255 case 0x11:
256 for (i = 2; i < len; ++i) {
257 switch (buffer_entry[i]) {
258 case 0xfff0:
259 /* Battery unplugged */
260 pr_debug("Battery unplugged\n");
261 break;
262 case 0xfff1:
263 /* Battery inserted */
264 pr_debug("Battery inserted\n");
265 break;
266 case 0x01e1:
267 case 0x02ea:
268 case 0x02eb:
269 case 0x02ec:
270 case 0x02f6:
271 /* Keyboard backlight level changed */
272 pr_debug("Keyboard backlight level "
273 "changed\n");
274 break;
275 default:
276 /* Unknown event */
277 pr_info("Unknown WMI event type 0x11: "
278 "0x%x\n", (int)buffer_entry[i]);
279 break;
280 }
281 }
282 break;
283 default:
284 /* Unknown event */
285 pr_info("Unknown WMI event type 0x%x\n",
286 (int)buffer_entry[1]);
287 break;
197 } 288 }
289
290 buffer_entry += len;
291
198 } 292 }
293
199 kfree(obj); 294 kfree(obj);
200} 295}
201 296
@@ -213,11 +308,16 @@ static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
213 for (i = 0; i < hotkey_num; i++) { 308 for (i = 0; i < hotkey_num; i++) {
214 const struct dell_bios_keymap_entry *bios_entry = 309 const struct dell_bios_keymap_entry *bios_entry =
215 &dell_bios_hotkey_table->keymap[i]; 310 &dell_bios_hotkey_table->keymap[i];
216 keymap[i].type = KE_KEY; 311 u16 keycode = bios_entry->keycode < 256 ?
217 keymap[i].code = bios_entry->scancode;
218 keymap[i].keycode = bios_entry->keycode < 256 ?
219 bios_to_linux_keycode[bios_entry->keycode] : 312 bios_to_linux_keycode[bios_entry->keycode] :
220 KEY_RESERVED; 313 KEY_RESERVED;
314
315 if (keycode == KEY_KBDILLUMTOGGLE)
316 keymap[i].type = KE_IGNORE;
317 else
318 keymap[i].type = KE_KEY;
319 keymap[i].code = bios_entry->scancode;
320 keymap[i].keycode = keycode;
221 } 321 }
222 322
223 keymap[hotkey_num].type = KE_END; 323 keymap[hotkey_num].type = KE_END;
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 5a54d35a61de..844c2096bde9 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -417,8 +417,7 @@ static ssize_t cpufv_disabled_store(struct device *dev,
417 switch (value) { 417 switch (value) {
418 case 0: 418 case 0:
419 if (eeepc->cpufv_disabled) 419 if (eeepc->cpufv_disabled)
420 pr_warn("cpufv enabled (not officially supported " 420 pr_warn("cpufv enabled (not officially supported on this model)\n");
421 "on this model)\n");
422 eeepc->cpufv_disabled = false; 421 eeepc->cpufv_disabled = false;
423 return count; 422 return count;
424 case 1: 423 case 1:
@@ -580,59 +579,58 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
580 mutex_lock(&eeepc->hotplug_lock); 579 mutex_lock(&eeepc->hotplug_lock);
581 pci_lock_rescan_remove(); 580 pci_lock_rescan_remove();
582 581
583 if (eeepc->hotplug_slot) { 582 if (!eeepc->hotplug_slot)
584 port = acpi_get_pci_dev(handle); 583 goto out_unlock;
585 if (!port) {
586 pr_warning("Unable to find port\n");
587 goto out_unlock;
588 }
589 584
590 bus = port->subordinate; 585 port = acpi_get_pci_dev(handle);
586 if (!port) {
587 pr_warning("Unable to find port\n");
588 goto out_unlock;
589 }
591 590
592 if (!bus) { 591 bus = port->subordinate;
593 pr_warn("Unable to find PCI bus 1?\n");
594 goto out_put_dev;
595 }
596 592
597 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) { 593 if (!bus) {
598 pr_err("Unable to read PCI config space?\n"); 594 pr_warn("Unable to find PCI bus 1?\n");
599 goto out_put_dev; 595 goto out_put_dev;
600 } 596 }
597
598 if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
599 pr_err("Unable to read PCI config space?\n");
600 goto out_put_dev;
601 }
601 602
602 absent = (l == 0xffffffff); 603 absent = (l == 0xffffffff);
603 604
604 if (blocked != absent) { 605 if (blocked != absent) {
605 pr_warn("BIOS says wireless lan is %s, " 606 pr_warn("BIOS says wireless lan is %s, but the pci device is %s\n",
606 "but the pci device is %s\n", 607 blocked ? "blocked" : "unblocked",
607 blocked ? "blocked" : "unblocked", 608 absent ? "absent" : "present");
608 absent ? "absent" : "present"); 609 pr_warn("skipped wireless hotplug as probably inappropriate for this model\n");
609 pr_warn("skipped wireless hotplug as probably " 610 goto out_put_dev;
610 "inappropriate for this model\n"); 611 }
612
613 if (!blocked) {
614 dev = pci_get_slot(bus, 0);
615 if (dev) {
616 /* Device already present */
617 pci_dev_put(dev);
611 goto out_put_dev; 618 goto out_put_dev;
612 } 619 }
613 620 dev = pci_scan_single_device(bus, 0);
614 if (!blocked) { 621 if (dev) {
615 dev = pci_get_slot(bus, 0); 622 pci_bus_assign_resources(bus);
616 if (dev) { 623 pci_bus_add_device(dev);
617 /* Device already present */ 624 }
618 pci_dev_put(dev); 625 } else {
619 goto out_put_dev; 626 dev = pci_get_slot(bus, 0);
620 } 627 if (dev) {
621 dev = pci_scan_single_device(bus, 0); 628 pci_stop_and_remove_bus_device(dev);
622 if (dev) { 629 pci_dev_put(dev);
623 pci_bus_assign_resources(bus);
624 pci_bus_add_device(dev);
625 }
626 } else {
627 dev = pci_get_slot(bus, 0);
628 if (dev) {
629 pci_stop_and_remove_bus_device(dev);
630 pci_dev_put(dev);
631 }
632 } 630 }
633out_put_dev:
634 pci_dev_put(port);
635 } 631 }
632out_put_dev:
633 pci_dev_put(port);
636 634
637out_unlock: 635out_unlock:
638 pci_unlock_rescan_remove(); 636 pci_unlock_rescan_remove();
@@ -821,11 +819,15 @@ static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
821 return 0; 819 return 0;
822} 820}
823 821
822static char EEEPC_RFKILL_NODE_1[] = "\\_SB.PCI0.P0P5";
823static char EEEPC_RFKILL_NODE_2[] = "\\_SB.PCI0.P0P6";
824static char EEEPC_RFKILL_NODE_3[] = "\\_SB.PCI0.P0P7";
825
824static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc) 826static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
825{ 827{
826 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5"); 828 eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
827 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6"); 829 eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
828 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7"); 830 eeepc_unregister_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
829 if (eeepc->wlan_rfkill) { 831 if (eeepc->wlan_rfkill) {
830 rfkill_unregister(eeepc->wlan_rfkill); 832 rfkill_unregister(eeepc->wlan_rfkill);
831 rfkill_destroy(eeepc->wlan_rfkill); 833 rfkill_destroy(eeepc->wlan_rfkill);
@@ -897,9 +899,9 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
897 if (result == -EBUSY) 899 if (result == -EBUSY)
898 result = 0; 900 result = 0;
899 901
900 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5"); 902 eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_1);
901 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6"); 903 eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_2);
902 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7"); 904 eeepc_register_rfkill_notifier(eeepc, EEEPC_RFKILL_NODE_3);
903 905
904exit: 906exit:
905 if (result && result != -ENODEV) 907 if (result && result != -ENODEV)
@@ -915,7 +917,7 @@ static int eeepc_hotk_thaw(struct device *device)
915 struct eeepc_laptop *eeepc = dev_get_drvdata(device); 917 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
916 918
917 if (eeepc->wlan_rfkill) { 919 if (eeepc->wlan_rfkill) {
918 bool wlan; 920 int wlan;
919 921
920 /* 922 /*
921 * Work around bios bug - acpi _PTS turns off the wireless led 923 * Work around bios bug - acpi _PTS turns off the wireless led
@@ -923,7 +925,8 @@ static int eeepc_hotk_thaw(struct device *device)
923 * we should kick it ourselves in case hibernation is aborted. 925 * we should kick it ourselves in case hibernation is aborted.
924 */ 926 */
925 wlan = get_acpi(eeepc, CM_ASL_WLAN); 927 wlan = get_acpi(eeepc, CM_ASL_WLAN);
926 set_acpi(eeepc, CM_ASL_WLAN, wlan); 928 if (wlan >= 0)
929 set_acpi(eeepc, CM_ASL_WLAN, wlan);
927 } 930 }
928 931
929 return 0; 932 return 0;
@@ -935,9 +938,9 @@ static int eeepc_hotk_restore(struct device *device)
935 938
936 /* Refresh both wlan rfkill state and pci hotplug */ 939 /* Refresh both wlan rfkill state and pci hotplug */
937 if (eeepc->wlan_rfkill) { 940 if (eeepc->wlan_rfkill) {
938 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5"); 941 eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_1);
939 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6"); 942 eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_2);
940 eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7"); 943 eeepc_rfkill_hotplug_update(eeepc, EEEPC_RFKILL_NODE_3);
941 } 944 }
942 945
943 if (eeepc->bluetooth_rfkill) 946 if (eeepc->bluetooth_rfkill)
@@ -977,18 +980,28 @@ static struct platform_driver platform_driver = {
977#define EEEPC_EC_SFB0 0xD0 980#define EEEPC_EC_SFB0 0xD0
978#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */ 981#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
979 982
983static inline int eeepc_pwm_to_lmsensors(int value)
984{
985 return value * 255 / 100;
986}
987
988static inline int eeepc_lmsensors_to_pwm(int value)
989{
990 value = clamp_val(value, 0, 255);
991 return value * 100 / 255;
992}
993
980static int eeepc_get_fan_pwm(void) 994static int eeepc_get_fan_pwm(void)
981{ 995{
982 u8 value = 0; 996 u8 value = 0;
983 997
984 ec_read(EEEPC_EC_FAN_PWM, &value); 998 ec_read(EEEPC_EC_FAN_PWM, &value);
985 return value * 255 / 100; 999 return eeepc_pwm_to_lmsensors(value);
986} 1000}
987 1001
988static void eeepc_set_fan_pwm(int value) 1002static void eeepc_set_fan_pwm(int value)
989{ 1003{
990 value = clamp_val(value, 0, 255); 1004 value = eeepc_lmsensors_to_pwm(value);
991 value = value * 100 / 255;
992 ec_write(EEEPC_EC_FAN_PWM, value); 1005 ec_write(EEEPC_EC_FAN_PWM, value);
993} 1006}
994 1007
@@ -1002,15 +1015,19 @@ static int eeepc_get_fan_rpm(void)
1002 return high << 8 | low; 1015 return high << 8 | low;
1003} 1016}
1004 1017
1018#define EEEPC_EC_FAN_CTRL_BIT 0x02
1019#define EEEPC_FAN_CTRL_MANUAL 1
1020#define EEEPC_FAN_CTRL_AUTO 2
1021
1005static int eeepc_get_fan_ctrl(void) 1022static int eeepc_get_fan_ctrl(void)
1006{ 1023{
1007 u8 value = 0; 1024 u8 value = 0;
1008 1025
1009 ec_read(EEEPC_EC_FAN_CTRL, &value); 1026 ec_read(EEEPC_EC_FAN_CTRL, &value);
1010 if (value & 0x02) 1027 if (value & EEEPC_EC_FAN_CTRL_BIT)
1011 return 1; /* manual */ 1028 return EEEPC_FAN_CTRL_MANUAL;
1012 else 1029 else
1013 return 2; /* automatic */ 1030 return EEEPC_FAN_CTRL_AUTO;
1014} 1031}
1015 1032
1016static void eeepc_set_fan_ctrl(int manual) 1033static void eeepc_set_fan_ctrl(int manual)
@@ -1018,10 +1035,10 @@ static void eeepc_set_fan_ctrl(int manual)
1018 u8 value = 0; 1035 u8 value = 0;
1019 1036
1020 ec_read(EEEPC_EC_FAN_CTRL, &value); 1037 ec_read(EEEPC_EC_FAN_CTRL, &value);
1021 if (manual == 1) 1038 if (manual == EEEPC_FAN_CTRL_MANUAL)
1022 value |= 0x02; 1039 value |= EEEPC_EC_FAN_CTRL_BIT;
1023 else 1040 else
1024 value &= ~0x02; 1041 value &= ~EEEPC_EC_FAN_CTRL_BIT;
1025 ec_write(EEEPC_EC_FAN_CTRL, value); 1042 ec_write(EEEPC_EC_FAN_CTRL, value);
1026} 1043}
1027 1044
@@ -1156,8 +1173,7 @@ static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1156 1173
1157static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) 1174static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1158{ 1175{
1159 if (eeepc->backlight_device) 1176 backlight_device_unregister(eeepc->backlight_device);
1160 backlight_device_unregister(eeepc->backlight_device);
1161 eeepc->backlight_device = NULL; 1177 eeepc->backlight_device = NULL;
1162} 1178}
1163 1179
@@ -1216,7 +1232,7 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1216static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) 1232static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1217{ 1233{
1218 if (!eeepc->inputdev) 1234 if (!eeepc->inputdev)
1219 return ; 1235 return;
1220 if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true)) 1236 if (!sparse_keymap_report_event(eeepc->inputdev, event, 1, true))
1221 pr_info("Unknown key %x pressed\n", event); 1237 pr_info("Unknown key %x pressed\n", event);
1222} 1238}
@@ -1224,6 +1240,7 @@ static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1224static void eeepc_acpi_notify(struct acpi_device *device, u32 event) 1240static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1225{ 1241{
1226 struct eeepc_laptop *eeepc = acpi_driver_data(device); 1242 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1243 int old_brightness, new_brightness;
1227 u16 count; 1244 u16 count;
1228 1245
1229 if (event > ACPI_MAX_SYS_NOTIFY) 1246 if (event > ACPI_MAX_SYS_NOTIFY)
@@ -1234,34 +1251,32 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1234 count); 1251 count);
1235 1252
1236 /* Brightness events are special */ 1253 /* Brightness events are special */
1237 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) { 1254 if (event < NOTIFY_BRN_MIN || event > NOTIFY_BRN_MAX) {
1238
1239 /* Ignore them completely if the acpi video driver is used */
1240 if (eeepc->backlight_device != NULL) {
1241 int old_brightness, new_brightness;
1242
1243 /* Update the backlight device. */
1244 old_brightness = eeepc_backlight_notify(eeepc);
1245
1246 /* Convert event to keypress (obsolescent hack) */
1247 new_brightness = event - NOTIFY_BRN_MIN;
1248
1249 if (new_brightness < old_brightness) {
1250 event = NOTIFY_BRN_MIN; /* brightness down */
1251 } else if (new_brightness > old_brightness) {
1252 event = NOTIFY_BRN_MAX; /* brightness up */
1253 } else {
1254 /*
1255 * no change in brightness - already at min/max,
1256 * event will be desired value (or else ignored)
1257 */
1258 }
1259 eeepc_input_notify(eeepc, event);
1260 }
1261 } else {
1262 /* Everything else is a bona-fide keypress event */
1263 eeepc_input_notify(eeepc, event); 1255 eeepc_input_notify(eeepc, event);
1256 return;
1257 }
1258
1259 /* Ignore them completely if the acpi video driver is used */
1260 if (!eeepc->backlight_device)
1261 return;
1262
1263 /* Update the backlight device. */
1264 old_brightness = eeepc_backlight_notify(eeepc);
1265
1266 /* Convert event to keypress (obsolescent hack) */
1267 new_brightness = event - NOTIFY_BRN_MIN;
1268
1269 if (new_brightness < old_brightness) {
1270 event = NOTIFY_BRN_MIN; /* brightness down */
1271 } else if (new_brightness > old_brightness) {
1272 event = NOTIFY_BRN_MAX; /* brightness up */
1273 } else {
1274 /*
1275 * no change in brightness - already at min/max,
1276 * event will be desired value (or else ignored)
1277 */
1264 } 1278 }
1279 eeepc_input_notify(eeepc, event);
1265} 1280}
1266 1281
1267static void eeepc_dmi_check(struct eeepc_laptop *eeepc) 1282static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
@@ -1293,8 +1308,8 @@ static void eeepc_dmi_check(struct eeepc_laptop *eeepc)
1293 */ 1308 */
1294 if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { 1309 if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) {
1295 eeepc->cpufv_disabled = true; 1310 eeepc->cpufv_disabled = true;
1296 pr_info("model %s does not officially support setting cpu " 1311 pr_info("model %s does not officially support setting cpu speed\n",
1297 "speed\n", model); 1312 model);
1298 pr_info("cpufv disabled to avoid instability\n"); 1313 pr_info("cpufv disabled to avoid instability\n");
1299 } 1314 }
1300 1315
@@ -1320,8 +1335,8 @@ static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1320 Check if cm_getv[cm] works and, if yes, assume cm should be set. */ 1335 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1321 if (!(eeepc->cm_supported & (1 << cm)) 1336 if (!(eeepc->cm_supported & (1 << cm))
1322 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) { 1337 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1323 pr_info("%s (%x) not reported by BIOS," 1338 pr_info("%s (%x) not reported by BIOS, enabling anyway\n",
1324 " enabling anyway\n", name, 1 << cm); 1339 name, 1 << cm);
1325 eeepc->cm_supported |= 1 << cm; 1340 eeepc->cm_supported |= 1 << cm;
1326 } 1341 }
1327} 1342}
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index be55bd78b503..7c21c1c44dfa 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -1153,8 +1153,7 @@ fail_hotkey1:
1153fail_hotkey: 1153fail_hotkey:
1154 platform_driver_unregister(&fujitsupf_driver); 1154 platform_driver_unregister(&fujitsupf_driver);
1155fail_backlight: 1155fail_backlight:
1156 if (fujitsu->bl_device) 1156 backlight_device_unregister(fujitsu->bl_device);
1157 backlight_device_unregister(fujitsu->bl_device);
1158fail_sysfs_group: 1157fail_sysfs_group:
1159 sysfs_remove_group(&fujitsu->pf_device->dev.kobj, 1158 sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
1160 &fujitsupf_attribute_group); 1159 &fujitsupf_attribute_group);
@@ -1178,8 +1177,7 @@ static void __exit fujitsu_cleanup(void)
1178 1177
1179 platform_driver_unregister(&fujitsupf_driver); 1178 platform_driver_unregister(&fujitsupf_driver);
1180 1179
1181 if (fujitsu->bl_device) 1180 backlight_device_unregister(fujitsu->bl_device);
1182 backlight_device_unregister(fujitsu->bl_device);
1183 1181
1184 sysfs_remove_group(&fujitsu->pf_device->dev.kobj, 1182 sysfs_remove_group(&fujitsu->pf_device->dev.kobj,
1185 &fujitsupf_attribute_group); 1183 &fujitsupf_attribute_group);
diff --git a/drivers/platform/x86/hp-wireless.c b/drivers/platform/x86/hp-wireless.c
index 415348fc1210..4e4cc8bd7557 100644
--- a/drivers/platform/x86/hp-wireless.c
+++ b/drivers/platform/x86/hp-wireless.c
@@ -85,6 +85,9 @@ static int hpwl_add(struct acpi_device *device)
85 int err; 85 int err;
86 86
87 err = hp_wireless_input_setup(); 87 err = hp_wireless_input_setup();
88 if (err)
89 pr_err("Failed to setup hp wireless hotkeys\n");
90
88 return err; 91 return err;
89} 92}
90 93
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 6bec745b6b92..10ce6cba4455 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -246,6 +246,7 @@ static const struct dmi_system_id lis3lv02d_dmi_ids[] = {
246 AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap), 246 AXIS_DMI_MATCH("HPB64xx", "HP ProBook 64", xy_swap),
247 AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap), 247 AXIS_DMI_MATCH("HPB64xx", "HP EliteBook 84", xy_swap),
248 AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted), 248 AXIS_DMI_MATCH("HPB65xx", "HP ProBook 65", x_inverted),
249 AXIS_DMI_MATCH("HPZBook15", "HP ZBook 15", x_inverted),
249 { NULL, } 250 { NULL, }
250/* Laptop models without axis info (yet): 251/* Laptop models without axis info (yet):
251 * "NC6910" "HP Compaq 6910" 252 * "NC6910" "HP Compaq 6910"
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index c860eace1ce3..b3d419a84723 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -729,8 +729,7 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
729 729
730static void ideapad_backlight_exit(struct ideapad_private *priv) 730static void ideapad_backlight_exit(struct ideapad_private *priv)
731{ 731{
732 if (priv->blightdev) 732 backlight_device_unregister(priv->blightdev);
733 backlight_device_unregister(priv->blightdev);
734 priv->blightdev = NULL; 733 priv->blightdev = NULL;
735} 734}
736 735
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index ecd36e332c3c..e2065e06a3f3 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -33,7 +33,7 @@
33 * performance by allocating more power or thermal budget to the CPU or GPU 33 * performance by allocating more power or thermal budget to the CPU or GPU
34 * based on available headroom and activity. 34 * based on available headroom and activity.
35 * 35 *
36 * The basic algorithm is driven by a 5s moving average of tempurature. If 36 * The basic algorithm is driven by a 5s moving average of temperature. If
37 * thermal headroom is available, the CPU and/or GPU power clamps may be 37 * thermal headroom is available, the CPU and/or GPU power clamps may be
38 * adjusted upwards. If we hit the thermal ceiling or a thermal trigger, 38 * adjusted upwards. If we hit the thermal ceiling or a thermal trigger,
39 * we scale back the clamp. Aside from trigger events (when we're critically 39 * we scale back the clamp. Aside from trigger events (when we're critically
diff --git a/drivers/platform/x86/intel_oaktrail.c b/drivers/platform/x86/intel_oaktrail.c
index 0afaaef5711f..a4a4258f6134 100644
--- a/drivers/platform/x86/intel_oaktrail.c
+++ b/drivers/platform/x86/intel_oaktrail.c
@@ -271,8 +271,7 @@ static int oaktrail_backlight_init(void)
271 271
272static void oaktrail_backlight_exit(void) 272static void oaktrail_backlight_exit(void)
273{ 273{
274 if (oaktrail_bl_device) 274 backlight_device_unregister(oaktrail_bl_device);
275 backlight_device_unregister(oaktrail_bl_device);
276} 275}
277 276
278static int oaktrail_probe(struct platform_device *pdev) 277static int oaktrail_probe(struct platform_device *pdev)
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index a3f06cb1063f..085987730aab 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -820,7 +820,7 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
820{ 820{
821 static bool extended; 821 static bool extended;
822 822
823 if (str & 0x20) 823 if (str & I8042_STR_AUXDATA)
824 return false; 824 return false;
825 825
826 /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan, 0xE4 touchpad toggle*/ 826 /* 0x54 wwan, 0x62 bluetooth, 0x76 wlan, 0xE4 touchpad toggle*/
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index 70222f265f68..6d2bac0c463c 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -354,8 +354,7 @@ static void __exit msi_wmi_exit(void)
354 sparse_keymap_free(msi_wmi_input_dev); 354 sparse_keymap_free(msi_wmi_input_dev);
355 input_unregister_device(msi_wmi_input_dev); 355 input_unregister_device(msi_wmi_input_dev);
356 } 356 }
357 if (backlight) 357 backlight_device_unregister(backlight);
358 backlight_device_unregister(backlight);
359} 358}
360 359
361module_init(msi_wmi_init); 360module_init(msi_wmi_init);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index a1a0fd72e9bf..6dd1c0e7dcd9 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -3140,8 +3140,7 @@ static void sony_nc_backlight_setup(void)
3140 3140
3141static void sony_nc_backlight_cleanup(void) 3141static void sony_nc_backlight_cleanup(void)
3142{ 3142{
3143 if (sony_bl_props.dev) 3143 backlight_device_unregister(sony_bl_props.dev);
3144 backlight_device_unregister(sony_bl_props.dev);
3145} 3144}
3146 3145
3147static int sony_nc_add(struct acpi_device *device) 3146static int sony_nc_add(struct acpi_device *device)
@@ -3716,8 +3715,7 @@ static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
3716 dev->event_types = type2_events; 3715 dev->event_types = type2_events;
3717 3716
3718out: 3717out:
3719 if (pcidev) 3718 pci_dev_put(pcidev);
3720 pci_dev_put(pcidev);
3721 3719
3722 pr_info("detected Type%d model\n", 3720 pr_info("detected Type%d model\n",
3723 dev->model == SONYPI_DEVICE_TYPE1 ? 1 : 3721 dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 6414cfe5d848..c3d11fabc46f 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6557,6 +6557,17 @@ static struct ibm_struct brightness_driver_data = {
6557 * bits 3-0 (volume). Other bits in NVRAM may have other functions, 6557 * bits 3-0 (volume). Other bits in NVRAM may have other functions,
6558 * such as bit 7 which is used to detect repeated presses of MUTE, 6558 * such as bit 7 which is used to detect repeated presses of MUTE,
6559 * and we leave them unchanged. 6559 * and we leave them unchanged.
6560 *
6561 * On newer Lenovo ThinkPads, the EC can automatically change the volume
6562 * in response to user input. Unfortunately, this rarely works well.
6563 * The laptop changes the state of its internal MUTE gate and, on some
6564 * models, sends KEY_MUTE, causing any user code that responds to the
6565 * mute button to get confused. The hardware MUTE gate is also
6566 * unnecessary, since user code can handle the mute button without
6567 * kernel or EC help.
6568 *
6569 * To avoid confusing userspace, we simply disable all EC-based mute
6570 * and volume controls when possible.
6560 */ 6571 */
6561 6572
6562#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT 6573#ifdef CONFIG_THINKPAD_ACPI_ALSA_SUPPORT
@@ -6611,11 +6622,21 @@ enum tpacpi_volume_capabilities {
6611 TPACPI_VOL_CAP_MAX 6622 TPACPI_VOL_CAP_MAX
6612}; 6623};
6613 6624
6625enum tpacpi_mute_btn_mode {
6626 TP_EC_MUTE_BTN_LATCH = 0, /* Mute mutes; up/down unmutes */
6627 /* We don't know what mode 1 is. */
6628 TP_EC_MUTE_BTN_NONE = 2, /* Mute and up/down are just keys */
6629 TP_EC_MUTE_BTN_TOGGLE = 3, /* Mute toggles; up/down unmutes */
6630};
6631
6614static enum tpacpi_volume_access_mode volume_mode = 6632static enum tpacpi_volume_access_mode volume_mode =
6615 TPACPI_VOL_MODE_MAX; 6633 TPACPI_VOL_MODE_MAX;
6616 6634
6617static enum tpacpi_volume_capabilities volume_capabilities; 6635static enum tpacpi_volume_capabilities volume_capabilities;
6618static bool volume_control_allowed; 6636static bool volume_control_allowed;
6637static bool software_mute_requested = true;
6638static bool software_mute_active;
6639static int software_mute_orig_mode;
6619 6640
6620/* 6641/*
6621 * Used to syncronize writers to TP_EC_AUDIO and 6642 * Used to syncronize writers to TP_EC_AUDIO and
@@ -6633,6 +6654,8 @@ static void tpacpi_volume_checkpoint_nvram(void)
6633 return; 6654 return;
6634 if (!volume_control_allowed) 6655 if (!volume_control_allowed)
6635 return; 6656 return;
6657 if (software_mute_active)
6658 return;
6636 6659
6637 vdbg_printk(TPACPI_DBG_MIXER, 6660 vdbg_printk(TPACPI_DBG_MIXER,
6638 "trying to checkpoint mixer state to NVRAM...\n"); 6661 "trying to checkpoint mixer state to NVRAM...\n");
@@ -6694,6 +6717,12 @@ static int volume_set_status_ec(const u8 status)
6694 6717
6695 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status); 6718 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
6696 6719
6720 /*
6721 * On X200s, and possibly on others, it can take a while for
6722 * reads to become correct.
6723 */
6724 msleep(1);
6725
6697 return 0; 6726 return 0;
6698} 6727}
6699 6728
@@ -6776,6 +6805,57 @@ unlock:
6776 return rc; 6805 return rc;
6777} 6806}
6778 6807
6808static int volume_set_software_mute(bool startup)
6809{
6810 int result;
6811
6812 if (!tpacpi_is_lenovo())
6813 return -ENODEV;
6814
6815 if (startup) {
6816 if (!acpi_evalf(ec_handle, &software_mute_orig_mode,
6817 "HAUM", "qd"))
6818 return -EIO;
6819
6820 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6821 "Initial HAUM setting was %d\n",
6822 software_mute_orig_mode);
6823 }
6824
6825 if (!acpi_evalf(ec_handle, &result, "SAUM", "qdd",
6826 (int)TP_EC_MUTE_BTN_NONE))
6827 return -EIO;
6828
6829 if (result != TP_EC_MUTE_BTN_NONE)
6830 pr_warn("Unexpected SAUM result %d\n",
6831 result);
6832
6833 /*
6834 * In software mute mode, the standard codec controls take
6835 * precendence, so we unmute the ThinkPad HW switch at
6836 * startup. Just on case there are SAUM-capable ThinkPads
6837 * with level controls, set max HW volume as well.
6838 */
6839 if (tp_features.mixer_no_level_control)
6840 result = volume_set_mute(false);
6841 else
6842 result = volume_set_status(TP_EC_VOLUME_MAX);
6843
6844 if (result != 0)
6845 pr_warn("Failed to unmute the HW mute switch\n");
6846
6847 return 0;
6848}
6849
6850static void volume_exit_software_mute(void)
6851{
6852 int r;
6853
6854 if (!acpi_evalf(ec_handle, &r, "SAUM", "qdd", software_mute_orig_mode)
6855 || r != software_mute_orig_mode)
6856 pr_warn("Failed to restore mute mode\n");
6857}
6858
6779static int volume_alsa_set_volume(const u8 vol) 6859static int volume_alsa_set_volume(const u8 vol)
6780{ 6860{
6781 dbg_printk(TPACPI_DBG_MIXER, 6861 dbg_printk(TPACPI_DBG_MIXER,
@@ -6883,7 +6963,12 @@ static void volume_suspend(void)
6883 6963
6884static void volume_resume(void) 6964static void volume_resume(void)
6885{ 6965{
6886 volume_alsa_notify_change(); 6966 if (software_mute_active) {
6967 if (volume_set_software_mute(false) < 0)
6968 pr_warn("Failed to restore software mute\n");
6969 } else {
6970 volume_alsa_notify_change();
6971 }
6887} 6972}
6888 6973
6889static void volume_shutdown(void) 6974static void volume_shutdown(void)
@@ -6899,6 +6984,9 @@ static void volume_exit(void)
6899 } 6984 }
6900 6985
6901 tpacpi_volume_checkpoint_nvram(); 6986 tpacpi_volume_checkpoint_nvram();
6987
6988 if (software_mute_active)
6989 volume_exit_software_mute();
6902} 6990}
6903 6991
6904static int __init volume_create_alsa_mixer(void) 6992static int __init volume_create_alsa_mixer(void)
@@ -7083,16 +7171,20 @@ static int __init volume_init(struct ibm_init_struct *iibm)
7083 "mute is supported, volume control is %s\n", 7171 "mute is supported, volume control is %s\n",
7084 str_supported(!tp_features.mixer_no_level_control)); 7172 str_supported(!tp_features.mixer_no_level_control));
7085 7173
7086 rc = volume_create_alsa_mixer(); 7174 if (software_mute_requested && volume_set_software_mute(true) == 0) {
7087 if (rc) { 7175 software_mute_active = true;
7088 pr_err("Could not create the ALSA mixer interface\n"); 7176 } else {
7089 return rc; 7177 rc = volume_create_alsa_mixer();
7090 } 7178 if (rc) {
7179 pr_err("Could not create the ALSA mixer interface\n");
7180 return rc;
7181 }
7091 7182
7092 pr_info("Console audio control enabled, mode: %s\n", 7183 pr_info("Console audio control enabled, mode: %s\n",
7093 (volume_control_allowed) ? 7184 (volume_control_allowed) ?
7094 "override (read/write)" : 7185 "override (read/write)" :
7095 "monitor (read only)"); 7186 "monitor (read only)");
7187 }
7096 7188
7097 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER, 7189 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
7098 "registering volume hotkeys as change notification\n"); 7190 "registering volume hotkeys as change notification\n");
@@ -9089,6 +9181,10 @@ MODULE_PARM_DESC(volume_control,
9089 "Enables software override for the console audio " 9181 "Enables software override for the console audio "
9090 "control when true"); 9182 "control when true");
9091 9183
9184module_param_named(software_mute, software_mute_requested, bool, 0444);
9185MODULE_PARM_DESC(software_mute,
9186 "Request full software mute control");
9187
9092/* ALSA module API parameters */ 9188/* ALSA module API parameters */
9093module_param_named(index, alsa_index, int, 0444); 9189module_param_named(index, alsa_index, int, 0444);
9094MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer"); 9190MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index ab6151f05420..fc34a71866ed 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -186,6 +186,7 @@ static struct toshiba_acpi_dev *toshiba_acpi;
186 186
187static const struct acpi_device_id toshiba_device_ids[] = { 187static const struct acpi_device_id toshiba_device_ids[] = {
188 {"TOS6200", 0}, 188 {"TOS6200", 0},
189 {"TOS6207", 0},
189 {"TOS6208", 0}, 190 {"TOS6208", 0},
190 {"TOS1900", 0}, 191 {"TOS1900", 0},
191 {"", 0}, 192 {"", 0},
@@ -928,9 +929,7 @@ static int lcd_proc_open(struct inode *inode, struct file *file)
928 929
929static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) 930static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
930{ 931{
931 u32 in[TCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 }; 932 u32 hci_result;
932 u32 out[TCI_WORDS];
933 acpi_status status;
934 933
935 if (dev->tr_backlight_supported) { 934 if (dev->tr_backlight_supported) {
936 bool enable = !value; 935 bool enable = !value;
@@ -941,20 +940,9 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
941 value--; 940 value--;
942 } 941 }
943 942
944 in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT; 943 value = value << HCI_LCD_BRIGHTNESS_SHIFT;
945 status = tci_raw(dev, in, out); 944 hci_result = hci_write1(dev, HCI_LCD_BRIGHTNESS, value);
946 if (ACPI_FAILURE(status) || out[0] == TOS_FAILURE) { 945 return hci_result == TOS_SUCCESS ? 0 : -EIO;
947 pr_err("ACPI call to set brightness failed");
948 return -EIO;
949 }
950 /* Extra check for "incomplete" backlight method, where the AML code
951 * doesn't check for HCI_SET or HCI_GET and returns TOS_SUCCESS,
952 * the actual brightness, and in some cases the max brightness.
953 */
954 if (out[2] > 0 || out[3] == 0xE000)
955 return -ENODEV;
956
957 return out[0] == TOS_SUCCESS ? 0 : -EIO;
958} 946}
959 947
960static int set_lcd_status(struct backlight_device *bd) 948static int set_lcd_status(struct backlight_device *bd)
@@ -1406,12 +1394,6 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
1406 if (ret) 1394 if (ret)
1407 return ret; 1395 return ret;
1408 1396
1409 /* Update sysfs entries on successful mode change*/
1410 ret = sysfs_update_group(&toshiba->acpi_dev->dev.kobj,
1411 &toshiba_attr_group);
1412 if (ret)
1413 return ret;
1414
1415 toshiba->kbd_mode = mode; 1397 toshiba->kbd_mode = mode;
1416 } 1398 }
1417 1399
@@ -1586,10 +1568,32 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
1586 return exists ? attr->mode : 0; 1568 return exists ? attr->mode : 0;
1587} 1569}
1588 1570
1571/*
1572 * Hotkeys
1573 */
1574static int toshiba_acpi_enable_hotkeys(struct toshiba_acpi_dev *dev)
1575{
1576 acpi_status status;
1577 u32 result;
1578
1579 status = acpi_evaluate_object(dev->acpi_dev->handle,
1580 "ENAB", NULL, NULL);
1581 if (ACPI_FAILURE(status))
1582 return -ENODEV;
1583
1584 result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE);
1585 if (result == TOS_FAILURE)
1586 return -EIO;
1587 else if (result == TOS_NOT_SUPPORTED)
1588 return -ENODEV;
1589
1590 return 0;
1591}
1592
1589static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str, 1593static bool toshiba_acpi_i8042_filter(unsigned char data, unsigned char str,
1590 struct serio *port) 1594 struct serio *port)
1591{ 1595{
1592 if (str & 0x20) 1596 if (str & I8042_STR_AUXDATA)
1593 return false; 1597 return false;
1594 1598
1595 if (unlikely(data == 0xe0)) 1599 if (unlikely(data == 0xe0))
@@ -1648,9 +1652,45 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
1648 pr_info("Unknown key %x\n", scancode); 1652 pr_info("Unknown key %x\n", scancode);
1649} 1653}
1650 1654
1655static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev)
1656{
1657 u32 hci_result, value;
1658 int retries = 3;
1659 int scancode;
1660
1661 if (dev->info_supported) {
1662 scancode = toshiba_acpi_query_hotkey(dev);
1663 if (scancode < 0)
1664 pr_err("Failed to query hotkey event\n");
1665 else if (scancode != 0)
1666 toshiba_acpi_report_hotkey(dev, scancode);
1667 } else if (dev->system_event_supported) {
1668 do {
1669 hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value);
1670 switch (hci_result) {
1671 case TOS_SUCCESS:
1672 toshiba_acpi_report_hotkey(dev, (int)value);
1673 break;
1674 case TOS_NOT_SUPPORTED:
1675 /*
1676 * This is a workaround for an unresolved
1677 * issue on some machines where system events
1678 * sporadically become disabled.
1679 */
1680 hci_result =
1681 hci_write1(dev, HCI_SYSTEM_EVENT, 1);
1682 pr_notice("Re-enabled hotkeys\n");
1683 /* fall through */
1684 default:
1685 retries--;
1686 break;
1687 }
1688 } while (retries && hci_result != TOS_FIFO_EMPTY);
1689 }
1690}
1691
1651static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) 1692static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
1652{ 1693{
1653 acpi_status status;
1654 acpi_handle ec_handle; 1694 acpi_handle ec_handle;
1655 int error; 1695 int error;
1656 u32 hci_result; 1696 u32 hci_result;
@@ -1677,7 +1717,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
1677 * supported, so if it's present set up an i8042 key filter 1717 * supported, so if it's present set up an i8042 key filter
1678 * for this purpose. 1718 * for this purpose.
1679 */ 1719 */
1680 status = AE_ERROR;
1681 ec_handle = ec_get_handle(); 1720 ec_handle = ec_get_handle();
1682 if (ec_handle && acpi_has_method(ec_handle, "NTFY")) { 1721 if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
1683 INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work); 1722 INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
@@ -1708,10 +1747,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
1708 goto err_remove_filter; 1747 goto err_remove_filter;
1709 } 1748 }
1710 1749
1711 status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", NULL, NULL); 1750 error = toshiba_acpi_enable_hotkeys(dev);
1712 if (ACPI_FAILURE(status)) { 1751 if (error) {
1713 pr_info("Unable to enable hotkeys\n"); 1752 pr_info("Unable to enable hotkeys\n");
1714 error = -ENODEV;
1715 goto err_remove_filter; 1753 goto err_remove_filter;
1716 } 1754 }
1717 1755
@@ -1721,7 +1759,6 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
1721 goto err_remove_filter; 1759 goto err_remove_filter;
1722 } 1760 }
1723 1761
1724 hci_result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE);
1725 return 0; 1762 return 0;
1726 1763
1727 err_remove_filter: 1764 err_remove_filter:
@@ -1810,8 +1847,7 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
1810 rfkill_destroy(dev->bt_rfk); 1847 rfkill_destroy(dev->bt_rfk);
1811 } 1848 }
1812 1849
1813 if (dev->backlight_dev) 1850 backlight_device_unregister(dev->backlight_dev);
1814 backlight_device_unregister(dev->backlight_dev);
1815 1851
1816 if (dev->illumination_supported) 1852 if (dev->illumination_supported)
1817 led_classdev_unregister(&dev->led_dev); 1853 led_classdev_unregister(&dev->led_dev);
@@ -1967,41 +2003,29 @@ error:
1967static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) 2003static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
1968{ 2004{
1969 struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev); 2005 struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
1970 u32 hci_result, value; 2006 int ret;
1971 int retries = 3;
1972 int scancode;
1973
1974 if (event != 0x80)
1975 return;
1976 2007
1977 if (dev->info_supported) { 2008 switch (event) {
1978 scancode = toshiba_acpi_query_hotkey(dev); 2009 case 0x80: /* Hotkeys and some system events */
1979 if (scancode < 0) 2010 toshiba_acpi_process_hotkeys(dev);
1980 pr_err("Failed to query hotkey event\n"); 2011 break;
1981 else if (scancode != 0) 2012 case 0x92: /* Keyboard backlight mode changed */
1982 toshiba_acpi_report_hotkey(dev, scancode); 2013 /* Update sysfs entries */
1983 } else if (dev->system_event_supported) { 2014 ret = sysfs_update_group(&acpi_dev->dev.kobj,
1984 do { 2015 &toshiba_attr_group);
1985 hci_result = hci_read1(dev, HCI_SYSTEM_EVENT, &value); 2016 if (ret)
1986 switch (hci_result) { 2017 pr_err("Unable to update sysfs entries\n");
1987 case TOS_SUCCESS: 2018 break;
1988 toshiba_acpi_report_hotkey(dev, (int)value); 2019 case 0x81: /* Unknown */
1989 break; 2020 case 0x82: /* Unknown */
1990 case TOS_NOT_SUPPORTED: 2021 case 0x83: /* Unknown */
1991 /* 2022 case 0x8c: /* Unknown */
1992 * This is a workaround for an unresolved 2023 case 0x8e: /* Unknown */
1993 * issue on some machines where system events 2024 case 0x8f: /* Unknown */
1994 * sporadically become disabled. 2025 case 0x90: /* Unknown */
1995 */ 2026 default:
1996 hci_result = 2027 pr_info("Unknown event received %x\n", event);
1997 hci_write1(dev, HCI_SYSTEM_EVENT, 1); 2028 break;
1998 pr_notice("Re-enabled hotkeys\n");
1999 /* fall through */
2000 default:
2001 retries--;
2002 break;
2003 }
2004 } while (retries && hci_result != TOS_FIFO_EMPTY);
2005 } 2029 }
2006} 2030}
2007 2031
@@ -2020,16 +2044,12 @@ static int toshiba_acpi_suspend(struct device *device)
2020static int toshiba_acpi_resume(struct device *device) 2044static int toshiba_acpi_resume(struct device *device)
2021{ 2045{
2022 struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device)); 2046 struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
2023 u32 result; 2047 int error;
2024 acpi_status status;
2025 2048
2026 if (dev->hotkey_dev) { 2049 if (dev->hotkey_dev) {
2027 status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB", 2050 error = toshiba_acpi_enable_hotkeys(dev);
2028 NULL, NULL); 2051 if (error)
2029 if (ACPI_FAILURE(status))
2030 pr_info("Unable to re-enable hotkeys\n"); 2052 pr_info("Unable to re-enable hotkeys\n");
2031
2032 result = hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE);
2033 } 2053 }
2034 2054
2035 return 0; 2055 return 0;