aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-03-23 20:20:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-23 20:20:59 -0400
commit5a010c73cdb760c9bdf37b28824b6566789cc005 (patch)
treea12508a6d3b20807eaa822bedd95973df47d6307 /drivers/platform
parentb615d3d406ead1157c6b846c417b71a3b6600776 (diff)
parentfffcad87d4e7c5f6f6f6e5fc9d337bd6f197f80f (diff)
Merge tag 'platform-drivers-x86-v4.6-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86
Pull x86 platform driver updates from Darren Hart: "Significant refactoring of Dell laptop drivers, modularizing the smbios code. Multiple new platforms added for ideapad, asus, dell, and alienware using existing quirks. A few fixes and cleanups. hp-wmi: - Remove GPS rfkill support via pre-2009 interface - fix unregister order in hp_wmi_rfkill_setup() once again ideapad-laptop: - Add ideapad Y700 (15) to the no_hw_rfkill DMI list fujitsu-laptop: - Support radio toggle button intel-hid: - allocate correct amount of memory for private struct platform/x86: - Make intel_scu_ipc explicitly non-modular intel_pmc_ipc: - Avoid pending IPC1 command during legacy suspend - Fix GCR register base address and length asus-nb-wmi: - add wapf=4 quirk for ASUS X75VD intel_telemetry_pltdrv: - Change verbosity control bits dell-rbtn: - Add a comment about the XPS 13 9350 dell-wmi, dell-laptop: - depends DMI dell-wmi: - support Dell Inspiron M5110 - properly process Dell Instant Launch hotkey - enable receiving WMI events on Dell Vostro V131 - Support new hotkeys on the XPS 13 9350 (Skylake) - Clean up hotkey table size check - Stop storing pointers to DMI tables dell-laptop: - move dell_smi_error() to dell-smbios - use dell_smbios_find_token() instead of find_token_location() - use dell_smbios_find_token() instead of find_token_id() - extract SMBIOS-related code to a separate module dell-smbios: - rename dell_smi_error() to dell_smbios_error() - make da_tokens static - remove find_token_{id,location}() - implement new function for finding DMI table 0xDA tokens - make the SMBIOS buffer static - return the SMBIOS buffer from dell_smbios_get_buffer() - don't return an SMBIOS buffer from dell_smbios_send_request() - don't pass an SMBIOS buffer to dell_smbios_send_request() - rename dell_send_request() to dell_smbios_send_request() - rename release_buffer() to dell_smbios_release_buffer() - rename clear_buffer() to dell_smbios_clear_buffer() - rename get_buffer() to dell_smbios_get_buffer() dell-led: - use dell_smbios_send_request() for performing SMBIOS calls - use dell_smbios_find_token() for finding mic DMI tokens toshiba_acpi: - Add a module parameter to disable hotkeys registration - Add sysfs entries for the Cooling Method feature - Add support for cooling method feature Documentation/ABI: - Update sysfs-driver-toshiba_acpi file thinkpad_acpi: - Remove ambiguous logging for "Unsupported brightness interface" alienware-wmi: - whitespace improvements - Add support for two new systems: ASM200 and ASM201. - Add support for deep sleep control. - Add initial support for alienware graphics amplifier. - Add support for new platform: X51-R3 - Clean up whitespace for ASM100 platform" * tag 'platform-drivers-x86-v4.6-1' of git://git.infradead.org/users/dvhart/linux-platform-drivers-x86: (47 commits) hp-wmi: Remove GPS rfkill support via pre-2009 interface hp-wmi: fix unregister order in hp_wmi_rfkill_setup() once again dell-wmi: support Dell Inspiron M5110 dell-wmi: properly process Dell Instant Launch hotkey dell-wmi: enable receiving WMI events on Dell Vostro V131 dell-smbios: rename dell_smi_error() to dell_smbios_error() dell-laptop: move dell_smi_error() to dell-smbios ideapad-laptop: Add ideapad Y700 (15) to the no_hw_rfkill DMI list fujitsu-laptop: Support radio toggle button intel-hid: allocate correct amount of memory for private struct platform/x86: Make intel_scu_ipc explicitly non-modular intel_pmc_ipc: Avoid pending IPC1 command during legacy suspend intel_pmc_ipc: Fix GCR register base address and length asus-nb-wmi: add wapf=4 quirk for ASUS X75VD intel_telemetry_pltdrv: Change verbosity control bits dell-rbtn: Add a comment about the XPS 13 9350 dell-wmi: Support new hotkeys on the XPS 13 9350 (Skylake) dell-wmi: Clean up hotkey table size check dell-wmi, dell-laptop: depends DMI dell-wmi: Stop storing pointers to DMI tables ...
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig15
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/alienware-wmi.c286
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c9
-rw-r--r--drivers/platform/x86/dell-laptop.c370
-rw-r--r--drivers/platform/x86/dell-rbtn.c15
-rw-r--r--drivers/platform/x86/dell-smbios.c193
-rw-r--r--drivers/platform/x86/dell-smbios.h46
-rw-r--r--drivers/platform/x86/dell-wmi.c238
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c8
-rw-r--r--drivers/platform/x86/hp-wmi.c46
-rw-r--r--drivers/platform/x86/ideapad-laptop.c14
-rw-r--r--drivers/platform/x86/intel-hid.c3
-rw-r--r--drivers/platform/x86/intel_pmc_ipc.c8
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c35
-rw-r--r--drivers/platform/x86/intel_telemetry_pltdrv.c13
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c4
-rw-r--r--drivers/platform/x86/toshiba_acpi.c115
18 files changed, 995 insertions, 424 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 69f93a576e45..ed2004be13cf 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -91,10 +91,21 @@ config ASUS_LAPTOP
91 91
92 If you have an ACPI-compatible ASUS laptop, say Y or M here. 92 If you have an ACPI-compatible ASUS laptop, say Y or M here.
93 93
94config DELL_SMBIOS
95 tristate "Dell SMBIOS Support"
96 depends on DCDBAS
97 default n
98 ---help---
99 This module provides common functions for kernel modules using
100 Dell SMBIOS.
101
102 If you have a Dell laptop, say Y or M here.
103
94config DELL_LAPTOP 104config DELL_LAPTOP
95 tristate "Dell Laptop Extras" 105 tristate "Dell Laptop Extras"
96 depends on X86 106 depends on X86
97 depends on DCDBAS 107 depends on DELL_SMBIOS
108 depends on DMI
98 depends on BACKLIGHT_CLASS_DEVICE 109 depends on BACKLIGHT_CLASS_DEVICE
99 depends on ACPI_VIDEO || ACPI_VIDEO = n 110 depends on ACPI_VIDEO || ACPI_VIDEO = n
100 depends on RFKILL || RFKILL = n 111 depends on RFKILL || RFKILL = n
@@ -110,8 +121,10 @@ config DELL_LAPTOP
110config DELL_WMI 121config DELL_WMI
111 tristate "Dell WMI extras" 122 tristate "Dell WMI extras"
112 depends on ACPI_WMI 123 depends on ACPI_WMI
124 depends on DMI
113 depends on INPUT 125 depends on INPUT
114 depends on ACPI_VIDEO || ACPI_VIDEO = n 126 depends on ACPI_VIDEO || ACPI_VIDEO = n
127 depends on DELL_SMBIOS
115 select INPUT_SPARSEKMAP 128 select INPUT_SPARSEKMAP
116 ---help--- 129 ---help---
117 Say Y here if you want to support WMI-based hotkeys on Dell laptops. 130 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 40574e7390f3..448443c3baba 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_EEEPC_WMI) += eeepc-wmi.o
11obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o 11obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o
12obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o 12obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o
13obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o 13obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
14obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
14obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o 15obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
15obj-$(CONFIG_DELL_WMI) += dell-wmi.o 16obj-$(CONFIG_DELL_WMI) += dell-wmi.o
16obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o 17obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c
index 1e1e59423889..005629447b0c 100644
--- a/drivers/platform/x86/alienware-wmi.c
+++ b/drivers/platform/x86/alienware-wmi.c
@@ -33,6 +33,9 @@
33#define WMAX_METHOD_BRIGHTNESS 0x3 33#define WMAX_METHOD_BRIGHTNESS 0x3
34#define WMAX_METHOD_ZONE_CONTROL 0x4 34#define WMAX_METHOD_ZONE_CONTROL 0x4
35#define WMAX_METHOD_HDMI_CABLE 0x5 35#define WMAX_METHOD_HDMI_CABLE 0x5
36#define WMAX_METHOD_AMPLIFIER_CABLE 0x6
37#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B
38#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C
36 39
37MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>"); 40MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>");
38MODULE_DESCRIPTION("Alienware special feature control"); 41MODULE_DESCRIPTION("Alienware special feature control");
@@ -60,6 +63,8 @@ enum WMAX_CONTROL_STATES {
60struct quirk_entry { 63struct quirk_entry {
61 u8 num_zones; 64 u8 num_zones;
62 u8 hdmi_mux; 65 u8 hdmi_mux;
66 u8 amplifier;
67 u8 deepslp;
63}; 68};
64 69
65static struct quirk_entry *quirks; 70static struct quirk_entry *quirks;
@@ -67,16 +72,43 @@ static struct quirk_entry *quirks;
67static struct quirk_entry quirk_unknown = { 72static struct quirk_entry quirk_unknown = {
68 .num_zones = 2, 73 .num_zones = 2,
69 .hdmi_mux = 0, 74 .hdmi_mux = 0,
75 .amplifier = 0,
76 .deepslp = 0,
70}; 77};
71 78
72static struct quirk_entry quirk_x51_family = { 79static struct quirk_entry quirk_x51_r1_r2 = {
73 .num_zones = 3, 80 .num_zones = 3,
74 .hdmi_mux = 0. 81 .hdmi_mux = 0,
82 .amplifier = 0,
83 .deepslp = 0,
84};
85
86static struct quirk_entry quirk_x51_r3 = {
87 .num_zones = 4,
88 .hdmi_mux = 0,
89 .amplifier = 1,
90 .deepslp = 0,
75}; 91};
76 92
77static struct quirk_entry quirk_asm100 = { 93static struct quirk_entry quirk_asm100 = {
78 .num_zones = 2, 94 .num_zones = 2,
79 .hdmi_mux = 1, 95 .hdmi_mux = 1,
96 .amplifier = 0,
97 .deepslp = 0,
98};
99
100static struct quirk_entry quirk_asm200 = {
101 .num_zones = 2,
102 .hdmi_mux = 1,
103 .amplifier = 0,
104 .deepslp = 1,
105};
106
107static struct quirk_entry quirk_asm201 = {
108 .num_zones = 2,
109 .hdmi_mux = 1,
110 .amplifier = 1,
111 .deepslp = 1,
80}; 112};
81 113
82static int __init dmi_matched(const struct dmi_system_id *dmi) 114static int __init dmi_matched(const struct dmi_system_id *dmi)
@@ -88,12 +120,12 @@ static int __init dmi_matched(const struct dmi_system_id *dmi)
88static const struct dmi_system_id alienware_quirks[] __initconst = { 120static const struct dmi_system_id alienware_quirks[] __initconst = {
89 { 121 {
90 .callback = dmi_matched, 122 .callback = dmi_matched,
91 .ident = "Alienware X51 R1", 123 .ident = "Alienware X51 R3",
92 .matches = { 124 .matches = {
93 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 125 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
94 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), 126 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"),
95 }, 127 },
96 .driver_data = &quirk_x51_family, 128 .driver_data = &quirk_x51_r3,
97 }, 129 },
98 { 130 {
99 .callback = dmi_matched, 131 .callback = dmi_matched,
@@ -102,17 +134,44 @@ static const struct dmi_system_id alienware_quirks[] __initconst = {
102 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 134 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
103 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), 135 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"),
104 }, 136 },
105 .driver_data = &quirk_x51_family, 137 .driver_data = &quirk_x51_r1_r2,
138 },
139 {
140 .callback = dmi_matched,
141 .ident = "Alienware X51 R1",
142 .matches = {
143 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
144 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"),
145 },
146 .driver_data = &quirk_x51_r1_r2,
147 },
148 {
149 .callback = dmi_matched,
150 .ident = "Alienware ASM100",
151 .matches = {
152 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
153 DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"),
154 },
155 .driver_data = &quirk_asm100,
156 },
157 {
158 .callback = dmi_matched,
159 .ident = "Alienware ASM200",
160 .matches = {
161 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
162 DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"),
163 },
164 .driver_data = &quirk_asm200,
106 }, 165 },
107 { 166 {
108 .callback = dmi_matched, 167 .callback = dmi_matched,
109 .ident = "Alienware ASM100", 168 .ident = "Alienware ASM201",
110 .matches = { 169 .matches = {
111 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 170 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
112 DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), 171 DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"),
113 }, 172 },
114 .driver_data = &quirk_asm100, 173 .driver_data = &quirk_asm201,
115 }, 174 },
116 {} 175 {}
117}; 176};
118 177
@@ -133,7 +192,7 @@ struct wmax_brightness_args {
133 u32 percentage; 192 u32 percentage;
134}; 193};
135 194
136struct hdmi_args { 195struct wmax_basic_args {
137 u8 arg; 196 u8 arg;
138}; 197};
139 198
@@ -170,7 +229,7 @@ static u8 global_brightness;
170 229
171/* 230/*
172 * Helpers used for zone control 231 * Helpers used for zone control
173*/ 232 */
174static int parse_rgb(const char *buf, struct platform_zone *zone) 233static int parse_rgb(const char *buf, struct platform_zone *zone)
175{ 234{
176 long unsigned int rgb; 235 long unsigned int rgb;
@@ -210,7 +269,7 @@ static struct platform_zone *match_zone(struct device_attribute *attr)
210 269
211/* 270/*
212 * Individual RGB zone control 271 * Individual RGB zone control
213*/ 272 */
214static int alienware_update_led(struct platform_zone *zone) 273static int alienware_update_led(struct platform_zone *zone)
215{ 274{
216 int method_id; 275 int method_id;
@@ -218,16 +277,16 @@ static int alienware_update_led(struct platform_zone *zone)
218 char *guid; 277 char *guid;
219 struct acpi_buffer input; 278 struct acpi_buffer input;
220 struct legacy_led_args legacy_args; 279 struct legacy_led_args legacy_args;
221 struct wmax_led_args wmax_args; 280 struct wmax_led_args wmax_basic_args;
222 if (interface == WMAX) { 281 if (interface == WMAX) {
223 wmax_args.led_mask = 1 << zone->location; 282 wmax_basic_args.led_mask = 1 << zone->location;
224 wmax_args.colors = zone->colors; 283 wmax_basic_args.colors = zone->colors;
225 wmax_args.state = lighting_control_state; 284 wmax_basic_args.state = lighting_control_state;
226 guid = WMAX_CONTROL_GUID; 285 guid = WMAX_CONTROL_GUID;
227 method_id = WMAX_METHOD_ZONE_CONTROL; 286 method_id = WMAX_METHOD_ZONE_CONTROL;
228 287
229 input.length = (acpi_size) sizeof(wmax_args); 288 input.length = (acpi_size) sizeof(wmax_basic_args);
230 input.pointer = &wmax_args; 289 input.pointer = &wmax_basic_args;
231 } else { 290 } else {
232 legacy_args.colors = zone->colors; 291 legacy_args.colors = zone->colors;
233 legacy_args.brightness = global_brightness; 292 legacy_args.brightness = global_brightness;
@@ -283,7 +342,7 @@ static ssize_t zone_set(struct device *dev, struct device_attribute *attr,
283 342
284/* 343/*
285 * LED Brightness (Global) 344 * LED Brightness (Global)
286*/ 345 */
287static int wmax_brightness(int brightness) 346static int wmax_brightness(int brightness)
288{ 347{
289 acpi_status status; 348 acpi_status status;
@@ -327,7 +386,7 @@ static struct led_classdev global_led = {
327 386
328/* 387/*
329 * Lighting control state device attribute (Global) 388 * Lighting control state device attribute (Global)
330*/ 389 */
331static ssize_t show_control_state(struct device *dev, 390static ssize_t show_control_state(struct device *dev,
332 struct device_attribute *attr, char *buf) 391 struct device_attribute *attr, char *buf)
333{ 392{
@@ -435,11 +494,7 @@ static void alienware_zone_exit(struct platform_device *dev)
435 kfree(zone_attrs); 494 kfree(zone_attrs);
436} 495}
437 496
438/* 497static acpi_status alienware_wmax_command(struct wmax_basic_args *in_args,
439 The HDMI mux sysfs node indicates the status of the HDMI input mux.
440 It can toggle between standard system GPU output and HDMI input.
441*/
442static acpi_status alienware_hdmi_command(struct hdmi_args *in_args,
443 u32 command, int *out_data) 498 u32 command, int *out_data)
444{ 499{
445 acpi_status status; 500 acpi_status status;
@@ -467,16 +522,20 @@ static acpi_status alienware_hdmi_command(struct hdmi_args *in_args,
467 522
468} 523}
469 524
525/*
526 * The HDMI mux sysfs node indicates the status of the HDMI input mux.
527 * It can toggle between standard system GPU output and HDMI input.
528 */
470static ssize_t show_hdmi_cable(struct device *dev, 529static ssize_t show_hdmi_cable(struct device *dev,
471 struct device_attribute *attr, char *buf) 530 struct device_attribute *attr, char *buf)
472{ 531{
473 acpi_status status; 532 acpi_status status;
474 u32 out_data; 533 u32 out_data;
475 struct hdmi_args in_args = { 534 struct wmax_basic_args in_args = {
476 .arg = 0, 535 .arg = 0,
477 }; 536 };
478 status = 537 status =
479 alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_CABLE, 538 alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_CABLE,
480 (u32 *) &out_data); 539 (u32 *) &out_data);
481 if (ACPI_SUCCESS(status)) { 540 if (ACPI_SUCCESS(status)) {
482 if (out_data == 0) 541 if (out_data == 0)
@@ -495,11 +554,11 @@ static ssize_t show_hdmi_source(struct device *dev,
495{ 554{
496 acpi_status status; 555 acpi_status status;
497 u32 out_data; 556 u32 out_data;
498 struct hdmi_args in_args = { 557 struct wmax_basic_args in_args = {
499 .arg = 0, 558 .arg = 0,
500 }; 559 };
501 status = 560 status =
502 alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_STATUS, 561 alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_STATUS,
503 (u32 *) &out_data); 562 (u32 *) &out_data);
504 563
505 if (ACPI_SUCCESS(status)) { 564 if (ACPI_SUCCESS(status)) {
@@ -519,7 +578,7 @@ static ssize_t toggle_hdmi_source(struct device *dev,
519 const char *buf, size_t count) 578 const char *buf, size_t count)
520{ 579{
521 acpi_status status; 580 acpi_status status;
522 struct hdmi_args args; 581 struct wmax_basic_args args;
523 if (strcmp(buf, "gpu\n") == 0) 582 if (strcmp(buf, "gpu\n") == 0)
524 args.arg = 1; 583 args.arg = 1;
525 else if (strcmp(buf, "input\n") == 0) 584 else if (strcmp(buf, "input\n") == 0)
@@ -528,7 +587,7 @@ static ssize_t toggle_hdmi_source(struct device *dev,
528 args.arg = 3; 587 args.arg = 3;
529 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); 588 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
530 589
531 status = alienware_hdmi_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); 590 status = alienware_wmax_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL);
532 591
533 if (ACPI_FAILURE(status)) 592 if (ACPI_FAILURE(status))
534 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", 593 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n",
@@ -563,11 +622,144 @@ static int create_hdmi(struct platform_device *dev)
563 622
564 ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group); 623 ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group);
565 if (ret) 624 if (ret)
566 goto error_create_hdmi; 625 remove_hdmi(dev);
567 return 0; 626 return ret;
627}
568 628
569error_create_hdmi: 629/*
570 remove_hdmi(dev); 630 * Alienware GFX amplifier support
631 * - Currently supports reading cable status
632 * - Leaving expansion room to possibly support dock/undock events later
633 */
634static ssize_t show_amplifier_status(struct device *dev,
635 struct device_attribute *attr, char *buf)
636{
637 acpi_status status;
638 u32 out_data;
639 struct wmax_basic_args in_args = {
640 .arg = 0,
641 };
642 status =
643 alienware_wmax_command(&in_args, WMAX_METHOD_AMPLIFIER_CABLE,
644 (u32 *) &out_data);
645 if (ACPI_SUCCESS(status)) {
646 if (out_data == 0)
647 return scnprintf(buf, PAGE_SIZE,
648 "[unconnected] connected unknown\n");
649 else if (out_data == 1)
650 return scnprintf(buf, PAGE_SIZE,
651 "unconnected [connected] unknown\n");
652 }
653 pr_err("alienware-wmi: unknown amplifier cable status: %d\n", status);
654 return scnprintf(buf, PAGE_SIZE, "unconnected connected [unknown]\n");
655}
656
657static DEVICE_ATTR(status, S_IRUGO, show_amplifier_status, NULL);
658
659static struct attribute *amplifier_attrs[] = {
660 &dev_attr_status.attr,
661 NULL,
662};
663
664static struct attribute_group amplifier_attribute_group = {
665 .name = "amplifier",
666 .attrs = amplifier_attrs,
667};
668
669static void remove_amplifier(struct platform_device *dev)
670{
671 if (quirks->amplifier > 0)
672 sysfs_remove_group(&dev->dev.kobj, &amplifier_attribute_group);
673}
674
675static int create_amplifier(struct platform_device *dev)
676{
677 int ret;
678
679 ret = sysfs_create_group(&dev->dev.kobj, &amplifier_attribute_group);
680 if (ret)
681 remove_amplifier(dev);
682 return ret;
683}
684
685/*
686 * Deep Sleep Control support
687 * - Modifies BIOS setting for deep sleep control allowing extra wakeup events
688 */
689static ssize_t show_deepsleep_status(struct device *dev,
690 struct device_attribute *attr, char *buf)
691{
692 acpi_status status;
693 u32 out_data;
694 struct wmax_basic_args in_args = {
695 .arg = 0,
696 };
697 status = alienware_wmax_command(&in_args, WMAX_METHOD_DEEP_SLEEP_STATUS,
698 (u32 *) &out_data);
699 if (ACPI_SUCCESS(status)) {
700 if (out_data == 0)
701 return scnprintf(buf, PAGE_SIZE,
702 "[disabled] s5 s5_s4\n");
703 else if (out_data == 1)
704 return scnprintf(buf, PAGE_SIZE,
705 "disabled [s5] s5_s4\n");
706 else if (out_data == 2)
707 return scnprintf(buf, PAGE_SIZE,
708 "disabled s5 [s5_s4]\n");
709 }
710 pr_err("alienware-wmi: unknown deep sleep status: %d\n", status);
711 return scnprintf(buf, PAGE_SIZE, "disabled s5 s5_s4 [unknown]\n");
712}
713
714static ssize_t toggle_deepsleep(struct device *dev,
715 struct device_attribute *attr,
716 const char *buf, size_t count)
717{
718 acpi_status status;
719 struct wmax_basic_args args;
720
721 if (strcmp(buf, "disabled\n") == 0)
722 args.arg = 0;
723 else if (strcmp(buf, "s5\n") == 0)
724 args.arg = 1;
725 else
726 args.arg = 2;
727 pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
728
729 status = alienware_wmax_command(&args, WMAX_METHOD_DEEP_SLEEP_CONTROL,
730 NULL);
731
732 if (ACPI_FAILURE(status))
733 pr_err("alienware-wmi: deep sleep control failed: results: %u\n",
734 status);
735 return count;
736}
737
738static DEVICE_ATTR(deepsleep, S_IRUGO | S_IWUSR, show_deepsleep_status, toggle_deepsleep);
739
740static struct attribute *deepsleep_attrs[] = {
741 &dev_attr_deepsleep.attr,
742 NULL,
743};
744
745static struct attribute_group deepsleep_attribute_group = {
746 .name = "deepsleep",
747 .attrs = deepsleep_attrs,
748};
749
750static void remove_deepsleep(struct platform_device *dev)
751{
752 if (quirks->deepslp > 0)
753 sysfs_remove_group(&dev->dev.kobj, &deepsleep_attribute_group);
754}
755
756static int create_deepsleep(struct platform_device *dev)
757{
758 int ret;
759
760 ret = sysfs_create_group(&dev->dev.kobj, &deepsleep_attribute_group);
761 if (ret)
762 remove_deepsleep(dev);
571 return ret; 763 return ret;
572} 764}
573 765
@@ -606,6 +798,18 @@ static int __init alienware_wmi_init(void)
606 goto fail_prep_hdmi; 798 goto fail_prep_hdmi;
607 } 799 }
608 800
801 if (quirks->amplifier > 0) {
802 ret = create_amplifier(platform_device);
803 if (ret)
804 goto fail_prep_amplifier;
805 }
806
807 if (quirks->deepslp > 0) {
808 ret = create_deepsleep(platform_device);
809 if (ret)
810 goto fail_prep_deepsleep;
811 }
812
609 ret = alienware_zone_init(platform_device); 813 ret = alienware_zone_init(platform_device);
610 if (ret) 814 if (ret)
611 goto fail_prep_zones; 815 goto fail_prep_zones;
@@ -614,6 +818,8 @@ static int __init alienware_wmi_init(void)
614 818
615fail_prep_zones: 819fail_prep_zones:
616 alienware_zone_exit(platform_device); 820 alienware_zone_exit(platform_device);
821fail_prep_deepsleep:
822fail_prep_amplifier:
617fail_prep_hdmi: 823fail_prep_hdmi:
618 platform_device_del(platform_device); 824 platform_device_del(platform_device);
619fail_platform_device2: 825fail_platform_device2:
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 131fee2b093e..091ca7ada8fc 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -272,6 +272,15 @@ static const struct dmi_system_id asus_quirks[] = {
272 }, 272 },
273 { 273 {
274 .callback = dmi_matched, 274 .callback = dmi_matched,
275 .ident = "ASUSTeK COMPUTER INC. X75VD",
276 .matches = {
277 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
278 DMI_MATCH(DMI_PRODUCT_NAME, "X75VD"),
279 },
280 .driver_data = &quirk_asus_wapf4,
281 },
282 {
283 .callback = dmi_matched,
275 .ident = "ASUSTeK COMPUTER INC. 1015E", 284 .ident = "ASUSTeK COMPUTER INC. 1015E",
276 .matches = { 285 .matches = {
277 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 286 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index aaeeae81e3a9..2c2f02b2e08a 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -28,12 +28,11 @@
28#include <linux/acpi.h> 28#include <linux/acpi.h>
29#include <linux/mm.h> 29#include <linux/mm.h>
30#include <linux/i8042.h> 30#include <linux/i8042.h>
31#include <linux/slab.h>
32#include <linux/debugfs.h> 31#include <linux/debugfs.h>
33#include <linux/seq_file.h> 32#include <linux/seq_file.h>
34#include <acpi/video.h> 33#include <acpi/video.h>
35#include "../../firmware/dcdbas.h"
36#include "dell-rbtn.h" 34#include "dell-rbtn.h"
35#include "dell-smbios.h"
37 36
38#define BRIGHTNESS_TOKEN 0x7d 37#define BRIGHTNESS_TOKEN 0x7d
39#define KBD_LED_OFF_TOKEN 0x01E1 38#define KBD_LED_OFF_TOKEN 0x01E1
@@ -44,33 +43,6 @@
44#define KBD_LED_AUTO_75_TOKEN 0x02EC 43#define KBD_LED_AUTO_75_TOKEN 0x02EC
45#define KBD_LED_AUTO_100_TOKEN 0x02F6 44#define KBD_LED_AUTO_100_TOKEN 0x02F6
46 45
47/* This structure will be modified by the firmware when we enter
48 * system management mode, hence the volatiles */
49
50struct calling_interface_buffer {
51 u16 class;
52 u16 select;
53 volatile u32 input[4];
54 volatile u32 output[4];
55} __packed;
56
57struct calling_interface_token {
58 u16 tokenID;
59 u16 location;
60 union {
61 u16 value;
62 u16 stringlength;
63 };
64};
65
66struct calling_interface_structure {
67 struct dmi_header header;
68 u16 cmdIOAddress;
69 u8 cmdIOCode;
70 u32 supportedCmds;
71 struct calling_interface_token tokens[];
72} __packed;
73
74struct quirk_entry { 46struct quirk_entry {
75 u8 touchpad_led; 47 u8 touchpad_led;
76 48
@@ -103,11 +75,6 @@ static struct quirk_entry quirk_dell_xps13_9333 = {
103 .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 }, 75 .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 },
104}; 76};
105 77
106static int da_command_address;
107static int da_command_code;
108static int da_num_tokens;
109static struct calling_interface_token *da_tokens;
110
111static struct platform_driver platform_driver = { 78static struct platform_driver platform_driver = {
112 .driver = { 79 .driver = {
113 .name = "dell-laptop", 80 .name = "dell-laptop",
@@ -306,126 +273,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
306 { } 273 { }
307}; 274};
308 275
309static struct calling_interface_buffer *buffer;
310static DEFINE_MUTEX(buffer_mutex);
311
312static void clear_buffer(void)
313{
314 memset(buffer, 0, sizeof(struct calling_interface_buffer));
315}
316
317static void get_buffer(void)
318{
319 mutex_lock(&buffer_mutex);
320 clear_buffer();
321}
322
323static void release_buffer(void)
324{
325 mutex_unlock(&buffer_mutex);
326}
327
328static void __init parse_da_table(const struct dmi_header *dm)
329{
330 /* Final token is a terminator, so we don't want to copy it */
331 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
332 struct calling_interface_token *new_da_tokens;
333 struct calling_interface_structure *table =
334 container_of(dm, struct calling_interface_structure, header);
335
336 /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least
337 6 bytes of entry */
338
339 if (dm->length < 17)
340 return;
341
342 da_command_address = table->cmdIOAddress;
343 da_command_code = table->cmdIOCode;
344
345 new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
346 sizeof(struct calling_interface_token),
347 GFP_KERNEL);
348
349 if (!new_da_tokens)
350 return;
351 da_tokens = new_da_tokens;
352
353 memcpy(da_tokens+da_num_tokens, table->tokens,
354 sizeof(struct calling_interface_token) * tokens);
355
356 da_num_tokens += tokens;
357}
358
359static void __init find_tokens(const struct dmi_header *dm, void *dummy)
360{
361 switch (dm->type) {
362 case 0xd4: /* Indexed IO */
363 case 0xd5: /* Protected Area Type 1 */
364 case 0xd6: /* Protected Area Type 2 */
365 break;
366 case 0xda: /* Calling interface */
367 parse_da_table(dm);
368 break;
369 }
370}
371
372static int find_token_id(int tokenid)
373{
374 int i;
375
376 for (i = 0; i < da_num_tokens; i++) {
377 if (da_tokens[i].tokenID == tokenid)
378 return i;
379 }
380
381 return -1;
382}
383
384static int find_token_location(int tokenid)
385{
386 int id;
387
388 id = find_token_id(tokenid);
389 if (id == -1)
390 return -1;
391
392 return da_tokens[id].location;
393}
394
395static struct calling_interface_buffer *
396dell_send_request(struct calling_interface_buffer *buffer, int class,
397 int select)
398{
399 struct smi_cmd command;
400
401 command.magic = SMI_CMD_MAGIC;
402 command.command_address = da_command_address;
403 command.command_code = da_command_code;
404 command.ebx = virt_to_phys(buffer);
405 command.ecx = 0x42534931;
406
407 buffer->class = class;
408 buffer->select = select;
409
410 dcdbas_smi_request(&command);
411
412 return buffer;
413}
414
415static inline int dell_smi_error(int value)
416{
417 switch (value) {
418 case 0: /* Completed successfully */
419 return 0;
420 case -1: /* Completed with error */
421 return -EIO;
422 case -2: /* Function not supported */
423 return -ENXIO;
424 default: /* Unknown error */
425 return -EINVAL;
426 }
427}
428
429/* 276/*
430 * Derived from information in smbios-wireless-ctl: 277 * Derived from information in smbios-wireless-ctl:
431 * 278 *
@@ -548,6 +395,7 @@ static inline int dell_smi_error(int value)
548 395
549static int dell_rfkill_set(void *data, bool blocked) 396static int dell_rfkill_set(void *data, bool blocked)
550{ 397{
398 struct calling_interface_buffer *buffer;
551 int disable = blocked ? 1 : 0; 399 int disable = blocked ? 1 : 0;
552 unsigned long radio = (unsigned long)data; 400 unsigned long radio = (unsigned long)data;
553 int hwswitch_bit = (unsigned long)data - 1; 401 int hwswitch_bit = (unsigned long)data - 1;
@@ -555,19 +403,19 @@ static int dell_rfkill_set(void *data, bool blocked)
555 int status; 403 int status;
556 int ret; 404 int ret;
557 405
558 get_buffer(); 406 buffer = dell_smbios_get_buffer();
559 407
560 dell_send_request(buffer, 17, 11); 408 dell_smbios_send_request(17, 11);
561 ret = buffer->output[0]; 409 ret = buffer->output[0];
562 status = buffer->output[1]; 410 status = buffer->output[1];
563 411
564 if (ret != 0) 412 if (ret != 0)
565 goto out; 413 goto out;
566 414
567 clear_buffer(); 415 dell_smbios_clear_buffer();
568 416
569 buffer->input[0] = 0x2; 417 buffer->input[0] = 0x2;
570 dell_send_request(buffer, 17, 11); 418 dell_smbios_send_request(17, 11);
571 ret = buffer->output[0]; 419 ret = buffer->output[0];
572 hwswitch = buffer->output[1]; 420 hwswitch = buffer->output[1];
573 421
@@ -577,27 +425,28 @@ static int dell_rfkill_set(void *data, bool blocked)
577 (status & BIT(0)) && !(status & BIT(16))) 425 (status & BIT(0)) && !(status & BIT(16)))
578 disable = 1; 426 disable = 1;
579 427
580 clear_buffer(); 428 dell_smbios_clear_buffer();
581 429
582 buffer->input[0] = (1 | (radio<<8) | (disable << 16)); 430 buffer->input[0] = (1 | (radio<<8) | (disable << 16));
583 dell_send_request(buffer, 17, 11); 431 dell_smbios_send_request(17, 11);
584 ret = buffer->output[0]; 432 ret = buffer->output[0];
585 433
586 out: 434 out:
587 release_buffer(); 435 dell_smbios_release_buffer();
588 return dell_smi_error(ret); 436 return dell_smbios_error(ret);
589} 437}
590 438
591/* Must be called with the buffer held */ 439/* Must be called with the buffer held */
592static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, 440static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
593 int status) 441 int status,
442 struct calling_interface_buffer *buffer)
594{ 443{
595 if (status & BIT(0)) { 444 if (status & BIT(0)) {
596 /* Has hw-switch, sync sw_state to BIOS */ 445 /* Has hw-switch, sync sw_state to BIOS */
597 int block = rfkill_blocked(rfkill); 446 int block = rfkill_blocked(rfkill);
598 clear_buffer(); 447 dell_smbios_clear_buffer();
599 buffer->input[0] = (1 | (radio << 8) | (block << 16)); 448 buffer->input[0] = (1 | (radio << 8) | (block << 16));
600 dell_send_request(buffer, 17, 11); 449 dell_smbios_send_request(17, 11);
601 } else { 450 } else {
602 /* No hw-switch, sync BIOS state to sw_state */ 451 /* No hw-switch, sync BIOS state to sw_state */
603 rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); 452 rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
@@ -613,30 +462,31 @@ static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
613 462
614static void dell_rfkill_query(struct rfkill *rfkill, void *data) 463static void dell_rfkill_query(struct rfkill *rfkill, void *data)
615{ 464{
465 struct calling_interface_buffer *buffer;
616 int radio = ((unsigned long)data & 0xF); 466 int radio = ((unsigned long)data & 0xF);
617 int hwswitch; 467 int hwswitch;
618 int status; 468 int status;
619 int ret; 469 int ret;
620 470
621 get_buffer(); 471 buffer = dell_smbios_get_buffer();
622 472
623 dell_send_request(buffer, 17, 11); 473 dell_smbios_send_request(17, 11);
624 ret = buffer->output[0]; 474 ret = buffer->output[0];
625 status = buffer->output[1]; 475 status = buffer->output[1];
626 476
627 if (ret != 0 || !(status & BIT(0))) { 477 if (ret != 0 || !(status & BIT(0))) {
628 release_buffer(); 478 dell_smbios_release_buffer();
629 return; 479 return;
630 } 480 }
631 481
632 clear_buffer(); 482 dell_smbios_clear_buffer();
633 483
634 buffer->input[0] = 0x2; 484 buffer->input[0] = 0x2;
635 dell_send_request(buffer, 17, 11); 485 dell_smbios_send_request(17, 11);
636 ret = buffer->output[0]; 486 ret = buffer->output[0];
637 hwswitch = buffer->output[1]; 487 hwswitch = buffer->output[1];
638 488
639 release_buffer(); 489 dell_smbios_release_buffer();
640 490
641 if (ret != 0) 491 if (ret != 0)
642 return; 492 return;
@@ -653,25 +503,26 @@ static struct dentry *dell_laptop_dir;
653 503
654static int dell_debugfs_show(struct seq_file *s, void *data) 504static int dell_debugfs_show(struct seq_file *s, void *data)
655{ 505{
506 struct calling_interface_buffer *buffer;
656 int hwswitch_state; 507 int hwswitch_state;
657 int hwswitch_ret; 508 int hwswitch_ret;
658 int status; 509 int status;
659 int ret; 510 int ret;
660 511
661 get_buffer(); 512 buffer = dell_smbios_get_buffer();
662 513
663 dell_send_request(buffer, 17, 11); 514 dell_smbios_send_request(17, 11);
664 ret = buffer->output[0]; 515 ret = buffer->output[0];
665 status = buffer->output[1]; 516 status = buffer->output[1];
666 517
667 clear_buffer(); 518 dell_smbios_clear_buffer();
668 519
669 buffer->input[0] = 0x2; 520 buffer->input[0] = 0x2;
670 dell_send_request(buffer, 17, 11); 521 dell_smbios_send_request(17, 11);
671 hwswitch_ret = buffer->output[0]; 522 hwswitch_ret = buffer->output[0];
672 hwswitch_state = buffer->output[1]; 523 hwswitch_state = buffer->output[1];
673 524
674 release_buffer(); 525 dell_smbios_release_buffer();
675 526
676 seq_printf(s, "return:\t%d\n", ret); 527 seq_printf(s, "return:\t%d\n", ret);
677 seq_printf(s, "status:\t0x%X\n", status); 528 seq_printf(s, "status:\t0x%X\n", status);
@@ -752,23 +603,24 @@ static const struct file_operations dell_debugfs_fops = {
752 603
753static void dell_update_rfkill(struct work_struct *ignored) 604static void dell_update_rfkill(struct work_struct *ignored)
754{ 605{
606 struct calling_interface_buffer *buffer;
755 int hwswitch = 0; 607 int hwswitch = 0;
756 int status; 608 int status;
757 int ret; 609 int ret;
758 610
759 get_buffer(); 611 buffer = dell_smbios_get_buffer();
760 612
761 dell_send_request(buffer, 17, 11); 613 dell_smbios_send_request(17, 11);
762 ret = buffer->output[0]; 614 ret = buffer->output[0];
763 status = buffer->output[1]; 615 status = buffer->output[1];
764 616
765 if (ret != 0) 617 if (ret != 0)
766 goto out; 618 goto out;
767 619
768 clear_buffer(); 620 dell_smbios_clear_buffer();
769 621
770 buffer->input[0] = 0x2; 622 buffer->input[0] = 0x2;
771 dell_send_request(buffer, 17, 11); 623 dell_smbios_send_request(17, 11);
772 ret = buffer->output[0]; 624 ret = buffer->output[0];
773 625
774 if (ret == 0 && (status & BIT(0))) 626 if (ret == 0 && (status & BIT(0)))
@@ -776,20 +628,21 @@ static void dell_update_rfkill(struct work_struct *ignored)
776 628
777 if (wifi_rfkill) { 629 if (wifi_rfkill) {
778 dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch); 630 dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch);
779 dell_rfkill_update_sw_state(wifi_rfkill, 1, status); 631 dell_rfkill_update_sw_state(wifi_rfkill, 1, status, buffer);
780 } 632 }
781 if (bluetooth_rfkill) { 633 if (bluetooth_rfkill) {
782 dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status, 634 dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status,
783 hwswitch); 635 hwswitch);
784 dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); 636 dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status,
637 buffer);
785 } 638 }
786 if (wwan_rfkill) { 639 if (wwan_rfkill) {
787 dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch); 640 dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch);
788 dell_rfkill_update_sw_state(wwan_rfkill, 3, status); 641 dell_rfkill_update_sw_state(wwan_rfkill, 3, status, buffer);
789 } 642 }
790 643
791 out: 644 out:
792 release_buffer(); 645 dell_smbios_release_buffer();
793} 646}
794static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); 647static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
795 648
@@ -833,6 +686,7 @@ static struct notifier_block dell_laptop_rbtn_notifier = {
833 686
834static int __init dell_setup_rfkill(void) 687static int __init dell_setup_rfkill(void)
835{ 688{
689 struct calling_interface_buffer *buffer;
836 int status, ret, whitelisted; 690 int status, ret, whitelisted;
837 const char *product; 691 const char *product;
838 692
@@ -848,11 +702,11 @@ static int __init dell_setup_rfkill(void)
848 if (!force_rfkill && !whitelisted) 702 if (!force_rfkill && !whitelisted)
849 return 0; 703 return 0;
850 704
851 get_buffer(); 705 buffer = dell_smbios_get_buffer();
852 dell_send_request(buffer, 17, 11); 706 dell_smbios_send_request(17, 11);
853 ret = buffer->output[0]; 707 ret = buffer->output[0];
854 status = buffer->output[1]; 708 status = buffer->output[1];
855 release_buffer(); 709 dell_smbios_release_buffer();
856 710
857 /* dell wireless info smbios call is not supported */ 711 /* dell wireless info smbios call is not supported */
858 if (ret != 0) 712 if (ret != 0)
@@ -1005,51 +859,53 @@ static void dell_cleanup_rfkill(void)
1005 859
1006static int dell_send_intensity(struct backlight_device *bd) 860static int dell_send_intensity(struct backlight_device *bd)
1007{ 861{
1008 int token; 862 struct calling_interface_buffer *buffer;
863 struct calling_interface_token *token;
1009 int ret; 864 int ret;
1010 865
1011 token = find_token_location(BRIGHTNESS_TOKEN); 866 token = dell_smbios_find_token(BRIGHTNESS_TOKEN);
1012 if (token == -1) 867 if (!token)
1013 return -ENODEV; 868 return -ENODEV;
1014 869
1015 get_buffer(); 870 buffer = dell_smbios_get_buffer();
1016 buffer->input[0] = token; 871 buffer->input[0] = token->location;
1017 buffer->input[1] = bd->props.brightness; 872 buffer->input[1] = bd->props.brightness;
1018 873
1019 if (power_supply_is_system_supplied() > 0) 874 if (power_supply_is_system_supplied() > 0)
1020 dell_send_request(buffer, 1, 2); 875 dell_smbios_send_request(1, 2);
1021 else 876 else
1022 dell_send_request(buffer, 1, 1); 877 dell_smbios_send_request(1, 1);
1023 878
1024 ret = dell_smi_error(buffer->output[0]); 879 ret = dell_smbios_error(buffer->output[0]);
1025 880
1026 release_buffer(); 881 dell_smbios_release_buffer();
1027 return ret; 882 return ret;
1028} 883}
1029 884
1030static int dell_get_intensity(struct backlight_device *bd) 885static int dell_get_intensity(struct backlight_device *bd)
1031{ 886{
1032 int token; 887 struct calling_interface_buffer *buffer;
888 struct calling_interface_token *token;
1033 int ret; 889 int ret;
1034 890
1035 token = find_token_location(BRIGHTNESS_TOKEN); 891 token = dell_smbios_find_token(BRIGHTNESS_TOKEN);
1036 if (token == -1) 892 if (!token)
1037 return -ENODEV; 893 return -ENODEV;
1038 894
1039 get_buffer(); 895 buffer = dell_smbios_get_buffer();
1040 buffer->input[0] = token; 896 buffer->input[0] = token->location;
1041 897
1042 if (power_supply_is_system_supplied() > 0) 898 if (power_supply_is_system_supplied() > 0)
1043 dell_send_request(buffer, 0, 2); 899 dell_smbios_send_request(0, 2);
1044 else 900 else
1045 dell_send_request(buffer, 0, 1); 901 dell_smbios_send_request(0, 1);
1046 902
1047 if (buffer->output[0]) 903 if (buffer->output[0])
1048 ret = dell_smi_error(buffer->output[0]); 904 ret = dell_smbios_error(buffer->output[0]);
1049 else 905 else
1050 ret = buffer->output[1]; 906 ret = buffer->output[1];
1051 907
1052 release_buffer(); 908 dell_smbios_release_buffer();
1053 return ret; 909 return ret;
1054} 910}
1055 911
@@ -1293,17 +1149,18 @@ static bool kbd_led_present;
1293 1149
1294static int kbd_get_info(struct kbd_info *info) 1150static int kbd_get_info(struct kbd_info *info)
1295{ 1151{
1152 struct calling_interface_buffer *buffer;
1296 u8 units; 1153 u8 units;
1297 int ret; 1154 int ret;
1298 1155
1299 get_buffer(); 1156 buffer = dell_smbios_get_buffer();
1300 1157
1301 buffer->input[0] = 0x0; 1158 buffer->input[0] = 0x0;
1302 dell_send_request(buffer, 4, 11); 1159 dell_smbios_send_request(4, 11);
1303 ret = buffer->output[0]; 1160 ret = buffer->output[0];
1304 1161
1305 if (ret) { 1162 if (ret) {
1306 ret = dell_smi_error(ret); 1163 ret = dell_smbios_error(ret);
1307 goto out; 1164 goto out;
1308 } 1165 }
1309 1166
@@ -1323,7 +1180,7 @@ static int kbd_get_info(struct kbd_info *info)
1323 info->days = (buffer->output[3] >> 24) & 0xFF; 1180 info->days = (buffer->output[3] >> 24) & 0xFF;
1324 1181
1325 out: 1182 out:
1326 release_buffer(); 1183 dell_smbios_release_buffer();
1327 return ret; 1184 return ret;
1328} 1185}
1329 1186
@@ -1382,16 +1239,17 @@ static int kbd_set_level(struct kbd_state *state, u8 level)
1382 1239
1383static int kbd_get_state(struct kbd_state *state) 1240static int kbd_get_state(struct kbd_state *state)
1384{ 1241{
1242 struct calling_interface_buffer *buffer;
1385 int ret; 1243 int ret;
1386 1244
1387 get_buffer(); 1245 buffer = dell_smbios_get_buffer();
1388 1246
1389 buffer->input[0] = 0x1; 1247 buffer->input[0] = 0x1;
1390 dell_send_request(buffer, 4, 11); 1248 dell_smbios_send_request(4, 11);
1391 ret = buffer->output[0]; 1249 ret = buffer->output[0];
1392 1250
1393 if (ret) { 1251 if (ret) {
1394 ret = dell_smi_error(ret); 1252 ret = dell_smbios_error(ret);
1395 goto out; 1253 goto out;
1396 } 1254 }
1397 1255
@@ -1407,15 +1265,16 @@ static int kbd_get_state(struct kbd_state *state)
1407 state->level = (buffer->output[2] >> 16) & 0xFF; 1265 state->level = (buffer->output[2] >> 16) & 0xFF;
1408 1266
1409 out: 1267 out:
1410 release_buffer(); 1268 dell_smbios_release_buffer();
1411 return ret; 1269 return ret;
1412} 1270}
1413 1271
1414static int kbd_set_state(struct kbd_state *state) 1272static int kbd_set_state(struct kbd_state *state)
1415{ 1273{
1274 struct calling_interface_buffer *buffer;
1416 int ret; 1275 int ret;
1417 1276
1418 get_buffer(); 1277 buffer = dell_smbios_get_buffer();
1419 buffer->input[0] = 0x2; 1278 buffer->input[0] = 0x2;
1420 buffer->input[1] = BIT(state->mode_bit) & 0xFFFF; 1279 buffer->input[1] = BIT(state->mode_bit) & 0xFFFF;
1421 buffer->input[1] |= (state->triggers & 0xFF) << 16; 1280 buffer->input[1] |= (state->triggers & 0xFF) << 16;
@@ -1423,11 +1282,11 @@ static int kbd_set_state(struct kbd_state *state)
1423 buffer->input[1] |= (state->timeout_unit & 0x3) << 30; 1282 buffer->input[1] |= (state->timeout_unit & 0x3) << 30;
1424 buffer->input[2] = state->als_setting & 0xFF; 1283 buffer->input[2] = state->als_setting & 0xFF;
1425 buffer->input[2] |= (state->level & 0xFF) << 16; 1284 buffer->input[2] |= (state->level & 0xFF) << 16;
1426 dell_send_request(buffer, 4, 11); 1285 dell_smbios_send_request(4, 11);
1427 ret = buffer->output[0]; 1286 ret = buffer->output[0];
1428 release_buffer(); 1287 dell_smbios_release_buffer();
1429 1288
1430 return dell_smi_error(ret); 1289 return dell_smbios_error(ret);
1431} 1290}
1432 1291
1433static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old) 1292static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old)
@@ -1452,50 +1311,52 @@ static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old)
1452 1311
1453static int kbd_set_token_bit(u8 bit) 1312static int kbd_set_token_bit(u8 bit)
1454{ 1313{
1455 int id; 1314 struct calling_interface_buffer *buffer;
1315 struct calling_interface_token *token;
1456 int ret; 1316 int ret;
1457 1317
1458 if (bit >= ARRAY_SIZE(kbd_tokens)) 1318 if (bit >= ARRAY_SIZE(kbd_tokens))
1459 return -EINVAL; 1319 return -EINVAL;
1460 1320
1461 id = find_token_id(kbd_tokens[bit]); 1321 token = dell_smbios_find_token(kbd_tokens[bit]);
1462 if (id == -1) 1322 if (!token)
1463 return -EINVAL; 1323 return -EINVAL;
1464 1324
1465 get_buffer(); 1325 buffer = dell_smbios_get_buffer();
1466 buffer->input[0] = da_tokens[id].location; 1326 buffer->input[0] = token->location;
1467 buffer->input[1] = da_tokens[id].value; 1327 buffer->input[1] = token->value;
1468 dell_send_request(buffer, 1, 0); 1328 dell_smbios_send_request(1, 0);
1469 ret = buffer->output[0]; 1329 ret = buffer->output[0];
1470 release_buffer(); 1330 dell_smbios_release_buffer();
1471 1331
1472 return dell_smi_error(ret); 1332 return dell_smbios_error(ret);
1473} 1333}
1474 1334
1475static int kbd_get_token_bit(u8 bit) 1335static int kbd_get_token_bit(u8 bit)
1476{ 1336{
1477 int id; 1337 struct calling_interface_buffer *buffer;
1338 struct calling_interface_token *token;
1478 int ret; 1339 int ret;
1479 int val; 1340 int val;
1480 1341
1481 if (bit >= ARRAY_SIZE(kbd_tokens)) 1342 if (bit >= ARRAY_SIZE(kbd_tokens))
1482 return -EINVAL; 1343 return -EINVAL;
1483 1344
1484 id = find_token_id(kbd_tokens[bit]); 1345 token = dell_smbios_find_token(kbd_tokens[bit]);
1485 if (id == -1) 1346 if (!token)
1486 return -EINVAL; 1347 return -EINVAL;
1487 1348
1488 get_buffer(); 1349 buffer = dell_smbios_get_buffer();
1489 buffer->input[0] = da_tokens[id].location; 1350 buffer->input[0] = token->location;
1490 dell_send_request(buffer, 0, 0); 1351 dell_smbios_send_request(0, 0);
1491 ret = buffer->output[0]; 1352 ret = buffer->output[0];
1492 val = buffer->output[1]; 1353 val = buffer->output[1];
1493 release_buffer(); 1354 dell_smbios_release_buffer();
1494 1355
1495 if (ret) 1356 if (ret)
1496 return dell_smi_error(ret); 1357 return dell_smbios_error(ret);
1497 1358
1498 return (val == da_tokens[id].value); 1359 return (val == token->value);
1499} 1360}
1500 1361
1501static int kbd_get_first_active_token_bit(void) 1362static int kbd_get_first_active_token_bit(void)
@@ -1597,7 +1458,7 @@ static inline void kbd_init_tokens(void)
1597 int i; 1458 int i;
1598 1459
1599 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) 1460 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i)
1600 if (find_token_id(kbd_tokens[i]) != -1) 1461 if (dell_smbios_find_token(kbd_tokens[i]))
1601 kbd_token_bits |= BIT(i); 1462 kbd_token_bits |= BIT(i);
1602} 1463}
1603 1464
@@ -2111,8 +1972,9 @@ static void kbd_led_exit(void)
2111 1972
2112static int __init dell_init(void) 1973static int __init dell_init(void)
2113{ 1974{
1975 struct calling_interface_buffer *buffer;
1976 struct calling_interface_token *token;
2114 int max_intensity = 0; 1977 int max_intensity = 0;
2115 int token;
2116 int ret; 1978 int ret;
2117 1979
2118 if (!dmi_check_system(dell_device_table)) 1980 if (!dmi_check_system(dell_device_table))
@@ -2122,13 +1984,6 @@ static int __init dell_init(void)
2122 /* find if this machine support other functions */ 1984 /* find if this machine support other functions */
2123 dmi_check_system(dell_quirks); 1985 dmi_check_system(dell_quirks);
2124 1986
2125 dmi_walk(find_tokens, NULL);
2126
2127 if (!da_tokens) {
2128 pr_info("Unable to find dmi tokens\n");
2129 return -ENODEV;
2130 }
2131
2132 ret = platform_driver_register(&platform_driver); 1987 ret = platform_driver_register(&platform_driver);
2133 if (ret) 1988 if (ret)
2134 goto fail_platform_driver; 1989 goto fail_platform_driver;
@@ -2141,16 +1996,6 @@ static int __init dell_init(void)
2141 if (ret) 1996 if (ret)
2142 goto fail_platform_device2; 1997 goto fail_platform_device2;
2143 1998
2144 /*
2145 * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
2146 * is passed to SMI handler.
2147 */
2148 buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
2149 if (!buffer) {
2150 ret = -ENOMEM;
2151 goto fail_buffer;
2152 }
2153
2154 ret = dell_setup_rfkill(); 1999 ret = dell_setup_rfkill();
2155 2000
2156 if (ret) { 2001 if (ret) {
@@ -2171,14 +2016,14 @@ static int __init dell_init(void)
2171 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2016 if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
2172 return 0; 2017 return 0;
2173 2018
2174 token = find_token_location(BRIGHTNESS_TOKEN); 2019 token = dell_smbios_find_token(BRIGHTNESS_TOKEN);
2175 if (token != -1) { 2020 if (token) {
2176 get_buffer(); 2021 buffer = dell_smbios_get_buffer();
2177 buffer->input[0] = token; 2022 buffer->input[0] = token->location;
2178 dell_send_request(buffer, 0, 2); 2023 dell_smbios_send_request(0, 2);
2179 if (buffer->output[0] == 0) 2024 if (buffer->output[0] == 0)
2180 max_intensity = buffer->output[3]; 2025 max_intensity = buffer->output[3];
2181 release_buffer(); 2026 dell_smbios_release_buffer();
2182 } 2027 }
2183 2028
2184 if (max_intensity) { 2029 if (max_intensity) {
@@ -2208,15 +2053,12 @@ static int __init dell_init(void)
2208fail_backlight: 2053fail_backlight:
2209 dell_cleanup_rfkill(); 2054 dell_cleanup_rfkill();
2210fail_rfkill: 2055fail_rfkill:
2211 free_page((unsigned long)buffer);
2212fail_buffer:
2213 platform_device_del(platform_device); 2056 platform_device_del(platform_device);
2214fail_platform_device2: 2057fail_platform_device2:
2215 platform_device_put(platform_device); 2058 platform_device_put(platform_device);
2216fail_platform_device1: 2059fail_platform_device1:
2217 platform_driver_unregister(&platform_driver); 2060 platform_driver_unregister(&platform_driver);
2218fail_platform_driver: 2061fail_platform_driver:
2219 kfree(da_tokens);
2220 return ret; 2062 return ret;
2221} 2063}
2222 2064
@@ -2232,8 +2074,6 @@ static void __exit dell_exit(void)
2232 platform_device_unregister(platform_device); 2074 platform_device_unregister(platform_device);
2233 platform_driver_unregister(&platform_driver); 2075 platform_driver_unregister(&platform_driver);
2234 } 2076 }
2235 kfree(da_tokens);
2236 free_page((unsigned long)buffer);
2237} 2077}
2238 2078
2239/* dell-rbtn.c driver export functions which will not work correctly (and could 2079/* dell-rbtn.c driver export functions which will not work correctly (and could
diff --git a/drivers/platform/x86/dell-rbtn.c b/drivers/platform/x86/dell-rbtn.c
index cd410e392550..b51a2008d782 100644
--- a/drivers/platform/x86/dell-rbtn.c
+++ b/drivers/platform/x86/dell-rbtn.c
@@ -217,6 +217,21 @@ static void rbtn_notify(struct acpi_device *device, u32 event);
217static const struct acpi_device_id rbtn_ids[] = { 217static const struct acpi_device_id rbtn_ids[] = {
218 { "DELRBTN", 0 }, 218 { "DELRBTN", 0 },
219 { "DELLABCE", 0 }, 219 { "DELLABCE", 0 },
220
221 /*
222 * This driver can also handle the "DELLABC6" device that
223 * appears on the XPS 13 9350, but that device is disabled
224 * by the DSDT unless booted with acpi_osi="!Windows 2012"
225 * acpi_osi="!Windows 2013". Even if we boot that and bind
226 * the driver, we seem to have inconsistent behavior in
227 * which NetworkManager can get out of sync with the rfkill
228 * state.
229 *
230 * On the XPS 13 9350 and similar laptops, we're not supposed to
231 * use DELLABC6 at all. Instead, we handle the rfkill button
232 * via the intel-hid driver.
233 */
234
220 { "", 0 }, 235 { "", 0 },
221}; 236};
222 237
diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c
new file mode 100644
index 000000000000..d2412ab097da
--- /dev/null
+++ b/drivers/platform/x86/dell-smbios.c
@@ -0,0 +1,193 @@
1/*
2 * Common functions for kernel modules using Dell SMBIOS
3 *
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>
7 *
8 * Based on documentation in the libsmbios package:
9 * Copyright (C) 2005-2014 Dell Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/dmi.h>
19#include <linux/err.h>
20#include <linux/gfp.h>
21#include <linux/mutex.h>
22#include <linux/slab.h>
23#include <linux/io.h>
24#include "../../firmware/dcdbas.h"
25#include "dell-smbios.h"
26
27struct calling_interface_structure {
28 struct dmi_header header;
29 u16 cmdIOAddress;
30 u8 cmdIOCode;
31 u32 supportedCmds;
32 struct calling_interface_token tokens[];
33} __packed;
34
35static struct calling_interface_buffer *buffer;
36static DEFINE_MUTEX(buffer_mutex);
37
38static int da_command_address;
39static int da_command_code;
40static int da_num_tokens;
41static struct calling_interface_token *da_tokens;
42
43int dell_smbios_error(int value)
44{
45 switch (value) {
46 case 0: /* Completed successfully */
47 return 0;
48 case -1: /* Completed with error */
49 return -EIO;
50 case -2: /* Function not supported */
51 return -ENXIO;
52 default: /* Unknown error */
53 return -EINVAL;
54 }
55}
56EXPORT_SYMBOL_GPL(dell_smbios_error);
57
58struct calling_interface_buffer *dell_smbios_get_buffer(void)
59{
60 mutex_lock(&buffer_mutex);
61 dell_smbios_clear_buffer();
62 return buffer;
63}
64EXPORT_SYMBOL_GPL(dell_smbios_get_buffer);
65
66void dell_smbios_clear_buffer(void)
67{
68 memset(buffer, 0, sizeof(struct calling_interface_buffer));
69}
70EXPORT_SYMBOL_GPL(dell_smbios_clear_buffer);
71
72void dell_smbios_release_buffer(void)
73{
74 mutex_unlock(&buffer_mutex);
75}
76EXPORT_SYMBOL_GPL(dell_smbios_release_buffer);
77
78void dell_smbios_send_request(int class, int select)
79{
80 struct smi_cmd command;
81
82 command.magic = SMI_CMD_MAGIC;
83 command.command_address = da_command_address;
84 command.command_code = da_command_code;
85 command.ebx = virt_to_phys(buffer);
86 command.ecx = 0x42534931;
87
88 buffer->class = class;
89 buffer->select = select;
90
91 dcdbas_smi_request(&command);
92}
93EXPORT_SYMBOL_GPL(dell_smbios_send_request);
94
95struct calling_interface_token *dell_smbios_find_token(int tokenid)
96{
97 int i;
98
99 for (i = 0; i < da_num_tokens; i++) {
100 if (da_tokens[i].tokenID == tokenid)
101 return &da_tokens[i];
102 }
103
104 return NULL;
105}
106EXPORT_SYMBOL_GPL(dell_smbios_find_token);
107
108static void __init parse_da_table(const struct dmi_header *dm)
109{
110 /* Final token is a terminator, so we don't want to copy it */
111 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
112 struct calling_interface_token *new_da_tokens;
113 struct calling_interface_structure *table =
114 container_of(dm, struct calling_interface_structure, header);
115
116 /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least
117 6 bytes of entry */
118
119 if (dm->length < 17)
120 return;
121
122 da_command_address = table->cmdIOAddress;
123 da_command_code = table->cmdIOCode;
124
125 new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) *
126 sizeof(struct calling_interface_token),
127 GFP_KERNEL);
128
129 if (!new_da_tokens)
130 return;
131 da_tokens = new_da_tokens;
132
133 memcpy(da_tokens+da_num_tokens, table->tokens,
134 sizeof(struct calling_interface_token) * tokens);
135
136 da_num_tokens += tokens;
137}
138
139static void __init find_tokens(const struct dmi_header *dm, void *dummy)
140{
141 switch (dm->type) {
142 case 0xd4: /* Indexed IO */
143 case 0xd5: /* Protected Area Type 1 */
144 case 0xd6: /* Protected Area Type 2 */
145 break;
146 case 0xda: /* Calling interface */
147 parse_da_table(dm);
148 break;
149 }
150}
151
152static int __init dell_smbios_init(void)
153{
154 int ret;
155
156 dmi_walk(find_tokens, NULL);
157
158 if (!da_tokens) {
159 pr_info("Unable to find dmi tokens\n");
160 return -ENODEV;
161 }
162
163 /*
164 * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
165 * is passed to SMI handler.
166 */
167 buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
168 if (!buffer) {
169 ret = -ENOMEM;
170 goto fail_buffer;
171 }
172
173 return 0;
174
175fail_buffer:
176 kfree(da_tokens);
177 return ret;
178}
179
180static void __exit dell_smbios_exit(void)
181{
182 kfree(da_tokens);
183 free_page((unsigned long)buffer);
184}
185
186subsys_initcall(dell_smbios_init);
187module_exit(dell_smbios_exit);
188
189MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
190MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>");
191MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
192MODULE_DESCRIPTION("Common functions for kernel modules using Dell SMBIOS");
193MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h
new file mode 100644
index 000000000000..ec7d40ae5e6e
--- /dev/null
+++ b/drivers/platform/x86/dell-smbios.h
@@ -0,0 +1,46 @@
1/*
2 * Common functions for kernel modules using Dell SMBIOS
3 *
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>
7 *
8 * Based on documentation in the libsmbios package:
9 * Copyright (C) 2005-2014 Dell Inc.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#ifndef _DELL_SMBIOS_H_
17#define _DELL_SMBIOS_H_
18
19/* This structure will be modified by the firmware when we enter
20 * system management mode, hence the volatiles */
21
22struct calling_interface_buffer {
23 u16 class;
24 u16 select;
25 volatile u32 input[4];
26 volatile u32 output[4];
27} __packed;
28
29struct calling_interface_token {
30 u16 tokenID;
31 u16 location;
32 union {
33 u16 value;
34 u16 stringlength;
35 };
36};
37
38int dell_smbios_error(int value);
39
40struct calling_interface_buffer *dell_smbios_get_buffer(void);
41void dell_smbios_clear_buffer(void);
42void dell_smbios_release_buffer(void);
43void dell_smbios_send_request(int class, int select);
44
45struct calling_interface_token *dell_smbios_find_token(int tokenid);
46#endif
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 368e193c2741..15c6f1191aec 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -37,6 +37,7 @@
37#include <linux/string.h> 37#include <linux/string.h>
38#include <linux/dmi.h> 38#include <linux/dmi.h>
39#include <acpi/video.h> 39#include <acpi/video.h>
40#include "dell-smbios.h"
40 41
41MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 42MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
42MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); 43MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
@@ -47,10 +48,37 @@ MODULE_LICENSE("GPL");
47#define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492" 48#define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
48 49
49static u32 dell_wmi_interface_version; 50static u32 dell_wmi_interface_version;
51static bool wmi_requires_smbios_request;
50 52
51MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 53MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
52MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID); 54MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID);
53 55
56static int __init dmi_matched(const struct dmi_system_id *dmi)
57{
58 wmi_requires_smbios_request = 1;
59 return 1;
60}
61
62static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = {
63 {
64 .callback = dmi_matched,
65 .ident = "Dell Inspiron M5110",
66 .matches = {
67 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
68 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"),
69 },
70 },
71 {
72 .callback = dmi_matched,
73 .ident = "Dell Vostro V131",
74 .matches = {
75 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
76 DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
77 },
78 },
79 { }
80};
81
54/* 82/*
55 * Certain keys are flagged as KE_IGNORE. All of these are either 83 * Certain keys are flagged as KE_IGNORE. All of these are either
56 * notifications (rather than requests for change) or are also sent 84 * notifications (rather than requests for change) or are also sent
@@ -90,8 +118,11 @@ static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
90 118
91 { KE_IGNORE, 0xe020, { KEY_MUTE } }, 119 { KE_IGNORE, 0xe020, { KEY_MUTE } },
92 120
93 /* Shortcut and audio panel keys */ 121 /* Dell Instant Launch key */
94 { KE_IGNORE, 0xe025, { KEY_RESERVED } }, 122 { KE_KEY, 0xe025, { KEY_PROG4 } },
123 { KE_KEY, 0xe029, { KEY_PROG4 } },
124
125 /* Audio panel key */
95 { KE_IGNORE, 0xe026, { KEY_RESERVED } }, 126 { KE_IGNORE, 0xe026, { KEY_RESERVED } },
96 127
97 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } }, 128 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
@@ -120,7 +151,10 @@ struct dell_bios_hotkey_table {
120 151
121}; 152};
122 153
123static const struct dell_bios_hotkey_table *dell_bios_hotkey_table; 154struct dell_dmi_results {
155 int err;
156 struct key_entry *keymap;
157};
124 158
125/* Uninitialized entries here are KEY_RESERVED == 0. */ 159/* Uninitialized entries here are KEY_RESERVED == 0. */
126static const u16 bios_to_linux_keycode[256] __initconst = { 160static const u16 bios_to_linux_keycode[256] __initconst = {
@@ -166,6 +200,30 @@ static const u16 bios_to_linux_keycode[256] __initconst = {
166 [255] = KEY_PROG3, 200 [255] = KEY_PROG3,
167}; 201};
168 202
203/*
204 * These are applied if the 0xB2 DMI hotkey table is present and doesn't
205 * override them.
206 */
207static const struct key_entry dell_wmi_extra_keymap[] __initconst = {
208 /* Fn-lock */
209 { KE_IGNORE, 0x151, { KEY_RESERVED } },
210
211 /* Change keyboard illumination */
212 { KE_IGNORE, 0x152, { KEY_KBDILLUMTOGGLE } },
213
214 /*
215 * Radio disable (notify only -- there is no model for which the
216 * WMI event is supposed to trigger an action).
217 */
218 { KE_IGNORE, 0x153, { KEY_RFKILL } },
219
220 /* RGB keyboard backlight control */
221 { KE_IGNORE, 0x154, { KEY_RESERVED } },
222
223 /* Stealth mode toggle */
224 { KE_IGNORE, 0x155, { KEY_RESERVED } },
225};
226
169static struct input_dev *dell_wmi_input_dev; 227static struct input_dev *dell_wmi_input_dev;
170 228
171static void dell_wmi_process_key(int reported_key) 229static void dell_wmi_process_key(int reported_key)
@@ -188,6 +246,9 @@ static void dell_wmi_process_key(int reported_key)
188 acpi_video_handles_brightness_key_presses()) 246 acpi_video_handles_brightness_key_presses())
189 return; 247 return;
190 248
249 if (reported_key == 0xe025 && !wmi_requires_smbios_request)
250 return;
251
191 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true); 252 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
192} 253}
193 254
@@ -337,20 +398,60 @@ static void dell_wmi_notify(u32 value, void *context)
337 kfree(obj); 398 kfree(obj);
338} 399}
339 400
340static const struct key_entry * __init dell_wmi_prepare_new_keymap(void) 401static bool have_scancode(u32 scancode, const struct key_entry *keymap, int len)
341{ 402{
342 int hotkey_num = (dell_bios_hotkey_table->header.length - 4) /
343 sizeof(struct dell_bios_keymap_entry);
344 struct key_entry *keymap;
345 int i; 403 int i;
346 404
347 keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL); 405 for (i = 0; i < len; i++)
348 if (!keymap) 406 if (keymap[i].code == scancode)
349 return NULL; 407 return true;
408
409 return false;
410}
411
412static void __init handle_dmi_entry(const struct dmi_header *dm,
413
414 void *opaque)
415
416{
417 struct dell_dmi_results *results = opaque;
418 struct dell_bios_hotkey_table *table;
419 int hotkey_num, i, pos = 0;
420 struct key_entry *keymap;
421 int num_bios_keys;
422
423 if (results->err || results->keymap)
424 return; /* We already found the hotkey table. */
425
426 if (dm->type != 0xb2)
427 return;
428
429 table = container_of(dm, struct dell_bios_hotkey_table, header);
430
431 hotkey_num = (table->header.length -
432 sizeof(struct dell_bios_hotkey_table)) /
433 sizeof(struct dell_bios_keymap_entry);
434 if (hotkey_num < 1) {
435 /*
436 * Historically, dell-wmi would ignore a DMI entry of
437 * fewer than 7 bytes. Sizes between 4 and 8 bytes are
438 * nonsensical (both the header and all entries are 4
439 * bytes), so we approximate the old behavior by
440 * ignoring tables with fewer than one entry.
441 */
442 return;
443 }
444
445 keymap = kcalloc(hotkey_num + ARRAY_SIZE(dell_wmi_extra_keymap) + 1,
446 sizeof(struct key_entry), GFP_KERNEL);
447 if (!keymap) {
448 results->err = -ENOMEM;
449 return;
450 }
350 451
351 for (i = 0; i < hotkey_num; i++) { 452 for (i = 0; i < hotkey_num; i++) {
352 const struct dell_bios_keymap_entry *bios_entry = 453 const struct dell_bios_keymap_entry *bios_entry =
353 &dell_bios_hotkey_table->keymap[i]; 454 &table->keymap[i];
354 455
355 /* Uninitialized entries are 0 aka KEY_RESERVED. */ 456 /* Uninitialized entries are 0 aka KEY_RESERVED. */
356 u16 keycode = (bios_entry->keycode < 457 u16 keycode = (bios_entry->keycode <
@@ -370,20 +471,39 @@ static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
370 } 471 }
371 472
372 if (keycode == KEY_KBDILLUMTOGGLE) 473 if (keycode == KEY_KBDILLUMTOGGLE)
373 keymap[i].type = KE_IGNORE; 474 keymap[pos].type = KE_IGNORE;
374 else 475 else
375 keymap[i].type = KE_KEY; 476 keymap[pos].type = KE_KEY;
376 keymap[i].code = bios_entry->scancode; 477 keymap[pos].code = bios_entry->scancode;
377 keymap[i].keycode = keycode; 478 keymap[pos].keycode = keycode;
479
480 pos++;
481 }
482
483 num_bios_keys = pos;
484
485 for (i = 0; i < ARRAY_SIZE(dell_wmi_extra_keymap); i++) {
486 const struct key_entry *entry = &dell_wmi_extra_keymap[i];
487
488 /*
489 * Check if we've already found this scancode. This takes
490 * quadratic time, but it doesn't matter unless the list
491 * of extra keys gets very long.
492 */
493 if (!have_scancode(entry->code, keymap, num_bios_keys)) {
494 keymap[pos] = *entry;
495 pos++;
496 }
378 } 497 }
379 498
380 keymap[hotkey_num].type = KE_END; 499 keymap[pos].type = KE_END;
381 500
382 return keymap; 501 results->keymap = keymap;
383} 502}
384 503
385static int __init dell_wmi_input_setup(void) 504static int __init dell_wmi_input_setup(void)
386{ 505{
506 struct dell_dmi_results dmi_results = {};
387 int err; 507 int err;
388 508
389 dell_wmi_input_dev = input_allocate_device(); 509 dell_wmi_input_dev = input_allocate_device();
@@ -394,20 +514,31 @@ static int __init dell_wmi_input_setup(void)
394 dell_wmi_input_dev->phys = "wmi/input0"; 514 dell_wmi_input_dev->phys = "wmi/input0";
395 dell_wmi_input_dev->id.bustype = BUS_HOST; 515 dell_wmi_input_dev->id.bustype = BUS_HOST;
396 516
397 if (dell_new_hk_type) { 517 if (dmi_walk(handle_dmi_entry, &dmi_results)) {
398 const struct key_entry *keymap = dell_wmi_prepare_new_keymap(); 518 /*
399 if (!keymap) { 519 * Historically, dell-wmi ignored dmi_walk errors. A failure
400 err = -ENOMEM; 520 * is certainly surprising, but it probably just indicates
401 goto err_free_dev; 521 * a very old laptop.
402 } 522 */
523 pr_warn("no DMI; using the old-style hotkey interface\n");
524 }
403 525
404 err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL); 526 if (dmi_results.err) {
527 err = dmi_results.err;
528 goto err_free_dev;
529 }
530
531 if (dmi_results.keymap) {
532 dell_new_hk_type = true;
533
534 err = sparse_keymap_setup(dell_wmi_input_dev,
535 dmi_results.keymap, NULL);
405 536
406 /* 537 /*
407 * Sparse keymap library makes a copy of keymap so we 538 * Sparse keymap library makes a copy of keymap so we
408 * don't need the original one that was allocated. 539 * don't need the original one that was allocated.
409 */ 540 */
410 kfree(keymap); 541 kfree(dmi_results.keymap);
411 } else { 542 } else {
412 err = sparse_keymap_setup(dell_wmi_input_dev, 543 err = sparse_keymap_setup(dell_wmi_input_dev,
413 dell_wmi_legacy_keymap, NULL); 544 dell_wmi_legacy_keymap, NULL);
@@ -434,15 +565,6 @@ static void dell_wmi_input_destroy(void)
434 input_unregister_device(dell_wmi_input_dev); 565 input_unregister_device(dell_wmi_input_dev);
435} 566}
436 567
437static void __init find_hk_type(const struct dmi_header *dm, void *dummy)
438{
439 if (dm->type == 0xb2 && dm->length > 6) {
440 dell_new_hk_type = true;
441 dell_bios_hotkey_table =
442 container_of(dm, struct dell_bios_hotkey_table, header);
443 }
444}
445
446/* 568/*
447 * Descriptor buffer is 128 byte long and contains: 569 * Descriptor buffer is 128 byte long and contains:
448 * 570 *
@@ -509,6 +631,38 @@ static int __init dell_wmi_check_descriptor_buffer(void)
509 return 0; 631 return 0;
510} 632}
511 633
634/*
635 * According to Dell SMBIOS documentation:
636 *
637 * 17 3 Application Program Registration
638 *
639 * cbArg1 Application ID 1 = 0x00010000
640 * cbArg2 Application ID 2
641 * QUICKSET/DCP = 0x51534554 "QSET"
642 * ALS Driver = 0x416c7353 "AlsS"
643 * Latitude ON = 0x4c6f6e52 "LonR"
644 * cbArg3 Application version or revision number
645 * cbArg4 0 = Unregister application
646 * 1 = Register application
647 * cbRes1 Standard return codes (0, -1, -2)
648 */
649
650static int dell_wmi_events_set_enabled(bool enable)
651{
652 struct calling_interface_buffer *buffer;
653 int ret;
654
655 buffer = dell_smbios_get_buffer();
656 buffer->input[0] = 0x10000;
657 buffer->input[1] = 0x51534554;
658 buffer->input[3] = enable;
659 dell_smbios_send_request(17, 3);
660 ret = buffer->output[0];
661 dell_smbios_release_buffer();
662
663 return dell_smbios_error(ret);
664}
665
512static int __init dell_wmi_init(void) 666static int __init dell_wmi_init(void)
513{ 667{
514 int err; 668 int err;
@@ -524,8 +678,6 @@ static int __init dell_wmi_init(void)
524 if (err) 678 if (err)
525 return err; 679 return err;
526 680
527 dmi_walk(find_hk_type, NULL);
528
529 err = dell_wmi_input_setup(); 681 err = dell_wmi_input_setup();
530 if (err) 682 if (err)
531 return err; 683 return err;
@@ -538,12 +690,26 @@ static int __init dell_wmi_init(void)
538 return -ENODEV; 690 return -ENODEV;
539 } 691 }
540 692
693 dmi_check_system(dell_wmi_smbios_list);
694
695 if (wmi_requires_smbios_request) {
696 err = dell_wmi_events_set_enabled(true);
697 if (err) {
698 pr_err("Failed to enable WMI events\n");
699 wmi_remove_notify_handler(DELL_EVENT_GUID);
700 dell_wmi_input_destroy();
701 return err;
702 }
703 }
704
541 return 0; 705 return 0;
542} 706}
543module_init(dell_wmi_init); 707module_init(dell_wmi_init);
544 708
545static void __exit dell_wmi_exit(void) 709static void __exit dell_wmi_exit(void)
546{ 710{
711 if (wmi_requires_smbios_request)
712 dell_wmi_events_set_enabled(false);
547 wmi_remove_notify_handler(DELL_EVENT_GUID); 713 wmi_remove_notify_handler(DELL_EVENT_GUID);
548 dell_wmi_input_destroy(); 714 dell_wmi_input_destroy();
549} 715}
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 1c62caff93fd..ffc84cc7b1c7 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -114,6 +114,7 @@
114#define KEY2_CODE 0x411 114#define KEY2_CODE 0x411
115#define KEY3_CODE 0x412 115#define KEY3_CODE 0x412
116#define KEY4_CODE 0x413 116#define KEY4_CODE 0x413
117#define KEY5_CODE 0x420
117 118
118#define MAX_HOTKEY_RINGBUFFER_SIZE 100 119#define MAX_HOTKEY_RINGBUFFER_SIZE 100
119#define RINGBUFFERSIZE 40 120#define RINGBUFFERSIZE 40
@@ -149,7 +150,7 @@ struct fujitsu_t {
149 char phys[32]; 150 char phys[32];
150 struct backlight_device *bl_device; 151 struct backlight_device *bl_device;
151 struct platform_device *pf_device; 152 struct platform_device *pf_device;
152 int keycode1, keycode2, keycode3, keycode4; 153 int keycode1, keycode2, keycode3, keycode4, keycode5;
153 154
154 unsigned int max_brightness; 155 unsigned int max_brightness;
155 unsigned int brightness_changed; 156 unsigned int brightness_changed;
@@ -823,6 +824,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
823 set_bit(fujitsu->keycode2, input->keybit); 824 set_bit(fujitsu->keycode2, input->keybit);
824 set_bit(fujitsu->keycode3, input->keybit); 825 set_bit(fujitsu->keycode3, input->keybit);
825 set_bit(fujitsu->keycode4, input->keybit); 826 set_bit(fujitsu->keycode4, input->keybit);
827 set_bit(fujitsu->keycode5, input->keybit);
826 set_bit(KEY_UNKNOWN, input->keybit); 828 set_bit(KEY_UNKNOWN, input->keybit);
827 829
828 error = input_register_device(input); 830 error = input_register_device(input);
@@ -962,6 +964,9 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event)
962 case KEY4_CODE: 964 case KEY4_CODE:
963 keycode = fujitsu->keycode4; 965 keycode = fujitsu->keycode4;
964 break; 966 break;
967 case KEY5_CODE:
968 keycode = fujitsu->keycode5;
969 break;
965 case 0: 970 case 0:
966 keycode = 0; 971 keycode = 0;
967 break; 972 break;
@@ -1072,6 +1077,7 @@ static int __init fujitsu_init(void)
1072 fujitsu->keycode2 = KEY_PROG2; 1077 fujitsu->keycode2 = KEY_PROG2;
1073 fujitsu->keycode3 = KEY_PROG3; 1078 fujitsu->keycode3 = KEY_PROG3;
1074 fujitsu->keycode4 = KEY_PROG4; 1079 fujitsu->keycode4 = KEY_PROG4;
1080 fujitsu->keycode5 = KEY_RFKILL;
1075 dmi_check_system(fujitsu_dmi_table); 1081 dmi_check_system(fujitsu_dmi_table);
1076 1082
1077 result = acpi_bus_register_driver(&acpi_fujitsu_driver); 1083 result = acpi_bus_register_driver(&acpi_fujitsu_driver);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index fb4dd7b3ee71..6f145f2d004d 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -157,7 +157,6 @@ static struct platform_device *hp_wmi_platform_dev;
157static struct rfkill *wifi_rfkill; 157static struct rfkill *wifi_rfkill;
158static struct rfkill *bluetooth_rfkill; 158static struct rfkill *bluetooth_rfkill;
159static struct rfkill *wwan_rfkill; 159static struct rfkill *wwan_rfkill;
160static struct rfkill *gps_rfkill;
161 160
162struct rfkill2_device { 161struct rfkill2_device {
163 u8 id; 162 u8 id;
@@ -613,10 +612,6 @@ static void hp_wmi_notify(u32 value, void *context)
613 rfkill_set_states(wwan_rfkill, 612 rfkill_set_states(wwan_rfkill,
614 hp_wmi_get_sw_state(HPWMI_WWAN), 613 hp_wmi_get_sw_state(HPWMI_WWAN),
615 hp_wmi_get_hw_state(HPWMI_WWAN)); 614 hp_wmi_get_hw_state(HPWMI_WWAN));
616 if (gps_rfkill)
617 rfkill_set_states(gps_rfkill,
618 hp_wmi_get_sw_state(HPWMI_GPS),
619 hp_wmi_get_hw_state(HPWMI_GPS));
620 break; 615 break;
621 case HPWMI_CPU_BATTERY_THROTTLE: 616 case HPWMI_CPU_BATTERY_THROTTLE:
622 pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n"); 617 pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
@@ -746,7 +741,7 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device)
746 (void *) HPWMI_BLUETOOTH); 741 (void *) HPWMI_BLUETOOTH);
747 if (!bluetooth_rfkill) { 742 if (!bluetooth_rfkill) {
748 err = -ENOMEM; 743 err = -ENOMEM;
749 goto register_wifi_error; 744 goto register_bluetooth_error;
750 } 745 }
751 rfkill_init_sw_state(bluetooth_rfkill, 746 rfkill_init_sw_state(bluetooth_rfkill,
752 hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); 747 hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
@@ -764,7 +759,7 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device)
764 (void *) HPWMI_WWAN); 759 (void *) HPWMI_WWAN);
765 if (!wwan_rfkill) { 760 if (!wwan_rfkill) {
766 err = -ENOMEM; 761 err = -ENOMEM;
767 goto register_bluetooth_error; 762 goto register_wwan_error;
768 } 763 }
769 rfkill_init_sw_state(wwan_rfkill, 764 rfkill_init_sw_state(wwan_rfkill,
770 hp_wmi_get_sw_state(HPWMI_WWAN)); 765 hp_wmi_get_sw_state(HPWMI_WWAN));
@@ -775,35 +770,13 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device)
775 goto register_wwan_error; 770 goto register_wwan_error;
776 } 771 }
777 772
778 if (wireless & 0x8) {
779 gps_rfkill = rfkill_alloc("hp-gps", &device->dev,
780 RFKILL_TYPE_GPS,
781 &hp_wmi_rfkill_ops,
782 (void *) HPWMI_GPS);
783 if (!gps_rfkill) {
784 err = -ENOMEM;
785 goto register_wwan_error;
786 }
787 rfkill_init_sw_state(gps_rfkill,
788 hp_wmi_get_sw_state(HPWMI_GPS));
789 rfkill_set_hw_state(gps_rfkill,
790 hp_wmi_get_hw_state(HPWMI_GPS));
791 err = rfkill_register(gps_rfkill);
792 if (err)
793 goto register_gps_error;
794 }
795
796 return 0; 773 return 0;
797register_gps_error: 774
798 rfkill_destroy(gps_rfkill);
799 gps_rfkill = NULL;
800 if (bluetooth_rfkill)
801 rfkill_unregister(bluetooth_rfkill);
802register_wwan_error: 775register_wwan_error:
803 rfkill_destroy(wwan_rfkill); 776 rfkill_destroy(wwan_rfkill);
804 wwan_rfkill = NULL; 777 wwan_rfkill = NULL;
805 if (gps_rfkill) 778 if (bluetooth_rfkill)
806 rfkill_unregister(gps_rfkill); 779 rfkill_unregister(bluetooth_rfkill);
807register_bluetooth_error: 780register_bluetooth_error:
808 rfkill_destroy(bluetooth_rfkill); 781 rfkill_destroy(bluetooth_rfkill);
809 bluetooth_rfkill = NULL; 782 bluetooth_rfkill = NULL;
@@ -907,7 +880,6 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
907 wifi_rfkill = NULL; 880 wifi_rfkill = NULL;
908 bluetooth_rfkill = NULL; 881 bluetooth_rfkill = NULL;
909 wwan_rfkill = NULL; 882 wwan_rfkill = NULL;
910 gps_rfkill = NULL;
911 rfkill2_count = 0; 883 rfkill2_count = 0;
912 884
913 if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device)) 885 if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device))
@@ -960,10 +932,6 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
960 rfkill_unregister(wwan_rfkill); 932 rfkill_unregister(wwan_rfkill);
961 rfkill_destroy(wwan_rfkill); 933 rfkill_destroy(wwan_rfkill);
962 } 934 }
963 if (gps_rfkill) {
964 rfkill_unregister(gps_rfkill);
965 rfkill_destroy(gps_rfkill);
966 }
967 935
968 return 0; 936 return 0;
969} 937}
@@ -999,10 +967,6 @@ static int hp_wmi_resume_handler(struct device *device)
999 rfkill_set_states(wwan_rfkill, 967 rfkill_set_states(wwan_rfkill,
1000 hp_wmi_get_sw_state(HPWMI_WWAN), 968 hp_wmi_get_sw_state(HPWMI_WWAN),
1001 hp_wmi_get_hw_state(HPWMI_WWAN)); 969 hp_wmi_get_hw_state(HPWMI_WWAN));
1002 if (gps_rfkill)
1003 rfkill_set_states(gps_rfkill,
1004 hp_wmi_get_sw_state(HPWMI_GPS),
1005 hp_wmi_get_hw_state(HPWMI_GPS));
1006 970
1007 return 0; 971 return 0;
1008} 972}
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index d78ee151c9e4..be3bc2f4edd4 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -865,6 +865,20 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
865 }, 865 },
866 }, 866 },
867 { 867 {
868 .ident = "Lenovo ideapad Y700-15ISK",
869 .matches = {
870 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
871 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ISK"),
872 },
873 },
874 {
875 .ident = "Lenovo ideapad Y700 Touch-15ISK",
876 .matches = {
877 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
878 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700 Touch-15ISK"),
879 },
880 },
881 {
868 .ident = "Lenovo ideapad Y700-17ISK", 882 .ident = "Lenovo ideapad Y700-17ISK",
869 .matches = { 883 .matches = {
870 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 884 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c
index e20f23e04c24..f93abc8c1424 100644
--- a/drivers/platform/x86/intel-hid.c
+++ b/drivers/platform/x86/intel-hid.c
@@ -180,8 +180,7 @@ static int intel_hid_probe(struct platform_device *device)
180 return -ENODEV; 180 return -ENODEV;
181 } 181 }
182 182
183 priv = devm_kzalloc(&device->dev, 183 priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL);
184 sizeof(struct intel_hid_priv *), GFP_KERNEL);
185 if (!priv) 184 if (!priv)
186 return -ENOMEM; 185 return -ENOMEM;
187 dev_set_drvdata(&device->dev, priv); 186 dev_set_drvdata(&device->dev, priv);
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index 092519e37de6..3fb1d85c70a8 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -67,7 +67,8 @@
67/* exported resources from IFWI */ 67/* exported resources from IFWI */
68#define PLAT_RESOURCE_IPC_INDEX 0 68#define PLAT_RESOURCE_IPC_INDEX 0
69#define PLAT_RESOURCE_IPC_SIZE 0x1000 69#define PLAT_RESOURCE_IPC_SIZE 0x1000
70#define PLAT_RESOURCE_GCR_SIZE 0x1000 70#define PLAT_RESOURCE_GCR_OFFSET 0x1008
71#define PLAT_RESOURCE_GCR_SIZE 0x4
71#define PLAT_RESOURCE_BIOS_DATA_INDEX 1 72#define PLAT_RESOURCE_BIOS_DATA_INDEX 1
72#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 73#define PLAT_RESOURCE_BIOS_IFACE_INDEX 2
73#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3 74#define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3
@@ -766,7 +767,7 @@ static int ipc_plat_get_res(struct platform_device *pdev)
766 } 767 }
767 ipcdev.ipc_base = addr; 768 ipcdev.ipc_base = addr;
768 769
769 ipcdev.gcr_base = res->start + size; 770 ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET;
770 ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE; 771 ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE;
771 dev_info(&pdev->dev, "ipc res: %pR\n", res); 772 dev_info(&pdev->dev, "ipc res: %pR\n", res);
772 773
@@ -824,7 +825,8 @@ static int ipc_plat_probe(struct platform_device *pdev)
824 goto err_device; 825 goto err_device;
825 } 826 }
826 827
827 if (request_irq(ipcdev.irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) { 828 if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND,
829 "intel_pmc_ipc", &ipcdev)) {
828 dev_err(&pdev->dev, "Failed to request irq\n"); 830 dev_err(&pdev->dev, "Failed to request irq\n");
829 ret = -EBUSY; 831 ret = -EBUSY;
830 goto err_irq; 832 goto err_irq;
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index f94b730540e2..e81daff65f62 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -24,7 +24,6 @@
24#include <linux/pci.h> 24#include <linux/pci.h>
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/sfi.h> 26#include <linux/sfi.h>
27#include <linux/module.h>
28#include <asm/intel-mid.h> 27#include <asm/intel-mid.h>
29#include <asm/intel_scu_ipc.h> 28#include <asm/intel_scu_ipc.h>
30 29
@@ -611,28 +610,6 @@ static int ipc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
611 return 0; 610 return 0;
612} 611}
613 612
614/**
615 * ipc_remove - remove a bound IPC device
616 * @pdev: PCI device
617 *
618 * In practice the SCU is not removable but this function is also
619 * called for each device on a module unload or cleanup which is the
620 * path that will get used.
621 *
622 * Free up the mappings and release the PCI resources
623 */
624static void ipc_remove(struct pci_dev *pdev)
625{
626 struct intel_scu_ipc_dev *scu = pci_get_drvdata(pdev);
627
628 mutex_lock(&ipclock);
629 scu->dev = NULL;
630 mutex_unlock(&ipclock);
631
632 iounmap(scu->i2c_base);
633 intel_scu_devices_destroy();
634}
635
636static const struct pci_device_id pci_ids[] = { 613static const struct pci_device_id pci_ids[] = {
637 { 614 {
638 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), 615 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT),
@@ -650,17 +627,13 @@ static const struct pci_device_id pci_ids[] = {
650 0, 627 0,
651 } 628 }
652}; 629};
653MODULE_DEVICE_TABLE(pci, pci_ids);
654 630
655static struct pci_driver ipc_driver = { 631static struct pci_driver ipc_driver = {
632 .driver = {
633 .suppress_bind_attrs = true,
634 },
656 .name = "intel_scu_ipc", 635 .name = "intel_scu_ipc",
657 .id_table = pci_ids, 636 .id_table = pci_ids,
658 .probe = ipc_probe, 637 .probe = ipc_probe,
659 .remove = ipc_remove,
660}; 638};
661 639builtin_pci_driver(ipc_driver);
662module_pci_driver(ipc_driver);
663
664MODULE_AUTHOR("Sreedhara DS <sreedhara.ds@intel.com>");
665MODULE_DESCRIPTION("Intel SCU IPC driver");
666MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c
index f97019b0106f..397119f83e82 100644
--- a/drivers/platform/x86/intel_telemetry_pltdrv.c
+++ b/drivers/platform/x86/intel_telemetry_pltdrv.c
@@ -1030,8 +1030,19 @@ static int telemetry_plt_set_trace_verbosity(enum telemetry_unit telem_unit,
1030 switch (telem_unit) { 1030 switch (telem_unit) {
1031 case TELEM_PSS: 1031 case TELEM_PSS:
1032 ret = intel_punit_ipc_command( 1032 ret = intel_punit_ipc_command(
1033 IPC_PUNIT_BIOS_READ_TELE_TRACE_CTRL,
1034 0, 0, NULL, &temp);
1035 if (ret) {
1036 pr_err("PSS TRACE_CTRL Read Failed\n");
1037 goto out;
1038 }
1039
1040 TELEM_CLEAR_VERBOSITY_BITS(temp);
1041 TELEM_SET_VERBOSITY_BITS(temp, verbosity);
1042
1043 ret = intel_punit_ipc_command(
1033 IPC_PUNIT_BIOS_WRITE_TELE_TRACE_CTRL, 1044 IPC_PUNIT_BIOS_WRITE_TELE_TRACE_CTRL,
1034 0, 0, &verbosity, NULL); 1045 0, 0, &temp, NULL);
1035 if (ret) { 1046 if (ret) {
1036 pr_err("PSS TRACE_CTRL Verbosity Set Failed\n"); 1047 pr_err("PSS TRACE_CTRL Verbosity Set Failed\n");
1037 goto out; 1048 goto out;
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index a268a7abf8ab..e305ab541a22 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6653,18 +6653,16 @@ static void __init tpacpi_detect_brightness_capabilities(void)
6653 switch (b) { 6653 switch (b) {
6654 case 16: 6654 case 16:
6655 bright_maxlvl = 15; 6655 bright_maxlvl = 15;
6656 pr_info("detected a 16-level brightness capable ThinkPad\n");
6657 break; 6656 break;
6658 case 8: 6657 case 8:
6659 case 0: 6658 case 0:
6660 bright_maxlvl = 7; 6659 bright_maxlvl = 7;
6661 pr_info("detected a 8-level brightness capable ThinkPad\n");
6662 break; 6660 break;
6663 default: 6661 default:
6664 pr_info("Unsupported brightness interface\n");
6665 tp_features.bright_unkfw = 1; 6662 tp_features.bright_unkfw = 1;
6666 bright_maxlvl = b - 1; 6663 bright_maxlvl = b - 1;
6667 } 6664 }
6665 pr_debug("detected %u brightness levels\n", bright_maxlvl + 1);
6668} 6666}
6669 6667
6670static int __init brightness_init(struct ibm_init_struct *iibm) 6668static int __init brightness_init(struct ibm_init_struct *iibm)
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 73833079bac8..df1f1a76a862 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -36,6 +36,7 @@
36 36
37#include <linux/kernel.h> 37#include <linux/kernel.h>
38#include <linux/module.h> 38#include <linux/module.h>
39#include <linux/moduleparam.h>
39#include <linux/init.h> 40#include <linux/init.h>
40#include <linux/types.h> 41#include <linux/types.h>
41#include <linux/proc_fs.h> 42#include <linux/proc_fs.h>
@@ -117,6 +118,7 @@ MODULE_LICENSE("GPL");
117#define HCI_LCD_BRIGHTNESS 0x002a 118#define HCI_LCD_BRIGHTNESS 0x002a
118#define HCI_WIRELESS 0x0056 119#define HCI_WIRELESS 0x0056
119#define HCI_ACCELEROMETER 0x006d 120#define HCI_ACCELEROMETER 0x006d
121#define HCI_COOLING_METHOD 0x007f
120#define HCI_KBD_ILLUMINATION 0x0095 122#define HCI_KBD_ILLUMINATION 0x0095
121#define HCI_ECO_MODE 0x0097 123#define HCI_ECO_MODE 0x0097
122#define HCI_ACCELEROMETER2 0x00a6 124#define HCI_ACCELEROMETER2 0x00a6
@@ -186,6 +188,7 @@ struct toshiba_acpi_dev {
186 int usbsc_bat_level; 188 int usbsc_bat_level;
187 int usbsc_mode_base; 189 int usbsc_mode_base;
188 int hotkey_event_type; 190 int hotkey_event_type;
191 int max_cooling_method;
189 192
190 unsigned int illumination_supported:1; 193 unsigned int illumination_supported:1;
191 unsigned int video_supported:1; 194 unsigned int video_supported:1;
@@ -205,6 +208,7 @@ struct toshiba_acpi_dev {
205 unsigned int panel_power_on_supported:1; 208 unsigned int panel_power_on_supported:1;
206 unsigned int usb_three_supported:1; 209 unsigned int usb_three_supported:1;
207 unsigned int wwan_supported:1; 210 unsigned int wwan_supported:1;
211 unsigned int cooling_method_supported:1;
208 unsigned int sysfs_created:1; 212 unsigned int sysfs_created:1;
209 unsigned int special_functions; 213 unsigned int special_functions;
210 214
@@ -217,6 +221,10 @@ struct toshiba_acpi_dev {
217 221
218static struct toshiba_acpi_dev *toshiba_acpi; 222static struct toshiba_acpi_dev *toshiba_acpi;
219 223
224static bool disable_hotkeys;
225module_param(disable_hotkeys, bool, 0444);
226MODULE_PARM_DESC(disable_hotkeys, "Disables the hotkeys activation");
227
220static const struct acpi_device_id toshiba_device_ids[] = { 228static const struct acpi_device_id toshiba_device_ids[] = {
221 {"TOS6200", 0}, 229 {"TOS6200", 0},
222 {"TOS6207", 0}, 230 {"TOS6207", 0},
@@ -1194,6 +1202,53 @@ static int toshiba_wwan_set(struct toshiba_acpi_dev *dev, u32 state)
1194 return out[0] == TOS_SUCCESS ? 0 : -EIO; 1202 return out[0] == TOS_SUCCESS ? 0 : -EIO;
1195} 1203}
1196 1204
1205/* Cooling Method */
1206static void toshiba_cooling_method_available(struct toshiba_acpi_dev *dev)
1207{
1208 u32 in[TCI_WORDS] = { HCI_GET, HCI_COOLING_METHOD, 0, 0, 0, 0 };
1209 u32 out[TCI_WORDS];
1210 acpi_status status;
1211
1212 dev->cooling_method_supported = 0;
1213 dev->max_cooling_method = 0;
1214
1215 status = tci_raw(dev, in, out);
1216 if (ACPI_FAILURE(status))
1217 pr_err("ACPI call to get Cooling Method failed\n");
1218
1219 if (out[0] != TOS_SUCCESS && out[0] != TOS_SUCCESS2)
1220 return;
1221
1222 dev->cooling_method_supported = 1;
1223 dev->max_cooling_method = out[3];
1224}
1225
1226static int toshiba_cooling_method_get(struct toshiba_acpi_dev *dev, u32 *state)
1227{
1228 u32 result = hci_read(dev, HCI_COOLING_METHOD, state);
1229
1230 if (result == TOS_FAILURE)
1231 pr_err("ACPI call to get Cooling Method failed\n");
1232
1233 if (result == TOS_NOT_SUPPORTED)
1234 return -ENODEV;
1235
1236 return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO;
1237}
1238
1239static int toshiba_cooling_method_set(struct toshiba_acpi_dev *dev, u32 state)
1240{
1241 u32 result = hci_write(dev, HCI_COOLING_METHOD, state);
1242
1243 if (result == TOS_FAILURE)
1244 pr_err("ACPI call to get Cooling Method failed\n");
1245
1246 if (result == TOS_NOT_SUPPORTED)
1247 return -ENODEV;
1248
1249 return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO;
1250}
1251
1197/* Transflective Backlight */ 1252/* Transflective Backlight */
1198static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 *status) 1253static int get_tr_backlight_status(struct toshiba_acpi_dev *dev, u32 *status)
1199{ 1254{
@@ -2239,6 +2294,54 @@ static ssize_t usb_three_store(struct device *dev,
2239} 2294}
2240static DEVICE_ATTR_RW(usb_three); 2295static DEVICE_ATTR_RW(usb_three);
2241 2296
2297static ssize_t cooling_method_show(struct device *dev,
2298 struct device_attribute *attr, char *buf)
2299{
2300 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2301 int state;
2302 int ret;
2303
2304 ret = toshiba_cooling_method_get(toshiba, &state);
2305 if (ret < 0)
2306 return ret;
2307
2308 return sprintf(buf, "%d %d\n", state, toshiba->max_cooling_method);
2309}
2310
2311static ssize_t cooling_method_store(struct device *dev,
2312 struct device_attribute *attr,
2313 const char *buf, size_t count)
2314{
2315 struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
2316 int state;
2317 int ret;
2318
2319 ret = kstrtoint(buf, 0, &state);
2320 if (ret)
2321 return ret;
2322
2323 /*
2324 * Check for supported values
2325 * Depending on the laptop model, some only support these two:
2326 * 0 - Maximum Performance
2327 * 1 - Battery Optimized
2328 *
2329 * While some others support all three methods:
2330 * 0 - Maximum Performance
2331 * 1 - Performance
2332 * 2 - Battery Optimized
2333 */
2334 if (state < 0 || state > toshiba->max_cooling_method)
2335 return -EINVAL;
2336
2337 ret = toshiba_cooling_method_set(toshiba, state);
2338 if (ret)
2339 return ret;
2340
2341 return count;
2342}
2343static DEVICE_ATTR_RW(cooling_method);
2344
2242static struct attribute *toshiba_attributes[] = { 2345static struct attribute *toshiba_attributes[] = {
2243 &dev_attr_version.attr, 2346 &dev_attr_version.attr,
2244 &dev_attr_fan.attr, 2347 &dev_attr_fan.attr,
@@ -2255,6 +2358,7 @@ static struct attribute *toshiba_attributes[] = {
2255 &dev_attr_kbd_function_keys.attr, 2358 &dev_attr_kbd_function_keys.attr,
2256 &dev_attr_panel_power_on.attr, 2359 &dev_attr_panel_power_on.attr,
2257 &dev_attr_usb_three.attr, 2360 &dev_attr_usb_three.attr,
2361 &dev_attr_cooling_method.attr,
2258 NULL, 2362 NULL,
2259}; 2363};
2260 2364
@@ -2289,6 +2393,8 @@ static umode_t toshiba_sysfs_is_visible(struct kobject *kobj,
2289 exists = (drv->panel_power_on_supported) ? true : false; 2393 exists = (drv->panel_power_on_supported) ? true : false;
2290 else if (attr == &dev_attr_usb_three.attr) 2394 else if (attr == &dev_attr_usb_three.attr)
2291 exists = (drv->usb_three_supported) ? true : false; 2395 exists = (drv->usb_three_supported) ? true : false;
2396 else if (attr == &dev_attr_cooling_method.attr)
2397 exists = (drv->cooling_method_supported) ? true : false;
2292 2398
2293 return exists ? attr->mode : 0; 2399 return exists ? attr->mode : 0;
2294} 2400}
@@ -2591,6 +2697,11 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
2591 acpi_handle ec_handle; 2697 acpi_handle ec_handle;
2592 int error; 2698 int error;
2593 2699
2700 if (disable_hotkeys) {
2701 pr_info("Hotkeys disabled by module parameter\n");
2702 return 0;
2703 }
2704
2594 if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) { 2705 if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) {
2595 pr_info("WMI event detected, hotkeys will not be monitored\n"); 2706 pr_info("WMI event detected, hotkeys will not be monitored\n");
2596 return 0; 2707 return 0;
@@ -2779,6 +2890,8 @@ static void print_supported_features(struct toshiba_acpi_dev *dev)
2779 pr_cont(" usb3"); 2890 pr_cont(" usb3");
2780 if (dev->wwan_supported) 2891 if (dev->wwan_supported)
2781 pr_cont(" wwan"); 2892 pr_cont(" wwan");
2893 if (dev->cooling_method_supported)
2894 pr_cont(" cooling-method");
2782 2895
2783 pr_cont("\n"); 2896 pr_cont("\n");
2784} 2897}
@@ -2963,6 +3076,8 @@ static int toshiba_acpi_add(struct acpi_device *acpi_dev)
2963 if (dev->wwan_supported) 3076 if (dev->wwan_supported)
2964 toshiba_acpi_setup_wwan_rfkill(dev); 3077 toshiba_acpi_setup_wwan_rfkill(dev);
2965 3078
3079 toshiba_cooling_method_available(dev);
3080
2966 print_supported_features(dev); 3081 print_supported_features(dev);
2967 3082
2968 ret = sysfs_create_group(&dev->acpi_dev->dev.kobj, 3083 ret = sysfs_create_group(&dev->acpi_dev->dev.kobj,