aboutsummaryrefslogtreecommitdiffstats
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
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 ...
-rw-r--r--Documentation/ABI/testing/sysfs-driver-toshiba_acpi16
-rw-r--r--drivers/leds/Kconfig1
-rw-r--r--drivers/leds/dell-led.c126
-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
21 files changed, 1026 insertions, 536 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-toshiba_acpi b/Documentation/ABI/testing/sysfs-driver-toshiba_acpi
index eed922ef42e5..f34221b52b14 100644
--- a/Documentation/ABI/testing/sysfs-driver-toshiba_acpi
+++ b/Documentation/ABI/testing/sysfs-driver-toshiba_acpi
@@ -179,3 +179,19 @@ Description: This file controls the USB 3 functionality, valid values are:
179 Note that toggling this value requires a reboot for changes to 179 Note that toggling this value requires a reboot for changes to
180 take effect. 180 take effect.
181Users: KToshiba 181Users: KToshiba
182
183What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/cooling_method
184Date: 2016
185KernelVersion: 4.6
186Contact: Azael Avalos <coproscefalo@gmail.com>
187Description: This file controls the Cooling Method feature.
188 Reading this file prints two values, the first is the actual cooling method
189 and the second is the maximum cooling method supported.
190 When the maximum cooling method is ONE, valid values are:
191 * 0 -> Maximum Performance
192 * 1 -> Battery Optimized
193 When the maximum cooling method is TWO, valid values are:
194 * 0 -> Maximum Performance
195 * 1 -> Performance
196 * 2 -> Battery Optimized
197Users: KToshiba
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 1f6415168998..225147863e02 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -443,6 +443,7 @@ config LEDS_DELL_NETBOOKS
443 tristate "External LED on Dell Business Netbooks" 443 tristate "External LED on Dell Business Netbooks"
444 depends on LEDS_CLASS 444 depends on LEDS_CLASS
445 depends on X86 && ACPI_WMI 445 depends on X86 && ACPI_WMI
446 depends on DELL_SMBIOS
446 help 447 help
447 This adds support for the Latitude 2100 and similar 448 This adds support for the Latitude 2100 and similar
448 notebooks that have an external LED. 449 notebooks that have an external LED.
diff --git a/drivers/leds/dell-led.c b/drivers/leds/dell-led.c
index c36acaf566a6..b3d6e9c15cf9 100644
--- a/drivers/leds/dell-led.c
+++ b/drivers/leds/dell-led.c
@@ -17,6 +17,7 @@
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/dmi.h> 18#include <linux/dmi.h>
19#include <linux/dell-led.h> 19#include <linux/dell-led.h>
20#include "../platform/x86/dell-smbios.h"
20 21
21MODULE_AUTHOR("Louis Davis/Jim Dailey"); 22MODULE_AUTHOR("Louis Davis/Jim Dailey");
22MODULE_DESCRIPTION("Dell LED Control Driver"); 23MODULE_DESCRIPTION("Dell LED Control Driver");
@@ -42,120 +43,32 @@ MODULE_ALIAS("wmi:" DELL_LED_BIOS_GUID);
42#define CMD_LED_OFF 17 43#define CMD_LED_OFF 17
43#define CMD_LED_BLINK 18 44#define CMD_LED_BLINK 18
44 45
45struct app_wmi_args {
46 u16 class;
47 u16 selector;
48 u32 arg1;
49 u32 arg2;
50 u32 arg3;
51 u32 arg4;
52 u32 res1;
53 u32 res2;
54 u32 res3;
55 u32 res4;
56 char dummy[92];
57};
58
59#define GLOBAL_MIC_MUTE_ENABLE 0x364 46#define GLOBAL_MIC_MUTE_ENABLE 0x364
60#define GLOBAL_MIC_MUTE_DISABLE 0x365 47#define GLOBAL_MIC_MUTE_DISABLE 0x365
61 48
62struct dell_bios_data_token {
63 u16 tokenid;
64 u16 location;
65 u16 value;
66};
67
68struct __attribute__ ((__packed__)) dell_bios_calling_interface {
69 struct dmi_header header;
70 u16 cmd_io_addr;
71 u8 cmd_io_code;
72 u32 supported_cmds;
73 struct dell_bios_data_token damap[];
74};
75
76static struct dell_bios_data_token dell_mic_tokens[2];
77
78static int dell_wmi_perform_query(struct app_wmi_args *args)
79{
80 struct app_wmi_args *bios_return;
81 union acpi_object *obj;
82 struct acpi_buffer input;
83 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
84 acpi_status status;
85 u32 rc = -EINVAL;
86
87 input.length = 128;
88 input.pointer = args;
89
90 status = wmi_evaluate_method(DELL_APP_GUID, 0, 1, &input, &output);
91 if (!ACPI_SUCCESS(status))
92 goto err_out0;
93
94 obj = output.pointer;
95 if (!obj)
96 goto err_out0;
97
98 if (obj->type != ACPI_TYPE_BUFFER)
99 goto err_out1;
100
101 bios_return = (struct app_wmi_args *)obj->buffer.pointer;
102 rc = bios_return->res1;
103 if (rc)
104 goto err_out1;
105
106 memcpy(args, bios_return, sizeof(struct app_wmi_args));
107 rc = 0;
108
109 err_out1:
110 kfree(obj);
111 err_out0:
112 return rc;
113}
114
115static void __init find_micmute_tokens(const struct dmi_header *dm, void *dummy)
116{
117 struct dell_bios_calling_interface *calling_interface;
118 struct dell_bios_data_token *token;
119 int token_size = sizeof(struct dell_bios_data_token);
120 int i = 0;
121
122 if (dm->type == 0xda && dm->length > 17) {
123 calling_interface = container_of(dm,
124 struct dell_bios_calling_interface, header);
125
126 token = &calling_interface->damap[i];
127 while (token->tokenid != 0xffff) {
128 if (token->tokenid == GLOBAL_MIC_MUTE_DISABLE)
129 memcpy(&dell_mic_tokens[0], token, token_size);
130 else if (token->tokenid == GLOBAL_MIC_MUTE_ENABLE)
131 memcpy(&dell_mic_tokens[1], token, token_size);
132
133 i++;
134 token = &calling_interface->damap[i];
135 }
136 }
137}
138
139static int dell_micmute_led_set(int state) 49static int dell_micmute_led_set(int state)
140{ 50{
141 struct app_wmi_args args; 51 struct calling_interface_buffer *buffer;
142 struct dell_bios_data_token *token; 52 struct calling_interface_token *token;
143 53
144 if (!wmi_has_guid(DELL_APP_GUID)) 54 if (!wmi_has_guid(DELL_APP_GUID))
145 return -ENODEV; 55 return -ENODEV;
146 56
147 if (state == 0 || state == 1) 57 if (state == 0)
148 token = &dell_mic_tokens[state]; 58 token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE);
59 else if (state == 1)
60 token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE);
149 else 61 else
150 return -EINVAL; 62 return -EINVAL;
151 63
152 memset(&args, 0, sizeof(struct app_wmi_args)); 64 if (!token)
153 65 return -ENODEV;
154 args.class = 1;
155 args.arg1 = token->location;
156 args.arg2 = token->value;
157 66
158 dell_wmi_perform_query(&args); 67 buffer = dell_smbios_get_buffer();
68 buffer->input[0] = token->location;
69 buffer->input[1] = token->value;
70 dell_smbios_send_request(1, 0);
71 dell_smbios_release_buffer();
159 72
160 return state; 73 return state;
161} 74}
@@ -177,14 +90,6 @@ int dell_app_wmi_led_set(int whichled, int on)
177} 90}
178EXPORT_SYMBOL_GPL(dell_app_wmi_led_set); 91EXPORT_SYMBOL_GPL(dell_app_wmi_led_set);
179 92
180static int __init dell_micmute_led_init(void)
181{
182 memset(dell_mic_tokens, 0, sizeof(struct dell_bios_data_token) * 2);
183 dmi_walk(find_micmute_tokens, NULL);
184
185 return 0;
186}
187
188struct bios_args { 93struct bios_args {
189 unsigned char length; 94 unsigned char length;
190 unsigned char result_code; 95 unsigned char result_code;
@@ -330,9 +235,6 @@ static int __init dell_led_init(void)
330 if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID)) 235 if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID))
331 return -ENODEV; 236 return -ENODEV;
332 237
333 if (wmi_has_guid(DELL_APP_GUID))
334 error = dell_micmute_led_init();
335
336 if (wmi_has_guid(DELL_LED_BIOS_GUID)) { 238 if (wmi_has_guid(DELL_LED_BIOS_GUID)) {
337 error = led_off(); 239 error = led_off();
338 if (error != 0) 240 if (error != 0)
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,