aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-16 11:32:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-16 11:32:27 -0400
commit605f884d05cc0de8c3bde36281d58216011f51a5 (patch)
tree28d62f20b36b059c397bbf8e7e9a033b638990d0
parent49899007b9401486421c99bb269db89b88136e47 (diff)
parent186e4e89a0922d75fba476f15b723e541cc34bea (diff)
Merge branch 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86
Pull x86 platform driver updates from Matthew Garrett: "A moderate number of changes, but nothing awfully significant. A lot of const cleanups, some reworking and additions to the rfkill quirks in the asus driver, a new driver for generating falling laptop events on Toshibas and some misc fixes. Maybe vendors have stopped inventing things" * 'for_linus' of git://cavan.codon.org.uk/platform-drivers-x86: (41 commits) platform/x86: Enable build support for toshiba_haps Documentation: Add file about toshiba_haps module platform/x86: Toshiba HDD Active Protection Sensor asus-nb-wmi: Add wapf4 quirk for the U32U alienware-wmi: make hdmi_mux enabled on case-by-case basis ideapad-laptop: Constify DMI table and other r/o variables asus-nb-wmi.c: Rename x401u quirk to wapf4 compal-laptop: correct invalid hwmon name toshiba_acpi: Add Qosmio X75-A to the alt keymap dmi list toshiba_acpi: Add extra check to backlight code Fix log message about future removal of interface ideapad-laptop: Disable touchpad interface on Yoga models asus-nb-wmi: Add wapf4 quirk for the X550CC intel_ips: Make ips_mcp_limits variables static thinkpad_acpi: Mark volume_alsa_control_{vol,mute} as __initdata fujitsu-laptop: Mark fujitsu_dmi_table[] DMI table as __initconst hp-wmi: Add missing __init annotations to initialization code hp_accel: Constify ACPI and DMI tables fujitsu-tablet: Mark DMI callbacks as __init code dell-laptop: Mark dell_quirks[] DMI table as __initconst ...
-rw-r--r--Documentation/laptops/00-INDEX2
-rw-r--r--Documentation/laptops/toshiba_haps.txt76
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/platform/x86/Kconfig19
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/acer-wmi.c54
-rw-r--r--drivers/platform/x86/alienware-wmi.c26
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c80
-rw-r--r--drivers/platform/x86/asus-wmi.c16
-rw-r--r--drivers/platform/x86/compal-laptop.c2
-rw-r--r--drivers/platform/x86/dell-laptop.c6
-rw-r--r--drivers/platform/x86/eeepc-laptop.c8
-rw-r--r--drivers/platform/x86/eeepc-wmi.c2
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c19
-rw-r--r--drivers/platform/x86/fujitsu-tablet.c6
-rw-r--r--drivers/platform/x86/hp-wmi.c6
-rw-r--r--drivers/platform/x86/hp_accel.c4
-rw-r--r--drivers/platform/x86/ideapad-laptop.c72
-rw-r--r--drivers/platform/x86/intel_ips.c6
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c8
-rw-r--r--drivers/platform/x86/toshiba_acpi.c30
-rw-r--r--drivers/platform/x86/toshiba_haps.c265
-rw-r--r--drivers/platform/x86/wmi.c4
24 files changed, 608 insertions, 108 deletions
diff --git a/Documentation/laptops/00-INDEX b/Documentation/laptops/00-INDEX
index d399ae1fc724..a3b4f209e562 100644
--- a/Documentation/laptops/00-INDEX
+++ b/Documentation/laptops/00-INDEX
@@ -18,3 +18,5 @@ sonypi.txt
18 - info on Linux Sony Programmable I/O Device support. 18 - info on Linux Sony Programmable I/O Device support.
19thinkpad-acpi.txt 19thinkpad-acpi.txt
20 - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver. 20 - information on the (IBM and Lenovo) ThinkPad ACPI Extras driver.
21toshiba_haps.txt
22 - information on the Toshiba HDD Active Protection Sensor driver.
diff --git a/Documentation/laptops/toshiba_haps.txt b/Documentation/laptops/toshiba_haps.txt
new file mode 100644
index 000000000000..11dbcfdc9e7a
--- /dev/null
+++ b/Documentation/laptops/toshiba_haps.txt
@@ -0,0 +1,76 @@
1Kernel driver toshiba_haps
2Toshiba HDD Active Protection Sensor
3====================================
4
5Author: Azael Avalos <coproscefalo@gmail.com>
6
7
80. Contents
9-----------
10
111. Description
122. Interface
133. Accelerometer axes
144. Supported devices
155. Usage
16
17
181. Description
19--------------
20
21This driver provides support for the accelerometer found in various Toshiba
22laptops, being called "Toshiba HDD Protection - Shock Sensor" officialy,
23and detects laptops automatically with this device.
24On Windows, Toshiba provided software monitors this device and provides
25automatic HDD protection (head unload) on sudden moves or harsh vibrations,
26however, this driver only provides a notification via a sysfs file to let
27userspace tools or daemons act accordingly, as well as providing a sysfs
28file to set the desired protection level or sensor sensibility.
29
30
312. Interface
32------------
33
34This device comes with 3 methods:
35_STA - Checks existence of the device, returning Zero if the device does not
36 exists or is not supported.
37PTLV - Sets the desired protection level.
38RSSS - Shuts down the HDD protection interface for a few seconds,
39 then restores normal operation.
40
41Note:
42The presence of Solid State Drives (SSD) can make this driver to fail loading,
43given the fact that such drives have no movable parts, and thus, not requiring
44any "protection" as well as failing during the evaluation of the _STA method
45found under this device.
46
47
483. Accelerometer axes
49---------------------
50
51This device does not report any axes, however, to query the sensor position
52a couple HCI (Hardware Configuration Interface) calls (0x6D and 0xA6) are
53provided to query such information, handled by the kernel module toshiba_acpi
54since kernel version 3.15.
55
56
574. Supported devices
58--------------------
59
60This driver binds itself to the ACPI device TOS620A, and any Toshiba laptop
61with this device is supported, given the fact that they have the presence of
62conventional HDD and not only SSD, or a combination of both HDD and SSD.
63
64
655. Usage
66--------
67
68The sysfs files under /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS620A:00/ are:
69protection_level - The protection_level is readable and writeable, and
70 provides a way to let userspace query the current protection
71 level, as well as set the desired protection level, the
72 available protection levels are:
73 0 - Disabled | 1 - Low | 2 - Medium | 3 - High
74reset_protection - The reset_protection entry is writeable only, being "1"
75 the only parameter it accepts, it is used to trigger
76 a reset of the protection interface.
diff --git a/MAINTAINERS b/MAINTAINERS
index 3bf3fc26c891..aefa94841ff3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10017,7 +10017,7 @@ F: arch/x86/
10017X86 PLATFORM DRIVERS 10017X86 PLATFORM DRIVERS
10018M: Matthew Garrett <matthew.garrett@nebula.com> 10018M: Matthew Garrett <matthew.garrett@nebula.com>
10019L: platform-driver-x86@vger.kernel.org 10019L: platform-driver-x86@vger.kernel.org
10020T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git 10020T: git git://cavan.codon.org.uk/platform-drivers-x86.git
10021S: Maintained 10021S: Maintained
10022F: drivers/platform/x86/ 10022F: drivers/platform/x86/
10023 10023
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 172f26ce59ac..3bbcbf12c1fb 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -652,6 +652,25 @@ config TOSHIBA_BT_RFKILL
652 If you have a modern Toshiba laptop with a Bluetooth and an 652 If you have a modern Toshiba laptop with a Bluetooth and an
653 RFKill switch (such as the Portege R500), say Y. 653 RFKill switch (such as the Portege R500), say Y.
654 654
655config TOSHIBA_HAPS
656 tristate "Toshiba HDD Active Protection Sensor"
657 depends on ACPI
658 ---help---
659 This driver adds support for the built-in accelerometer
660 found on recent Toshiba laptops equiped with HID TOS620A
661 device.
662
663 This driver receives ACPI notify events 0x80 when the sensor
664 detects a sudden move or a harsh vibration, as well as an
665 ACPI notify event 0x81 whenever the movement or vibration has
666 been stabilized.
667
668 Also provides sysfs entries to get/set the desired protection
669 level and reseting the HDD protection interface.
670
671 If you have a recent Toshiba laptop with a built-in accelerometer
672 device, say Y.
673
655config ACPI_CMPC 674config ACPI_CMPC
656 tristate "CMPC Laptop Extras" 675 tristate "CMPC Laptop Extras"
657 depends on X86 && ACPI 676 depends on X86 && ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index c4ca428fd3db..f82232b1fc4d 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
38obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 38obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
39 39
40obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o 40obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
41obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o
41obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o 42obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o
42obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o 43obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
43obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o 44obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index bbf78b2d6d93..96a0b75c52c9 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -96,7 +96,7 @@ enum acer_wmi_event_ids {
96 WMID_ACCEL_EVENT = 0x5, 96 WMID_ACCEL_EVENT = 0x5,
97}; 97};
98 98
99static const struct key_entry acer_wmi_keymap[] = { 99static const struct key_entry acer_wmi_keymap[] __initconst = {
100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */ 100 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */
101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */ 101 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */
102 {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */ 102 {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */
@@ -294,7 +294,7 @@ struct quirk_entry {
294 294
295static struct quirk_entry *quirks; 295static struct quirk_entry *quirks;
296 296
297static void set_quirks(void) 297static void __init set_quirks(void)
298{ 298{
299 if (!interface) 299 if (!interface)
300 return; 300 return;
@@ -306,7 +306,7 @@ static void set_quirks(void)
306 interface->capability |= ACER_CAP_BRIGHTNESS; 306 interface->capability |= ACER_CAP_BRIGHTNESS;
307} 307}
308 308
309static int dmi_matched(const struct dmi_system_id *dmi) 309static int __init dmi_matched(const struct dmi_system_id *dmi)
310{ 310{
311 quirks = dmi->driver_data; 311 quirks = dmi->driver_data;
312 return 1; 312 return 1;
@@ -337,7 +337,7 @@ static struct quirk_entry quirk_lenovo_ideapad_s205 = {
337}; 337};
338 338
339/* The Aspire One has a dummy ACPI-WMI interface - disable it */ 339/* The Aspire One has a dummy ACPI-WMI interface - disable it */
340static struct dmi_system_id acer_blacklist[] = { 340static const struct dmi_system_id acer_blacklist[] __initconst = {
341 { 341 {
342 .ident = "Acer Aspire One (SSD)", 342 .ident = "Acer Aspire One (SSD)",
343 .matches = { 343 .matches = {
@@ -355,7 +355,7 @@ static struct dmi_system_id acer_blacklist[] = {
355 {} 355 {}
356}; 356};
357 357
358static struct dmi_system_id acer_quirks[] = { 358static const struct dmi_system_id acer_quirks[] __initconst = {
359 { 359 {
360 .callback = dmi_matched, 360 .callback = dmi_matched,
361 .ident = "Acer Aspire 1360", 361 .ident = "Acer Aspire 1360",
@@ -530,14 +530,15 @@ static struct dmi_system_id acer_quirks[] = {
530 {} 530 {}
531}; 531};
532 532
533static int video_set_backlight_video_vendor(const struct dmi_system_id *d) 533static int __init
534video_set_backlight_video_vendor(const struct dmi_system_id *d)
534{ 535{
535 interface->capability &= ~ACER_CAP_BRIGHTNESS; 536 interface->capability &= ~ACER_CAP_BRIGHTNESS;
536 pr_info("Brightness must be controlled by generic video driver\n"); 537 pr_info("Brightness must be controlled by generic video driver\n");
537 return 0; 538 return 0;
538} 539}
539 540
540static const struct dmi_system_id video_vendor_dmi_table[] = { 541static const struct dmi_system_id video_vendor_dmi_table[] __initconst = {
541 { 542 {
542 .callback = video_set_backlight_video_vendor, 543 .callback = video_set_backlight_video_vendor,
543 .ident = "Acer TravelMate 4750", 544 .ident = "Acer TravelMate 4750",
@@ -582,7 +583,7 @@ static const struct dmi_system_id video_vendor_dmi_table[] = {
582}; 583};
583 584
584/* Find which quirks are needed for a particular vendor/ model pair */ 585/* Find which quirks are needed for a particular vendor/ model pair */
585static void find_quirks(void) 586static void __init find_quirks(void)
586{ 587{
587 if (!force_series) { 588 if (!force_series) {
588 dmi_check_system(acer_quirks); 589 dmi_check_system(acer_quirks);
@@ -749,7 +750,7 @@ static acpi_status AMW0_set_u32(u32 value, u32 cap)
749 return wmab_execute(&args, NULL); 750 return wmab_execute(&args, NULL);
750} 751}
751 752
752static acpi_status AMW0_find_mailled(void) 753static acpi_status __init AMW0_find_mailled(void)
753{ 754{
754 struct wmab_args args; 755 struct wmab_args args;
755 struct wmab_ret ret; 756 struct wmab_ret ret;
@@ -781,16 +782,16 @@ static acpi_status AMW0_find_mailled(void)
781 return AE_OK; 782 return AE_OK;
782} 783}
783 784
784static int AMW0_set_cap_acpi_check_device_found; 785static int AMW0_set_cap_acpi_check_device_found __initdata;
785 786
786static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle, 787static acpi_status __init AMW0_set_cap_acpi_check_device_cb(acpi_handle handle,
787 u32 level, void *context, void **retval) 788 u32 level, void *context, void **retval)
788{ 789{
789 AMW0_set_cap_acpi_check_device_found = 1; 790 AMW0_set_cap_acpi_check_device_found = 1;
790 return AE_OK; 791 return AE_OK;
791} 792}
792 793
793static const struct acpi_device_id norfkill_ids[] = { 794static const struct acpi_device_id norfkill_ids[] __initconst = {
794 { "VPC2004", 0}, 795 { "VPC2004", 0},
795 { "IBM0068", 0}, 796 { "IBM0068", 0},
796 { "LEN0068", 0}, 797 { "LEN0068", 0},
@@ -798,7 +799,7 @@ static const struct acpi_device_id norfkill_ids[] = {
798 { "", 0}, 799 { "", 0},
799}; 800};
800 801
801static int AMW0_set_cap_acpi_check_device(void) 802static int __init AMW0_set_cap_acpi_check_device(void)
802{ 803{
803 const struct acpi_device_id *id; 804 const struct acpi_device_id *id;
804 805
@@ -808,7 +809,7 @@ static int AMW0_set_cap_acpi_check_device(void)
808 return AMW0_set_cap_acpi_check_device_found; 809 return AMW0_set_cap_acpi_check_device_found;
809} 810}
810 811
811static acpi_status AMW0_set_capabilities(void) 812static acpi_status __init AMW0_set_capabilities(void)
812{ 813{
813 struct wmab_args args; 814 struct wmab_args args;
814 struct wmab_ret ret; 815 struct wmab_ret ret;
@@ -1184,7 +1185,7 @@ static acpi_status wmid_v2_set_u32(u32 value, u32 cap)
1184 return wmid3_set_device_status(value, device); 1185 return wmid3_set_device_status(value, device);
1185} 1186}
1186 1187
1187static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy) 1188static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d)
1188{ 1189{
1189 struct hotkey_function_type_aa *type_aa; 1190 struct hotkey_function_type_aa *type_aa;
1190 1191
@@ -1209,7 +1210,7 @@ static void type_aa_dmi_decode(const struct dmi_header *header, void *dummy)
1209 commun_fn_key_number = type_aa->commun_fn_key_number; 1210 commun_fn_key_number = type_aa->commun_fn_key_number;
1210} 1211}
1211 1212
1212static acpi_status WMID_set_capabilities(void) 1213static acpi_status __init WMID_set_capabilities(void)
1213{ 1214{
1214 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 1215 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1215 union acpi_object *obj; 1216 union acpi_object *obj;
@@ -1658,7 +1659,7 @@ static ssize_t show_bool_threeg(struct device *dev,
1658 u32 result; \ 1659 u32 result; \
1659 acpi_status status; 1660 acpi_status status;
1660 1661
1661 pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", 1662 pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n",
1662 current->comm); 1663 current->comm);
1663 status = get_u32(&result, ACER_CAP_THREEG); 1664 status = get_u32(&result, ACER_CAP_THREEG);
1664 if (ACPI_SUCCESS(status)) 1665 if (ACPI_SUCCESS(status))
@@ -1671,7 +1672,7 @@ static ssize_t set_bool_threeg(struct device *dev,
1671{ 1672{
1672 u32 tmp = simple_strtoul(buf, NULL, 10); 1673 u32 tmp = simple_strtoul(buf, NULL, 10);
1673 acpi_status status = set_u32(tmp, ACER_CAP_THREEG); 1674 acpi_status status = set_u32(tmp, ACER_CAP_THREEG);
1674 pr_info("This threeg sysfs will be removed in 2012 - used by: %s\n", 1675 pr_info("This threeg sysfs will be removed in 2014 - used by: %s\n",
1675 current->comm); 1676 current->comm);
1676 if (ACPI_FAILURE(status)) 1677 if (ACPI_FAILURE(status))
1677 return -EINVAL; 1678 return -EINVAL;
@@ -1683,7 +1684,7 @@ static DEVICE_ATTR(threeg, S_IRUGO | S_IWUSR, show_bool_threeg,
1683static ssize_t show_interface(struct device *dev, struct device_attribute *attr, 1684static ssize_t show_interface(struct device *dev, struct device_attribute *attr,
1684 char *buf) 1685 char *buf)
1685{ 1686{
1686 pr_info("This interface sysfs will be removed in 2012 - used by: %s\n", 1687 pr_info("This interface sysfs will be removed in 2014 - used by: %s\n",
1687 current->comm); 1688 current->comm);
1688 switch (interface->type) { 1689 switch (interface->type) {
1689 case ACER_AMW0: 1690 case ACER_AMW0:
@@ -1777,7 +1778,7 @@ static void acer_wmi_notify(u32 value, void *context)
1777 } 1778 }
1778} 1779}
1779 1780
1780static acpi_status 1781static acpi_status __init
1781wmid3_set_lm_mode(struct lm_input_params *params, 1782wmid3_set_lm_mode(struct lm_input_params *params,
1782 struct lm_return_value *return_value) 1783 struct lm_return_value *return_value)
1783{ 1784{
@@ -1811,7 +1812,7 @@ wmid3_set_lm_mode(struct lm_input_params *params,
1811 return status; 1812 return status;
1812} 1813}
1813 1814
1814static int acer_wmi_enable_ec_raw(void) 1815static int __init acer_wmi_enable_ec_raw(void)
1815{ 1816{
1816 struct lm_return_value return_value; 1817 struct lm_return_value return_value;
1817 acpi_status status; 1818 acpi_status status;
@@ -1834,7 +1835,7 @@ static int acer_wmi_enable_ec_raw(void)
1834 return status; 1835 return status;
1835} 1836}
1836 1837
1837static int acer_wmi_enable_lm(void) 1838static int __init acer_wmi_enable_lm(void)
1838{ 1839{
1839 struct lm_return_value return_value; 1840 struct lm_return_value return_value;
1840 acpi_status status; 1841 acpi_status status;
@@ -2043,6 +2044,7 @@ static int acer_platform_remove(struct platform_device *device)
2043 return 0; 2044 return 0;
2044} 2045}
2045 2046
2047#ifdef CONFIG_PM_SLEEP
2046static int acer_suspend(struct device *dev) 2048static int acer_suspend(struct device *dev)
2047{ 2049{
2048 u32 value; 2050 u32 value;
@@ -2083,6 +2085,10 @@ static int acer_resume(struct device *dev)
2083 2085
2084 return 0; 2086 return 0;
2085} 2087}
2088#else
2089#define acer_suspend NULL
2090#define acer_resume NULL
2091#endif
2086 2092
2087static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume); 2093static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
2088 2094
@@ -2120,7 +2126,7 @@ static int remove_sysfs(struct platform_device *device)
2120 return 0; 2126 return 0;
2121} 2127}
2122 2128
2123static int create_sysfs(void) 2129static int __init create_sysfs(void)
2124{ 2130{
2125 int retval = -ENOMEM; 2131 int retval = -ENOMEM;
2126 2132
@@ -2149,7 +2155,7 @@ static void remove_debugfs(void)
2149 debugfs_remove(interface->debug.root); 2155 debugfs_remove(interface->debug.root);
2150} 2156}
2151 2157
2152static int create_debugfs(void) 2158static int __init create_debugfs(void)
2153{ 2159{
2154 interface->debug.root = debugfs_create_dir("acer-wmi", NULL); 2160 interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
2155 if (!interface->debug.root) { 2161 if (!interface->debug.root) {
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c
index 297b6640213f..c5af23b64438 100644
--- a/drivers/platform/x86/alienware-wmi.c
+++ b/drivers/platform/x86/alienware-wmi.c
@@ -59,25 +59,33 @@ enum WMAX_CONTROL_STATES {
59 59
60struct quirk_entry { 60struct quirk_entry {
61 u8 num_zones; 61 u8 num_zones;
62 u8 hdmi_mux;
62}; 63};
63 64
64static struct quirk_entry *quirks; 65static struct quirk_entry *quirks;
65 66
66static struct quirk_entry quirk_unknown = { 67static struct quirk_entry quirk_unknown = {
67 .num_zones = 2, 68 .num_zones = 2,
69 .hdmi_mux = 0,
68}; 70};
69 71
70static struct quirk_entry quirk_x51_family = { 72static struct quirk_entry quirk_x51_family = {
71 .num_zones = 3, 73 .num_zones = 3,
74 .hdmi_mux = 0.
72}; 75};
73 76
74static int dmi_matched(const struct dmi_system_id *dmi) 77static struct quirk_entry quirk_asm100 = {
78 .num_zones = 2,
79 .hdmi_mux = 1,
80};
81
82static int __init dmi_matched(const struct dmi_system_id *dmi)
75{ 83{
76 quirks = dmi->driver_data; 84 quirks = dmi->driver_data;
77 return 1; 85 return 1;
78} 86}
79 87
80static struct dmi_system_id alienware_quirks[] = { 88static const struct dmi_system_id alienware_quirks[] __initconst = {
81 { 89 {
82 .callback = dmi_matched, 90 .callback = dmi_matched,
83 .ident = "Alienware X51 R1", 91 .ident = "Alienware X51 R1",
@@ -96,6 +104,15 @@ static struct dmi_system_id alienware_quirks[] = {
96 }, 104 },
97 .driver_data = &quirk_x51_family, 105 .driver_data = &quirk_x51_family,
98 }, 106 },
107 {
108 .callback = dmi_matched,
109 .ident = "Alienware ASM100",
110 .matches = {
111 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
112 DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"),
113 },
114 .driver_data = &quirk_asm100,
115 },
99 {} 116 {}
100}; 117};
101 118
@@ -537,7 +554,8 @@ static struct attribute_group hdmi_attribute_group = {
537 554
538static void remove_hdmi(struct platform_device *dev) 555static void remove_hdmi(struct platform_device *dev)
539{ 556{
540 sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group); 557 if (quirks->hdmi_mux > 0)
558 sysfs_remove_group(&dev->dev.kobj, &hdmi_attribute_group);
541} 559}
542 560
543static int create_hdmi(struct platform_device *dev) 561static int create_hdmi(struct platform_device *dev)
@@ -583,7 +601,7 @@ static int __init alienware_wmi_init(void)
583 if (ret) 601 if (ret)
584 goto fail_platform_device2; 602 goto fail_platform_device2;
585 603
586 if (interface == WMAX) { 604 if (quirks->hdmi_mux > 0) {
587 ret = create_hdmi(platform_device); 605 ret = create_hdmi(platform_device);
588 if (ret) 606 if (ret)
589 goto fail_prep_hdmi; 607 goto fail_prep_hdmi;
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index ddf0eefd862c..3a4951f46065 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -70,17 +70,35 @@ static struct quirk_entry quirk_asus_x55u = {
70 .no_display_toggle = true, 70 .no_display_toggle = true,
71}; 71};
72 72
73static struct quirk_entry quirk_asus_x401u = { 73static struct quirk_entry quirk_asus_wapf4 = {
74 .wapf = 4, 74 .wapf = 4,
75}; 75};
76 76
77static struct quirk_entry quirk_asus_x200ca = {
78 .wapf = 2,
79};
80
77static int dmi_matched(const struct dmi_system_id *dmi) 81static int dmi_matched(const struct dmi_system_id *dmi)
78{ 82{
79 quirks = dmi->driver_data; 83 quirks = dmi->driver_data;
80 return 1; 84 return 1;
81} 85}
82 86
83static struct dmi_system_id asus_quirks[] = { 87static const struct dmi_system_id asus_quirks[] = {
88 {
89 .callback = dmi_matched,
90 .ident = "ASUSTeK COMPUTER INC. U32U",
91 .matches = {
92 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
93 DMI_MATCH(DMI_PRODUCT_NAME, "U32U"),
94 },
95 /*
96 * Note this machine has a Brazos APU, and most Brazos Asus
97 * machines need quirk_asus_x55u / wmi_backlight_power but
98 * here acpi-video seems to work fine for backlight control.
99 */
100 .driver_data = &quirk_asus_wapf4,
101 },
84 { 102 {
85 .callback = dmi_matched, 103 .callback = dmi_matched,
86 .ident = "ASUSTeK COMPUTER INC. X401U", 104 .ident = "ASUSTeK COMPUTER INC. X401U",
@@ -97,7 +115,7 @@ static struct dmi_system_id asus_quirks[] = {
97 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 115 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
98 DMI_MATCH(DMI_PRODUCT_NAME, "X401A"), 116 DMI_MATCH(DMI_PRODUCT_NAME, "X401A"),
99 }, 117 },
100 .driver_data = &quirk_asus_x401u, 118 .driver_data = &quirk_asus_wapf4,
101 }, 119 },
102 { 120 {
103 .callback = dmi_matched, 121 .callback = dmi_matched,
@@ -106,7 +124,7 @@ static struct dmi_system_id asus_quirks[] = {
106 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 124 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
107 DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"), 125 DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"),
108 }, 126 },
109 .driver_data = &quirk_asus_x401u, 127 .driver_data = &quirk_asus_wapf4,
110 }, 128 },
111 { 129 {
112 .callback = dmi_matched, 130 .callback = dmi_matched,
@@ -124,7 +142,7 @@ static struct dmi_system_id asus_quirks[] = {
124 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 142 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
125 DMI_MATCH(DMI_PRODUCT_NAME, "X501A"), 143 DMI_MATCH(DMI_PRODUCT_NAME, "X501A"),
126 }, 144 },
127 .driver_data = &quirk_asus_x401u, 145 .driver_data = &quirk_asus_wapf4,
128 }, 146 },
129 { 147 {
130 .callback = dmi_matched, 148 .callback = dmi_matched,
@@ -133,7 +151,7 @@ static struct dmi_system_id asus_quirks[] = {
133 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 151 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
134 DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"), 152 DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"),
135 }, 153 },
136 .driver_data = &quirk_asus_x401u, 154 .driver_data = &quirk_asus_wapf4,
137 }, 155 },
138 { 156 {
139 .callback = dmi_matched, 157 .callback = dmi_matched,
@@ -142,7 +160,25 @@ static struct dmi_system_id asus_quirks[] = {
142 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 160 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
143 DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"), 161 DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"),
144 }, 162 },
145 .driver_data = &quirk_asus_x401u, 163 .driver_data = &quirk_asus_wapf4,
164 },
165 {
166 .callback = dmi_matched,
167 .ident = "ASUSTeK COMPUTER INC. X550CC",
168 .matches = {
169 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
170 DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"),
171 },
172 .driver_data = &quirk_asus_wapf4,
173 },
174 {
175 .callback = dmi_matched,
176 .ident = "ASUSTeK COMPUTER INC. X550CL",
177 .matches = {
178 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
179 DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"),
180 },
181 .driver_data = &quirk_asus_wapf4,
146 }, 182 },
147 { 183 {
148 .callback = dmi_matched, 184 .callback = dmi_matched,
@@ -151,7 +187,7 @@ static struct dmi_system_id asus_quirks[] = {
151 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 187 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
152 DMI_MATCH(DMI_PRODUCT_NAME, "X55A"), 188 DMI_MATCH(DMI_PRODUCT_NAME, "X55A"),
153 }, 189 },
154 .driver_data = &quirk_asus_x401u, 190 .driver_data = &quirk_asus_wapf4,
155 }, 191 },
156 { 192 {
157 .callback = dmi_matched, 193 .callback = dmi_matched,
@@ -160,7 +196,7 @@ static struct dmi_system_id asus_quirks[] = {
160 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
161 DMI_MATCH(DMI_PRODUCT_NAME, "X55C"), 197 DMI_MATCH(DMI_PRODUCT_NAME, "X55C"),
162 }, 198 },
163 .driver_data = &quirk_asus_x401u, 199 .driver_data = &quirk_asus_wapf4,
164 }, 200 },
165 { 201 {
166 .callback = dmi_matched, 202 .callback = dmi_matched,
@@ -178,7 +214,7 @@ static struct dmi_system_id asus_quirks[] = {
178 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 214 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
179 DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"), 215 DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"),
180 }, 216 },
181 .driver_data = &quirk_asus_x401u, 217 .driver_data = &quirk_asus_wapf4,
182 }, 218 },
183 { 219 {
184 .callback = dmi_matched, 220 .callback = dmi_matched,
@@ -187,7 +223,16 @@ static struct dmi_system_id asus_quirks[] = {
187 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 223 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
188 DMI_MATCH(DMI_PRODUCT_NAME, "X75A"), 224 DMI_MATCH(DMI_PRODUCT_NAME, "X75A"),
189 }, 225 },
190 .driver_data = &quirk_asus_x401u, 226 .driver_data = &quirk_asus_wapf4,
227 },
228 {
229 .callback = dmi_matched,
230 .ident = "ASUSTeK COMPUTER INC. X75VBP",
231 .matches = {
232 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
233 DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"),
234 },
235 .driver_data = &quirk_asus_wapf4,
191 }, 236 },
192 { 237 {
193 .callback = dmi_matched, 238 .callback = dmi_matched,
@@ -196,7 +241,7 @@ static struct dmi_system_id asus_quirks[] = {
196 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 241 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
197 DMI_MATCH(DMI_PRODUCT_NAME, "1015E"), 242 DMI_MATCH(DMI_PRODUCT_NAME, "1015E"),
198 }, 243 },
199 .driver_data = &quirk_asus_x401u, 244 .driver_data = &quirk_asus_wapf4,
200 }, 245 },
201 { 246 {
202 .callback = dmi_matched, 247 .callback = dmi_matched,
@@ -205,7 +250,16 @@ static struct dmi_system_id asus_quirks[] = {
205 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 250 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
206 DMI_MATCH(DMI_PRODUCT_NAME, "1015U"), 251 DMI_MATCH(DMI_PRODUCT_NAME, "1015U"),
207 }, 252 },
208 .driver_data = &quirk_asus_x401u, 253 .driver_data = &quirk_asus_wapf4,
254 },
255 {
256 .callback = dmi_matched,
257 .ident = "ASUSTeK COMPUTER INC. X200CA",
258 .matches = {
259 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
260 DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"),
261 },
262 .driver_data = &quirk_asus_x200ca,
209 }, 263 },
210 {}, 264 {},
211}; 265};
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3c6ccedc82b6..21fc932da3a1 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -46,6 +46,7 @@
46#include <linux/platform_device.h> 46#include <linux/platform_device.h>
47#include <linux/thermal.h> 47#include <linux/thermal.h>
48#include <linux/acpi.h> 48#include <linux/acpi.h>
49#include <linux/dmi.h>
49#include <acpi/video.h> 50#include <acpi/video.h>
50 51
51#include "asus-wmi.h" 52#include "asus-wmi.h"
@@ -554,7 +555,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
554 goto error; 555 goto error;
555 } 556 }
556 557
557 if (wlan_led_presence(asus) && (asus->driver->quirks->wapf == 4)) { 558 if (wlan_led_presence(asus) && (asus->driver->quirks->wapf > 0)) {
558 INIT_WORK(&asus->wlan_led_work, wlan_led_update); 559 INIT_WORK(&asus->wlan_led_work, wlan_led_update);
559 560
560 asus->wlan_led.name = "asus::wlan"; 561 asus->wlan_led.name = "asus::wlan";
@@ -884,7 +885,7 @@ static int asus_new_rfkill(struct asus_wmi *asus,
884 return -EINVAL; 885 return -EINVAL;
885 886
886 if ((dev_id == ASUS_WMI_DEVID_WLAN) && 887 if ((dev_id == ASUS_WMI_DEVID_WLAN) &&
887 (asus->driver->quirks->wapf == 4)) 888 (asus->driver->quirks->wapf > 0))
888 rfkill_set_led_trigger_name(*rfkill, "asus-wlan"); 889 rfkill_set_led_trigger_name(*rfkill, "asus-wlan");
889 890
890 rfkill_init_sw_state(*rfkill, !result); 891 rfkill_init_sw_state(*rfkill, !result);
@@ -1270,10 +1271,7 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus)
1270 int power; 1271 int power;
1271 1272
1272 max = read_brightness_max(asus); 1273 max = read_brightness_max(asus);
1273 1274 if (max < 0)
1274 if (max == -ENODEV)
1275 max = 0;
1276 else if (max < 0)
1277 return max; 1275 return max;
1278 1276
1279 power = read_backlight_power(asus); 1277 power = read_backlight_power(asus);
@@ -1734,6 +1732,7 @@ static int asus_wmi_add(struct platform_device *pdev)
1734 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); 1732 struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
1735 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv); 1733 struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
1736 struct asus_wmi *asus; 1734 struct asus_wmi *asus;
1735 const char *chassis_type;
1737 acpi_status status; 1736 acpi_status status;
1738 int err; 1737 int err;
1739 u32 result; 1738 u32 result;
@@ -1770,6 +1769,11 @@ static int asus_wmi_add(struct platform_device *pdev)
1770 if (err) 1769 if (err)
1771 goto fail_rfkill; 1770 goto fail_rfkill;
1772 1771
1772 /* Some Asus desktop boards export an acpi-video backlight interface,
1773 stop this from showing up */
1774 chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
1775 if (chassis_type && !strcmp(chassis_type, "3"))
1776 acpi_video_dmi_promote_vendor();
1773 if (asus->driver->quirks->wmi_backlight_power) 1777 if (asus->driver->quirks->wmi_backlight_power)
1774 acpi_video_dmi_promote_vendor(); 1778 acpi_video_dmi_promote_vendor();
1775 if (!acpi_video_backlight_support()) { 1779 if (!acpi_video_backlight_support()) {
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 7297df2ebf50..26bfd7bb5c13 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -1028,7 +1028,7 @@ static int compal_probe(struct platform_device *pdev)
1028 return err; 1028 return err;
1029 1029
1030 hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, 1030 hwmon_dev = hwmon_device_register_with_groups(&pdev->dev,
1031 DRIVER_NAME, data, 1031 "compal", data,
1032 compal_hwmon_groups); 1032 compal_hwmon_groups);
1033 if (IS_ERR(hwmon_dev)) { 1033 if (IS_ERR(hwmon_dev)) {
1034 err = PTR_ERR(hwmon_dev); 1034 err = PTR_ERR(hwmon_dev);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index fed4111ac31a..233d2ee598a6 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -70,7 +70,7 @@ static struct quirk_entry quirk_dell_vostro_v130 = {
70 .touchpad_led = 1, 70 .touchpad_led = 1,
71}; 71};
72 72
73static int dmi_matched(const struct dmi_system_id *dmi) 73static int __init dmi_matched(const struct dmi_system_id *dmi)
74{ 74{
75 quirks = dmi->driver_data; 75 quirks = dmi->driver_data;
76 return 1; 76 return 1;
@@ -123,7 +123,7 @@ static const struct dmi_system_id dell_device_table[] __initconst = {
123}; 123};
124MODULE_DEVICE_TABLE(dmi, dell_device_table); 124MODULE_DEVICE_TABLE(dmi, dell_device_table);
125 125
126static struct dmi_system_id dell_quirks[] = { 126static const struct dmi_system_id dell_quirks[] __initconst = {
127 { 127 {
128 .callback = dmi_matched, 128 .callback = dmi_matched,
129 .ident = "Dell Vostro V130", 129 .ident = "Dell Vostro V130",
@@ -780,7 +780,7 @@ static struct led_classdev touchpad_led = {
780 .flags = LED_CORE_SUSPENDRESUME, 780 .flags = LED_CORE_SUSPENDRESUME,
781}; 781};
782 782
783static int touchpad_led_init(struct device *dev) 783static int __init touchpad_led_init(struct device *dev)
784{ 784{
785 return led_classdev_register(dev, &touchpad_led); 785 return led_classdev_register(dev, &touchpad_led);
786} 786}
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 9b0c57cd1d4a..bd533c22be57 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1053,20 +1053,20 @@ static ssize_t show_sys_hwmon(int (*get)(void), char *buf)
1053 return sprintf(buf, "%d\n", get()); 1053 return sprintf(buf, "%d\n", get());
1054} 1054}
1055 1055
1056#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ 1056#define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _get, _set) \
1057 static ssize_t show_##_name(struct device *dev, \ 1057 static ssize_t show_##_name(struct device *dev, \
1058 struct device_attribute *attr, \ 1058 struct device_attribute *attr, \
1059 char *buf) \ 1059 char *buf) \
1060 { \ 1060 { \
1061 return show_sys_hwmon(_set, buf); \ 1061 return show_sys_hwmon(_get, buf); \
1062 } \ 1062 } \
1063 static ssize_t store_##_name(struct device *dev, \ 1063 static ssize_t store_##_name(struct device *dev, \
1064 struct device_attribute *attr, \ 1064 struct device_attribute *attr, \
1065 const char *buf, size_t count) \ 1065 const char *buf, size_t count) \
1066 { \ 1066 { \
1067 return store_sys_hwmon(_get, buf, count); \ 1067 return store_sys_hwmon(_set, buf, count); \
1068 } \ 1068 } \
1069 static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name); 1069 static DEVICE_ATTR(_name, _mode, show_##_name, store_##_name)
1070 1070
1071EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); 1071EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL);
1072EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, 1072EEEPC_CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR,
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 6112933f6278..14fd2ecb06a1 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -145,7 +145,7 @@ static int dmi_matched(const struct dmi_system_id *dmi)
145 return 1; 145 return 1;
146} 146}
147 147
148static struct dmi_system_id asus_quirks[] = { 148static const struct dmi_system_id asus_quirks[] = {
149 { 149 {
150 .callback = dmi_matched, 150 .callback = dmi_matched,
151 .ident = "ASUSTeK Computer INC. 1000H", 151 .ident = "ASUSTeK Computer INC. 1000H",
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index e6f336270c21..87aa28c4280f 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -129,15 +129,14 @@
129#define FUJLAPTOP_DBG_INFO 0x0004 129#define FUJLAPTOP_DBG_INFO 0x0004
130#define FUJLAPTOP_DBG_TRACE 0x0008 130#define FUJLAPTOP_DBG_TRACE 0x0008
131 131
132#define dbg_printk(a_dbg_level, format, arg...) \ 132#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
133#define vdbg_printk(a_dbg_level, format, arg...) \
133 do { if (dbg_level & a_dbg_level) \ 134 do { if (dbg_level & a_dbg_level) \
134 printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \ 135 printk(FUJLAPTOP_DEBUG "%s: " format, __func__ , ## arg); \
135 } while (0) 136 } while (0)
136#ifdef CONFIG_FUJITSU_LAPTOP_DEBUG
137#define vdbg_printk(a_dbg_level, format, arg...) \
138 dbg_printk(a_dbg_level, format, ## arg)
139#else 137#else
140#define vdbg_printk(a_dbg_level, format, arg...) 138#define vdbg_printk(a_dbg_level, format, arg...) \
139 do { } while (0)
141#endif 140#endif
142 141
143/* Device controlling the backlight and associated keys */ 142/* Device controlling the backlight and associated keys */
@@ -564,7 +563,7 @@ static struct platform_driver fujitsupf_driver = {
564 } 563 }
565}; 564};
566 565
567static void dmi_check_cb_common(const struct dmi_system_id *id) 566static void __init dmi_check_cb_common(const struct dmi_system_id *id)
568{ 567{
569 pr_info("Identified laptop model '%s'\n", id->ident); 568 pr_info("Identified laptop model '%s'\n", id->ident);
570 if (use_alt_lcd_levels == -1) { 569 if (use_alt_lcd_levels == -1) {
@@ -578,7 +577,7 @@ static void dmi_check_cb_common(const struct dmi_system_id *id)
578 } 577 }
579} 578}
580 579
581static int dmi_check_cb_s6410(const struct dmi_system_id *id) 580static int __init dmi_check_cb_s6410(const struct dmi_system_id *id)
582{ 581{
583 dmi_check_cb_common(id); 582 dmi_check_cb_common(id);
584 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 583 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
@@ -586,7 +585,7 @@ static int dmi_check_cb_s6410(const struct dmi_system_id *id)
586 return 1; 585 return 1;
587} 586}
588 587
589static int dmi_check_cb_s6420(const struct dmi_system_id *id) 588static int __init dmi_check_cb_s6420(const struct dmi_system_id *id)
590{ 589{
591 dmi_check_cb_common(id); 590 dmi_check_cb_common(id);
592 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */ 591 fujitsu->keycode1 = KEY_SCREENLOCK; /* "Lock" */
@@ -594,7 +593,7 @@ static int dmi_check_cb_s6420(const struct dmi_system_id *id)
594 return 1; 593 return 1;
595} 594}
596 595
597static int dmi_check_cb_p8010(const struct dmi_system_id *id) 596static int __init dmi_check_cb_p8010(const struct dmi_system_id *id)
598{ 597{
599 dmi_check_cb_common(id); 598 dmi_check_cb_common(id);
600 fujitsu->keycode1 = KEY_HELP; /* "Support" */ 599 fujitsu->keycode1 = KEY_HELP; /* "Support" */
@@ -603,7 +602,7 @@ static int dmi_check_cb_p8010(const struct dmi_system_id *id)
603 return 1; 602 return 1;
604} 603}
605 604
606static struct dmi_system_id fujitsu_dmi_table[] = { 605static const struct dmi_system_id fujitsu_dmi_table[] __initconst = {
607 { 606 {
608 .ident = "Fujitsu Siemens S6410", 607 .ident = "Fujitsu Siemens S6410",
609 .matches = { 608 .matches = {
diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c
index c3784baceae3..53bdbb01bd3f 100644
--- a/drivers/platform/x86/fujitsu-tablet.c
+++ b/drivers/platform/x86/fujitsu-tablet.c
@@ -315,21 +315,21 @@ static irqreturn_t fujitsu_interrupt(int irq, void *dev_id)
315 return IRQ_HANDLED; 315 return IRQ_HANDLED;
316} 316}
317 317
318static void fujitsu_dmi_common(const struct dmi_system_id *dmi) 318static void __init fujitsu_dmi_common(const struct dmi_system_id *dmi)
319{ 319{
320 pr_info("%s\n", dmi->ident); 320 pr_info("%s\n", dmi->ident);
321 memcpy(fujitsu.config.keymap, dmi->driver_data, 321 memcpy(fujitsu.config.keymap, dmi->driver_data,
322 sizeof(fujitsu.config.keymap)); 322 sizeof(fujitsu.config.keymap));
323} 323}
324 324
325static int fujitsu_dmi_lifebook(const struct dmi_system_id *dmi) 325static int __init fujitsu_dmi_lifebook(const struct dmi_system_id *dmi)
326{ 326{
327 fujitsu_dmi_common(dmi); 327 fujitsu_dmi_common(dmi);
328 fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT; 328 fujitsu.config.quirks |= INVERT_TABLET_MODE_BIT;
329 return 1; 329 return 1;
330} 330}
331 331
332static int fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) 332static int __init fujitsu_dmi_stylistic(const struct dmi_system_id *dmi)
333{ 333{
334 fujitsu_dmi_common(dmi); 334 fujitsu_dmi_common(dmi);
335 fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK; 335 fujitsu.config.quirks |= FORCE_TABLET_MODE_IF_UNDOCK;
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 484a8673b835..4c559640dcba 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -295,7 +295,7 @@ static int hp_wmi_tablet_state(void)
295 return (state & 0x4) ? 1 : 0; 295 return (state & 0x4) ? 1 : 0;
296} 296}
297 297
298static int hp_wmi_bios_2009_later(void) 298static int __init hp_wmi_bios_2009_later(void)
299{ 299{
300 int state = 0; 300 int state = 0;
301 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state, 301 int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, 0, &state,
@@ -704,7 +704,7 @@ static void cleanup_sysfs(struct platform_device *device)
704 device_remove_file(&device->dev, &dev_attr_postcode); 704 device_remove_file(&device->dev, &dev_attr_postcode);
705} 705}
706 706
707static int hp_wmi_rfkill_setup(struct platform_device *device) 707static int __init hp_wmi_rfkill_setup(struct platform_device *device)
708{ 708{
709 int err; 709 int err;
710 int wireless = 0; 710 int wireless = 0;
@@ -806,7 +806,7 @@ register_wifi_error:
806 return err; 806 return err;
807} 807}
808 808
809static int hp_wmi_rfkill2_setup(struct platform_device *device) 809static int __init hp_wmi_rfkill2_setup(struct platform_device *device)
810{ 810{
811 int err, i; 811 int err, i;
812 struct bios_rfkill2_state state; 812 struct bios_rfkill2_state state;
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
index 3dc934438c28..13e14ec1d3d7 100644
--- a/drivers/platform/x86/hp_accel.c
+++ b/drivers/platform/x86/hp_accel.c
@@ -74,7 +74,7 @@ static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
74/* HP-specific accelerometer driver ------------------------------------ */ 74/* HP-specific accelerometer driver ------------------------------------ */
75 75
76/* For automatic insertion of the module */ 76/* For automatic insertion of the module */
77static struct acpi_device_id lis3lv02d_device_ids[] = { 77static const struct acpi_device_id lis3lv02d_device_ids[] = {
78 {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ 78 {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
79 {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */ 79 {"HPQ6000", 0}, /* HP Mobile Data Protection System PNP */
80 {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */ 80 {"HPQ6007", 0}, /* HP Mobile Data Protection System PNP */
@@ -192,7 +192,7 @@ DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
192 }, \ 192 }, \
193 .driver_data = &lis3lv02d_axis_##_axis \ 193 .driver_data = &lis3lv02d_axis_##_axis \
194} 194}
195static struct dmi_system_id lis3lv02d_dmi_ids[] = { 195static const struct dmi_system_id lis3lv02d_dmi_ids[] = {
196 /* product names are truncated to match all kinds of a same model */ 196 /* product names are truncated to match all kinds of a same model */
197 AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted), 197 AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
198 AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted), 198 AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index b4c495a62eec..fc468a3d95ce 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -87,6 +87,8 @@ struct ideapad_private {
87 struct backlight_device *blightdev; 87 struct backlight_device *blightdev;
88 struct dentry *debug; 88 struct dentry *debug;
89 unsigned long cfg; 89 unsigned long cfg;
90 bool has_hw_rfkill_switch;
91 bool has_touchpad_control;
90}; 92};
91 93
92static bool no_bt_rfkill; 94static bool no_bt_rfkill;
@@ -439,7 +441,7 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
439 return supported ? attr->mode : 0; 441 return supported ? attr->mode : 0;
440} 442}
441 443
442static struct attribute_group ideapad_attribute_group = { 444static const struct attribute_group ideapad_attribute_group = {
443 .is_visible = ideapad_is_visible, 445 .is_visible = ideapad_is_visible,
444 .attrs = ideapad_attributes 446 .attrs = ideapad_attributes
445}; 447};
@@ -454,7 +456,7 @@ struct ideapad_rfk_data {
454 int type; 456 int type;
455}; 457};
456 458
457const struct ideapad_rfk_data ideapad_rfk_data[] = { 459const const struct ideapad_rfk_data ideapad_rfk_data[] = {
458 { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN }, 460 { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
459 { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH }, 461 { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
460 { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN }, 462 { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
@@ -473,12 +475,14 @@ static struct rfkill_ops ideapad_rfk_ops = {
473 475
474static void ideapad_sync_rfk_state(struct ideapad_private *priv) 476static void ideapad_sync_rfk_state(struct ideapad_private *priv)
475{ 477{
476 unsigned long hw_blocked; 478 unsigned long hw_blocked = 0;
477 int i; 479 int i;
478 480
479 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) 481 if (priv->has_hw_rfkill_switch) {
480 return; 482 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
481 hw_blocked = !hw_blocked; 483 return;
484 hw_blocked = !hw_blocked;
485 }
482 486
483 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 487 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
484 if (priv->rfk[i]) 488 if (priv->rfk[i])
@@ -763,6 +767,9 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
763{ 767{
764 unsigned long value; 768 unsigned long value;
765 769
770 if (!priv->has_touchpad_control)
771 return;
772
766 /* Without reading from EC touchpad LED doesn't switch state */ 773 /* Without reading from EC touchpad LED doesn't switch state */
767 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) { 774 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
768 /* Some IdeaPads don't really turn off touchpad - they only 775 /* Some IdeaPads don't really turn off touchpad - they only
@@ -821,14 +828,39 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
821 } 828 }
822} 829}
823 830
824/* Blacklist for devices where the ideapad rfkill interface does not work */ 831/*
825static struct dmi_system_id rfkill_blacklist[] = { 832 * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
826 /* The Lenovo Yoga 2 11 always reports everything as blocked */ 833 * always results in 0 on these models, causing ideapad_laptop to wrongly
834 * report all radios as hardware-blocked.
835 */
836static struct dmi_system_id no_hw_rfkill_list[] = {
827 { 837 {
828 .ident = "Lenovo Yoga 2 11", 838 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
829 .matches = { 839 .matches = {
830 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 840 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
831 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), 841 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
842 },
843 },
844 {}
845};
846
847/*
848 * Some models don't offer touchpad ctrl through the ideapad interface, causing
849 * ideapad_sync_touchpad_state to send wrong touchpad enable/disable events.
850 */
851static struct dmi_system_id no_touchpad_ctrl_list[] = {
852 {
853 .ident = "Lenovo Yoga 1 series",
854 .matches = {
855 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
856 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga"),
857 },
858 },
859 {
860 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
861 .matches = {
862 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
863 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
832 }, 864 },
833 }, 865 },
834 {} 866 {}
@@ -856,6 +888,8 @@ static int ideapad_acpi_add(struct platform_device *pdev)
856 priv->cfg = cfg; 888 priv->cfg = cfg;
857 priv->adev = adev; 889 priv->adev = adev;
858 priv->platform_device = pdev; 890 priv->platform_device = pdev;
891 priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
892 priv->has_touchpad_control = !dmi_check_system(no_touchpad_ctrl_list);
859 893
860 ret = ideapad_sysfs_init(priv); 894 ret = ideapad_sysfs_init(priv);
861 if (ret) 895 if (ret)
@@ -869,11 +903,17 @@ static int ideapad_acpi_add(struct platform_device *pdev)
869 if (ret) 903 if (ret)
870 goto input_failed; 904 goto input_failed;
871 905
872 if (!dmi_check_system(rfkill_blacklist)) { 906 /*
873 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) 907 * On some models without a hw-switch (the yoga 2 13 at least)
874 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) 908 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
875 ideapad_register_rfkill(priv, i); 909 */
876 } 910 if (!priv->has_hw_rfkill_switch)
911 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
912
913 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
914 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
915 ideapad_register_rfkill(priv, i);
916
877 ideapad_sync_rfk_state(priv); 917 ideapad_sync_rfk_state(priv);
878 ideapad_sync_touchpad_state(priv); 918 ideapad_sync_touchpad_state(priv);
879 919
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index a0d1f576cf40..c0242ed13d9e 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -269,7 +269,7 @@ struct ips_mcp_limits {
269 269
270/* Max temps are -10 degrees C to avoid PROCHOT# */ 270/* Max temps are -10 degrees C to avoid PROCHOT# */
271 271
272struct ips_mcp_limits ips_sv_limits = { 272static struct ips_mcp_limits ips_sv_limits = {
273 .mcp_power_limit = 35000, 273 .mcp_power_limit = 35000,
274 .core_power_limit = 29000, 274 .core_power_limit = 29000,
275 .mch_power_limit = 20000, 275 .mch_power_limit = 20000,
@@ -277,7 +277,7 @@ struct ips_mcp_limits ips_sv_limits = {
277 .mch_temp_limit = 90 277 .mch_temp_limit = 90
278}; 278};
279 279
280struct ips_mcp_limits ips_lv_limits = { 280static struct ips_mcp_limits ips_lv_limits = {
281 .mcp_power_limit = 25000, 281 .mcp_power_limit = 25000,
282 .core_power_limit = 21000, 282 .core_power_limit = 21000,
283 .mch_power_limit = 13000, 283 .mch_power_limit = 13000,
@@ -285,7 +285,7 @@ struct ips_mcp_limits ips_lv_limits = {
285 .mch_temp_limit = 90 285 .mch_temp_limit = 90
286}; 286};
287 287
288struct ips_mcp_limits ips_ulv_limits = { 288static struct ips_mcp_limits ips_ulv_limits = {
289 .mcp_power_limit = 18000, 289 .mcp_power_limit = 18000,
290 .core_power_limit = 14000, 290 .core_power_limit = 14000,
291 .mch_power_limit = 11000, 291 .mch_power_limit = 11000,
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 9c5a07417b2b..26ad9ff12ac5 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -2389,7 +2389,7 @@ static int sony_nc_lid_resume_setup(struct platform_device *pd,
2389 lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store; 2389 lid_ctl->attrs[LID_RESUME_S3].store = sony_nc_lid_resume_store;
2390 } 2390 }
2391 for (i = 0; i < LID_RESUME_MAX && 2391 for (i = 0; i < LID_RESUME_MAX &&
2392 lid_ctl->attrs[LID_RESUME_S3].attr.name; i++) { 2392 lid_ctl->attrs[i].attr.name; i++) {
2393 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]); 2393 result = device_create_file(&pd->dev, &lid_ctl->attrs[i]);
2394 if (result) 2394 if (result)
2395 goto liderror; 2395 goto liderror;
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index d82f196e3cfe..3bbc6eb60de5 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -3174,7 +3174,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3174 KEY_UNKNOWN, 3174 KEY_UNKNOWN,
3175 3175
3176 /* Extra keys in use since the X240 / T440 / T540 */ 3176 /* Extra keys in use since the X240 / T440 / T540 */
3177 KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_COMPUTER, 3177 KEY_CONFIG, KEY_SEARCH, KEY_SCALE, KEY_FILE,
3178 }, 3178 },
3179 }; 3179 };
3180 3180
@@ -6144,7 +6144,7 @@ static int brightness_set(unsigned int value)
6144{ 6144{
6145 int res; 6145 int res;
6146 6146
6147 if (value > bright_maxlvl || value < 0) 6147 if (value > bright_maxlvl)
6148 return -EINVAL; 6148 return -EINVAL;
6149 6149
6150 vdbg_printk(TPACPI_DBG_BRGHT, 6150 vdbg_printk(TPACPI_DBG_BRGHT,
@@ -6860,7 +6860,7 @@ static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6860 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]); 6860 return volume_alsa_set_mute(!ucontrol->value.integer.value[0]);
6861} 6861}
6862 6862
6863static struct snd_kcontrol_new volume_alsa_control_vol = { 6863static struct snd_kcontrol_new volume_alsa_control_vol __initdata = {
6864 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6864 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6865 .name = "Console Playback Volume", 6865 .name = "Console Playback Volume",
6866 .index = 0, 6866 .index = 0,
@@ -6869,7 +6869,7 @@ static struct snd_kcontrol_new volume_alsa_control_vol = {
6869 .get = volume_alsa_vol_get, 6869 .get = volume_alsa_vol_get,
6870}; 6870};
6871 6871
6872static struct snd_kcontrol_new volume_alsa_control_mute = { 6872static struct snd_kcontrol_new volume_alsa_control_mute __initdata = {
6873 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 6873 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6874 .name = "Console Playback Switch", 6874 .name = "Console Playback Switch",
6875 .index = 0, 6875 .index = 0,
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 76441dcbe5ff..e4da61bcbf8b 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -222,6 +222,12 @@ static const struct dmi_system_id toshiba_alt_keymap_dmi[] = {
222 DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"), 222 DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M840"),
223 }, 223 },
224 }, 224 },
225 {
226 .matches = {
227 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
228 DMI_MATCH(DMI_PRODUCT_NAME, "Qosmio X75-A"),
229 },
230 },
225 {} 231 {}
226}; 232};
227 233
@@ -229,6 +235,7 @@ static const struct key_entry toshiba_acpi_alt_keymap[] = {
229 { KE_KEY, 0x157, { KEY_MUTE } }, 235 { KE_KEY, 0x157, { KEY_MUTE } },
230 { KE_KEY, 0x102, { KEY_ZOOMOUT } }, 236 { KE_KEY, 0x102, { KEY_ZOOMOUT } },
231 { KE_KEY, 0x103, { KEY_ZOOMIN } }, 237 { KE_KEY, 0x103, { KEY_ZOOMIN } },
238 { KE_KEY, 0x12c, { KEY_KBDILLUMTOGGLE } },
232 { KE_KEY, 0x139, { KEY_ZOOMRESET } }, 239 { KE_KEY, 0x139, { KEY_ZOOMRESET } },
233 { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } }, 240 { KE_KEY, 0x13e, { KEY_SWITCHVIDEOMODE } },
234 { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } }, 241 { KE_KEY, 0x13c, { KEY_BRIGHTNESSDOWN } },
@@ -872,7 +879,9 @@ static int lcd_proc_open(struct inode *inode, struct file *file)
872 879
873static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value) 880static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
874{ 881{
875 u32 hci_result; 882 u32 in[HCI_WORDS] = { HCI_SET, HCI_LCD_BRIGHTNESS, 0, 0, 0, 0 };
883 u32 out[HCI_WORDS];
884 acpi_status status;
876 885
877 if (dev->tr_backlight_supported) { 886 if (dev->tr_backlight_supported) {
878 bool enable = !value; 887 bool enable = !value;
@@ -883,9 +892,20 @@ static int set_lcd_brightness(struct toshiba_acpi_dev *dev, int value)
883 value--; 892 value--;
884 } 893 }
885 894
886 value = value << HCI_LCD_BRIGHTNESS_SHIFT; 895 in[2] = value << HCI_LCD_BRIGHTNESS_SHIFT;
887 hci_write1(dev, HCI_LCD_BRIGHTNESS, value, &hci_result); 896 status = hci_raw(dev, in, out);
888 return hci_result == HCI_SUCCESS ? 0 : -EIO; 897 if (ACPI_FAILURE(status) || out[0] == HCI_FAILURE) {
898 pr_err("ACPI call to set brightness failed");
899 return -EIO;
900 }
901 /* Extra check for "incomplete" backlight method, where the AML code
902 * doesn't check for HCI_SET or HCI_GET and returns HCI_SUCCESS,
903 * the actual brightness, and in some cases the max brightness.
904 */
905 if (out[2] > 0 || out[3] == 0xE000)
906 return -ENODEV;
907
908 return out[0] == HCI_SUCCESS ? 0 : -EIO;
889} 909}
890 910
891static int set_lcd_status(struct backlight_device *bd) 911static int set_lcd_status(struct backlight_device *bd)
@@ -1238,7 +1258,7 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
1238 int mode = -1; 1258 int mode = -1;
1239 int time = -1; 1259 int time = -1;
1240 1260
1241 if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1)) 1261 if (sscanf(buf, "%i", &mode) != 1 || (mode != 2 || mode != 1))
1242 return -EINVAL; 1262 return -EINVAL;
1243 1263
1244 /* Set the Keyboard Backlight Mode where: 1264 /* Set the Keyboard Backlight Mode where:
diff --git a/drivers/platform/x86/toshiba_haps.c b/drivers/platform/x86/toshiba_haps.c
new file mode 100644
index 000000000000..65300b6a84b9
--- /dev/null
+++ b/drivers/platform/x86/toshiba_haps.c
@@ -0,0 +1,265 @@
1/*
2 * Toshiba HDD Active Protection Sensor (HAPS) driver
3 *
4 * Copyright (C) 2014 Azael Avalos <coproscefalo@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/types.h>
24#include <linux/acpi.h>
25
26MODULE_AUTHOR("Azael Avalos <coproscefalo@gmail.com>");
27MODULE_DESCRIPTION("Toshiba HDD Active Protection Sensor");
28MODULE_LICENSE("GPL");
29
30struct toshiba_haps_dev {
31 struct acpi_device *acpi_dev;
32
33 int protection_level;
34};
35
36static struct toshiba_haps_dev *toshiba_haps;
37
38/* HAPS functions */
39static int toshiba_haps_reset_protection(acpi_handle handle)
40{
41 acpi_status status;
42
43 status = acpi_evaluate_object(handle, "RSSS", NULL, NULL);
44 if (ACPI_FAILURE(status)) {
45 pr_err("Unable to reset the HDD protection\n");
46 return -EIO;
47 }
48
49 return 0;
50}
51
52static int toshiba_haps_protection_level(acpi_handle handle, int level)
53{
54 acpi_status status;
55
56 status = acpi_execute_simple_method(handle, "PTLV", level);
57 if (ACPI_FAILURE(status)) {
58 pr_err("Error while setting the protection level\n");
59 return -EIO;
60 }
61
62 pr_info("HDD protection level set to: %d\n", level);
63
64 return 0;
65}
66
67/* sysfs files */
68static ssize_t protection_level_show(struct device *dev,
69 struct device_attribute *attr, char *buf)
70{
71 struct toshiba_haps_dev *haps = dev_get_drvdata(dev);
72
73 return sprintf(buf, "%i\n", haps->protection_level);
74}
75
76static ssize_t protection_level_store(struct device *dev,
77 struct device_attribute *attr,
78 const char *buf, size_t count)
79{
80 struct toshiba_haps_dev *haps = dev_get_drvdata(dev);
81 int level, ret;
82
83 if (sscanf(buf, "%d", &level) != 1 || level < 0 || level > 3)
84 return -EINVAL;
85
86 /* Set the sensor level.
87 * Acceptable levels are:
88 * 0 - Disabled | 1 - Low | 2 - Medium | 3 - High
89 */
90 ret = toshiba_haps_protection_level(haps->acpi_dev->handle, level);
91 if (ret != 0)
92 return ret;
93
94 haps->protection_level = level;
95
96 return count;
97}
98
99static ssize_t reset_protection_store(struct device *dev,
100 struct device_attribute *attr,
101 const char *buf, size_t count)
102{
103 struct toshiba_haps_dev *haps = dev_get_drvdata(dev);
104 int reset, ret;
105
106 if (sscanf(buf, "%d", &reset) != 1 || reset != 1)
107 return -EINVAL;
108
109 /* Reset the protection interface */
110 ret = toshiba_haps_reset_protection(haps->acpi_dev->handle);
111 if (ret != 0)
112 return ret;
113
114 return count;
115}
116
117static DEVICE_ATTR(protection_level, S_IRUGO | S_IWUSR,
118 protection_level_show, protection_level_store);
119static DEVICE_ATTR(reset_protection, S_IWUSR, NULL, reset_protection_store);
120
121static struct attribute *haps_attributes[] = {
122 &dev_attr_protection_level.attr,
123 &dev_attr_reset_protection.attr,
124 NULL,
125};
126
127static struct attribute_group haps_attr_group = {
128 .attrs = haps_attributes,
129};
130
131/*
132 * ACPI stuff
133 */
134static void toshiba_haps_notify(struct acpi_device *device, u32 event)
135{
136 pr_info("Received event: 0x%x", event);
137
138 acpi_bus_generate_netlink_event(device->pnp.device_class,
139 dev_name(&device->dev),
140 event, 0);
141}
142
143static int toshiba_haps_remove(struct acpi_device *device)
144{
145 sysfs_remove_group(&device->dev.kobj, &haps_attr_group);
146
147 if (toshiba_haps)
148 toshiba_haps = NULL;
149
150 return 0;
151}
152
153/* Helper function */
154static int toshiba_haps_available(acpi_handle handle)
155{
156 acpi_status status;
157 u64 hdd_present;
158
159 /*
160 * A non existent device as well as having (only)
161 * Solid State Drives can cause the call to fail.
162 */
163 status = acpi_evaluate_integer(handle, "_STA", NULL,
164 &hdd_present);
165 if (ACPI_FAILURE(status) || !hdd_present) {
166 pr_info("HDD protection not available or using SSD\n");
167 return 0;
168 }
169
170 return 1;
171}
172
173static int toshiba_haps_add(struct acpi_device *acpi_dev)
174{
175 struct toshiba_haps_dev *haps;
176 int ret;
177
178 if (toshiba_haps)
179 return -EBUSY;
180
181 if (!toshiba_haps_available(acpi_dev->handle))
182 return -ENODEV;
183
184 pr_info("Toshiba HDD Active Protection Sensor device\n");
185
186 haps = kzalloc(sizeof(struct toshiba_haps_dev), GFP_KERNEL);
187 if (!haps)
188 return -ENOMEM;
189
190 haps->acpi_dev = acpi_dev;
191 haps->protection_level = 2;
192 acpi_dev->driver_data = haps;
193 dev_set_drvdata(&acpi_dev->dev, haps);
194
195 /* Set the protection level, currently at level 2 (Medium) */
196 ret = toshiba_haps_protection_level(acpi_dev->handle, 2);
197 if (ret != 0)
198 return ret;
199
200 ret = sysfs_create_group(&acpi_dev->dev.kobj, &haps_attr_group);
201 if (ret)
202 return ret;
203
204 toshiba_haps = haps;
205
206 return 0;
207}
208
209#ifdef CONFIG_PM_SLEEP
210static int toshiba_haps_suspend(struct device *device)
211{
212 struct toshiba_haps_dev *haps;
213 int ret;
214
215 haps = acpi_driver_data(to_acpi_device(device));
216
217 /* Deactivate the protection on suspend */
218 ret = toshiba_haps_protection_level(haps->acpi_dev->handle, 0);
219
220 return ret;
221}
222
223static int toshiba_haps_resume(struct device *device)
224{
225 struct toshiba_haps_dev *haps;
226 int ret;
227
228 haps = acpi_driver_data(to_acpi_device(device));
229
230 /* Set the stored protection level */
231 ret = toshiba_haps_protection_level(haps->acpi_dev->handle,
232 haps->protection_level);
233
234 /* Reset the protection on resume */
235 ret = toshiba_haps_reset_protection(haps->acpi_dev->handle);
236 if (ret != 0)
237 return ret;
238
239 return ret;
240}
241#endif
242
243static SIMPLE_DEV_PM_OPS(toshiba_haps_pm,
244 toshiba_haps_suspend, toshiba_haps_resume);
245
246static const struct acpi_device_id haps_device_ids[] = {
247 {"TOS620A", 0},
248 {"", 0},
249};
250MODULE_DEVICE_TABLE(acpi, haps_device_ids);
251
252static struct acpi_driver toshiba_haps_driver = {
253 .name = "Toshiba HAPS",
254 .owner = THIS_MODULE,
255 .ids = haps_device_ids,
256 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
257 .ops = {
258 .add = toshiba_haps_add,
259 .remove = toshiba_haps_remove,
260 .notify = toshiba_haps_notify,
261 },
262 .drv.pm = &toshiba_haps_pm,
263};
264
265module_acpi_driver(toshiba_haps_driver);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 43d13295e63d..737e56d46f61 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -256,10 +256,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
256 block = &wblock->gblock; 256 block = &wblock->gblock;
257 handle = wblock->handle; 257 handle = wblock->handle;
258 258
259 if (!block)
260 return AE_NOT_EXIST;
261
262
263 snprintf(method, 5, "WE%02X", block->notify_id); 259 snprintf(method, 5, "WE%02X", block->notify_id);
264 status = acpi_execute_simple_method(handle, method, enable); 260 status = acpi_execute_simple_method(handle, method, enable);
265 261