Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

+1026 -536
+16
Documentation/ABI/testing/sysfs-driver-toshiba_acpi
··· 179 179 Note that toggling this value requires a reboot for changes to 180 180 take effect. 181 181 Users: KToshiba 182 + 183 + What: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/TOS{1900,620{0,7,8}}:00/cooling_method 184 + Date: 2016 185 + KernelVersion: 4.6 186 + Contact: Azael Avalos <coproscefalo@gmail.com> 187 + Description: 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 197 + Users: KToshiba
+1
drivers/leds/Kconfig
··· 443 443 tristate "External LED on Dell Business Netbooks" 444 444 depends on LEDS_CLASS 445 445 depends on X86 && ACPI_WMI 446 + depends on DELL_SMBIOS 446 447 help 447 448 This adds support for the Latitude 2100 and similar 448 449 notebooks that have an external LED.
+14 -112
drivers/leds/dell-led.c
··· 17 17 #include <linux/module.h> 18 18 #include <linux/dmi.h> 19 19 #include <linux/dell-led.h> 20 + #include "../platform/x86/dell-smbios.h" 20 21 21 22 MODULE_AUTHOR("Louis Davis/Jim Dailey"); 22 23 MODULE_DESCRIPTION("Dell LED Control Driver"); ··· 43 42 #define CMD_LED_OFF 17 44 43 #define CMD_LED_BLINK 18 45 44 46 - struct app_wmi_args { 47 - u16 class; 48 - u16 selector; 49 - u32 arg1; 50 - u32 arg2; 51 - u32 arg3; 52 - u32 arg4; 53 - u32 res1; 54 - u32 res2; 55 - u32 res3; 56 - u32 res4; 57 - char dummy[92]; 58 - }; 59 - 60 45 #define GLOBAL_MIC_MUTE_ENABLE 0x364 61 46 #define GLOBAL_MIC_MUTE_DISABLE 0x365 62 47 63 - struct dell_bios_data_token { 64 - u16 tokenid; 65 - u16 location; 66 - u16 value; 67 - }; 68 - 69 - struct __attribute__ ((__packed__)) dell_bios_calling_interface { 70 - struct dmi_header header; 71 - u16 cmd_io_addr; 72 - u8 cmd_io_code; 73 - u32 supported_cmds; 74 - struct dell_bios_data_token damap[]; 75 - }; 76 - 77 - static struct dell_bios_data_token dell_mic_tokens[2]; 78 - 79 - static int dell_wmi_perform_query(struct app_wmi_args *args) 80 - { 81 - struct app_wmi_args *bios_return; 82 - union acpi_object *obj; 83 - struct acpi_buffer input; 84 - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; 85 - acpi_status status; 86 - u32 rc = -EINVAL; 87 - 88 - input.length = 128; 89 - input.pointer = args; 90 - 91 - status = wmi_evaluate_method(DELL_APP_GUID, 0, 1, &input, &output); 92 - if (!ACPI_SUCCESS(status)) 93 - goto err_out0; 94 - 95 - obj = output.pointer; 96 - if (!obj) 97 - goto err_out0; 98 - 99 - if (obj->type != ACPI_TYPE_BUFFER) 100 - goto err_out1; 101 - 102 - bios_return = (struct app_wmi_args *)obj->buffer.pointer; 103 - rc = bios_return->res1; 104 - if (rc) 105 - goto err_out1; 106 - 107 - memcpy(args, bios_return, sizeof(struct app_wmi_args)); 108 - rc = 0; 109 - 110 - err_out1: 111 - kfree(obj); 112 - err_out0: 113 - return rc; 114 - } 115 - 116 - static void __init find_micmute_tokens(const struct dmi_header *dm, void *dummy) 117 - { 118 - struct dell_bios_calling_interface *calling_interface; 119 - struct dell_bios_data_token *token; 120 - int token_size = sizeof(struct dell_bios_data_token); 121 - int i = 0; 122 - 123 - if (dm->type == 0xda && dm->length > 17) { 124 - calling_interface = container_of(dm, 125 - struct dell_bios_calling_interface, header); 126 - 127 - token = &calling_interface->damap[i]; 128 - while (token->tokenid != 0xffff) { 129 - if (token->tokenid == GLOBAL_MIC_MUTE_DISABLE) 130 - memcpy(&dell_mic_tokens[0], token, token_size); 131 - else if (token->tokenid == GLOBAL_MIC_MUTE_ENABLE) 132 - memcpy(&dell_mic_tokens[1], token, token_size); 133 - 134 - i++; 135 - token = &calling_interface->damap[i]; 136 - } 137 - } 138 - } 139 - 140 48 static int dell_micmute_led_set(int state) 141 49 { 142 - struct app_wmi_args args; 143 - struct dell_bios_data_token *token; 50 + struct calling_interface_buffer *buffer; 51 + struct calling_interface_token *token; 144 52 145 53 if (!wmi_has_guid(DELL_APP_GUID)) 146 54 return -ENODEV; 147 55 148 - if (state == 0 || state == 1) 149 - token = &dell_mic_tokens[state]; 56 + if (state == 0) 57 + token = dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE); 58 + else if (state == 1) 59 + token = dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE); 150 60 else 151 61 return -EINVAL; 152 62 153 - memset(&args, 0, sizeof(struct app_wmi_args)); 63 + if (!token) 64 + return -ENODEV; 154 65 155 - args.class = 1; 156 - args.arg1 = token->location; 157 - args.arg2 = token->value; 158 - 159 - dell_wmi_perform_query(&args); 66 + buffer = dell_smbios_get_buffer(); 67 + buffer->input[0] = token->location; 68 + buffer->input[1] = token->value; 69 + dell_smbios_send_request(1, 0); 70 + dell_smbios_release_buffer(); 160 71 161 72 return state; 162 73 } ··· 89 176 return state; 90 177 } 91 178 EXPORT_SYMBOL_GPL(dell_app_wmi_led_set); 92 - 93 - static int __init dell_micmute_led_init(void) 94 - { 95 - memset(dell_mic_tokens, 0, sizeof(struct dell_bios_data_token) * 2); 96 - dmi_walk(find_micmute_tokens, NULL); 97 - 98 - return 0; 99 - } 100 179 101 180 struct bios_args { 102 181 unsigned char length; ··· 234 329 235 330 if (!wmi_has_guid(DELL_LED_BIOS_GUID) && !wmi_has_guid(DELL_APP_GUID)) 236 331 return -ENODEV; 237 - 238 - if (wmi_has_guid(DELL_APP_GUID)) 239 - error = dell_micmute_led_init(); 240 332 241 333 if (wmi_has_guid(DELL_LED_BIOS_GUID)) { 242 334 error = led_off();
+14 -1
drivers/platform/x86/Kconfig
··· 91 91 92 92 If you have an ACPI-compatible ASUS laptop, say Y or M here. 93 93 94 + config 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 + 94 104 config DELL_LAPTOP 95 105 tristate "Dell Laptop Extras" 96 106 depends on X86 97 - depends on DCDBAS 107 + depends on DELL_SMBIOS 108 + depends on DMI 98 109 depends on BACKLIGHT_CLASS_DEVICE 99 110 depends on ACPI_VIDEO || ACPI_VIDEO = n 100 111 depends on RFKILL || RFKILL = n ··· 121 110 config DELL_WMI 122 111 tristate "Dell WMI extras" 123 112 depends on ACPI_WMI 113 + depends on DMI 124 114 depends on INPUT 125 115 depends on ACPI_VIDEO || ACPI_VIDEO = n 116 + depends on DELL_SMBIOS 126 117 select INPUT_SPARSEKMAP 127 118 ---help--- 128 119 Say Y here if you want to support WMI-based hotkeys on Dell laptops.
+1
drivers/platform/x86/Makefile
··· 11 11 obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o 12 12 obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o 13 13 obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o 14 + obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o 14 15 obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o 15 16 obj-$(CONFIG_DELL_WMI) += dell-wmi.o 16 17 obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
+246 -40
drivers/platform/x86/alienware-wmi.c
··· 33 33 #define WMAX_METHOD_BRIGHTNESS 0x3 34 34 #define WMAX_METHOD_ZONE_CONTROL 0x4 35 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 37 40 MODULE_AUTHOR("Mario Limonciello <mario_limonciello@dell.com>"); 38 41 MODULE_DESCRIPTION("Alienware special feature control"); ··· 63 60 struct quirk_entry { 64 61 u8 num_zones; 65 62 u8 hdmi_mux; 63 + u8 amplifier; 64 + u8 deepslp; 66 65 }; 67 66 68 67 static struct quirk_entry *quirks; ··· 72 67 static struct quirk_entry quirk_unknown = { 73 68 .num_zones = 2, 74 69 .hdmi_mux = 0, 70 + .amplifier = 0, 71 + .deepslp = 0, 75 72 }; 76 73 77 - static struct quirk_entry quirk_x51_family = { 74 + static struct quirk_entry quirk_x51_r1_r2 = { 78 75 .num_zones = 3, 79 - .hdmi_mux = 0. 76 + .hdmi_mux = 0, 77 + .amplifier = 0, 78 + .deepslp = 0, 79 + }; 80 + 81 + static struct quirk_entry quirk_x51_r3 = { 82 + .num_zones = 4, 83 + .hdmi_mux = 0, 84 + .amplifier = 1, 85 + .deepslp = 0, 80 86 }; 81 87 82 88 static struct quirk_entry quirk_asm100 = { 83 89 .num_zones = 2, 84 90 .hdmi_mux = 1, 91 + .amplifier = 0, 92 + .deepslp = 0, 93 + }; 94 + 95 + static struct quirk_entry quirk_asm200 = { 96 + .num_zones = 2, 97 + .hdmi_mux = 1, 98 + .amplifier = 0, 99 + .deepslp = 1, 100 + }; 101 + 102 + static struct quirk_entry quirk_asm201 = { 103 + .num_zones = 2, 104 + .hdmi_mux = 1, 105 + .amplifier = 1, 106 + .deepslp = 1, 85 107 }; 86 108 87 109 static int __init dmi_matched(const struct dmi_system_id *dmi) ··· 120 88 static const struct dmi_system_id alienware_quirks[] __initconst = { 121 89 { 122 90 .callback = dmi_matched, 123 - .ident = "Alienware X51 R1", 91 + .ident = "Alienware X51 R3", 124 92 .matches = { 125 93 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 126 - DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), 94 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R3"), 127 95 }, 128 - .driver_data = &quirk_x51_family, 96 + .driver_data = &quirk_x51_r3, 129 97 }, 130 98 { 131 99 .callback = dmi_matched, ··· 134 102 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 135 103 DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51 R2"), 136 104 }, 137 - .driver_data = &quirk_x51_family, 105 + .driver_data = &quirk_x51_r1_r2, 138 106 }, 139 107 { 140 - .callback = dmi_matched, 141 - .ident = "Alienware ASM100", 142 - .matches = { 143 - DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 144 - DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), 145 - }, 146 - .driver_data = &quirk_asm100, 147 - }, 108 + .callback = dmi_matched, 109 + .ident = "Alienware X51 R1", 110 + .matches = { 111 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 112 + DMI_MATCH(DMI_PRODUCT_NAME, "Alienware X51"), 113 + }, 114 + .driver_data = &quirk_x51_r1_r2, 115 + }, 116 + { 117 + .callback = dmi_matched, 118 + .ident = "Alienware ASM100", 119 + .matches = { 120 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 121 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM100"), 122 + }, 123 + .driver_data = &quirk_asm100, 124 + }, 125 + { 126 + .callback = dmi_matched, 127 + .ident = "Alienware ASM200", 128 + .matches = { 129 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 130 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM200"), 131 + }, 132 + .driver_data = &quirk_asm200, 133 + }, 134 + { 135 + .callback = dmi_matched, 136 + .ident = "Alienware ASM201", 137 + .matches = { 138 + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 139 + DMI_MATCH(DMI_PRODUCT_NAME, "ASM201"), 140 + }, 141 + .driver_data = &quirk_asm201, 142 + }, 148 143 {} 149 144 }; 150 145 ··· 192 133 u32 percentage; 193 134 }; 194 135 195 - struct hdmi_args { 136 + struct wmax_basic_args { 196 137 u8 arg; 197 138 }; 198 139 ··· 229 170 230 171 /* 231 172 * Helpers used for zone control 232 - */ 173 + */ 233 174 static int parse_rgb(const char *buf, struct platform_zone *zone) 234 175 { 235 176 long unsigned int rgb; ··· 269 210 270 211 /* 271 212 * Individual RGB zone control 272 - */ 213 + */ 273 214 static int alienware_update_led(struct platform_zone *zone) 274 215 { 275 216 int method_id; ··· 277 218 char *guid; 278 219 struct acpi_buffer input; 279 220 struct legacy_led_args legacy_args; 280 - struct wmax_led_args wmax_args; 221 + struct wmax_led_args wmax_basic_args; 281 222 if (interface == WMAX) { 282 - wmax_args.led_mask = 1 << zone->location; 283 - wmax_args.colors = zone->colors; 284 - wmax_args.state = lighting_control_state; 223 + wmax_basic_args.led_mask = 1 << zone->location; 224 + wmax_basic_args.colors = zone->colors; 225 + wmax_basic_args.state = lighting_control_state; 285 226 guid = WMAX_CONTROL_GUID; 286 227 method_id = WMAX_METHOD_ZONE_CONTROL; 287 228 288 - input.length = (acpi_size) sizeof(wmax_args); 289 - input.pointer = &wmax_args; 229 + input.length = (acpi_size) sizeof(wmax_basic_args); 230 + input.pointer = &wmax_basic_args; 290 231 } else { 291 232 legacy_args.colors = zone->colors; 292 233 legacy_args.brightness = global_brightness; ··· 342 283 343 284 /* 344 285 * LED Brightness (Global) 345 - */ 286 + */ 346 287 static int wmax_brightness(int brightness) 347 288 { 348 289 acpi_status status; ··· 386 327 387 328 /* 388 329 * Lighting control state device attribute (Global) 389 - */ 330 + */ 390 331 static ssize_t show_control_state(struct device *dev, 391 332 struct device_attribute *attr, char *buf) 392 333 { ··· 494 435 kfree(zone_attrs); 495 436 } 496 437 497 - /* 498 - The HDMI mux sysfs node indicates the status of the HDMI input mux. 499 - It can toggle between standard system GPU output and HDMI input. 500 - */ 501 - static acpi_status alienware_hdmi_command(struct hdmi_args *in_args, 438 + static acpi_status alienware_wmax_command(struct wmax_basic_args *in_args, 502 439 u32 command, int *out_data) 503 440 { 504 441 acpi_status status; ··· 522 467 523 468 } 524 469 470 + /* 471 + * The HDMI mux sysfs node indicates the status of the HDMI input mux. 472 + * It can toggle between standard system GPU output and HDMI input. 473 + */ 525 474 static ssize_t show_hdmi_cable(struct device *dev, 526 475 struct device_attribute *attr, char *buf) 527 476 { 528 477 acpi_status status; 529 478 u32 out_data; 530 - struct hdmi_args in_args = { 479 + struct wmax_basic_args in_args = { 531 480 .arg = 0, 532 481 }; 533 482 status = 534 - alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_CABLE, 483 + alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_CABLE, 535 484 (u32 *) &out_data); 536 485 if (ACPI_SUCCESS(status)) { 537 486 if (out_data == 0) ··· 554 495 { 555 496 acpi_status status; 556 497 u32 out_data; 557 - struct hdmi_args in_args = { 498 + struct wmax_basic_args in_args = { 558 499 .arg = 0, 559 500 }; 560 501 status = 561 - alienware_hdmi_command(&in_args, WMAX_METHOD_HDMI_STATUS, 502 + alienware_wmax_command(&in_args, WMAX_METHOD_HDMI_STATUS, 562 503 (u32 *) &out_data); 563 504 564 505 if (ACPI_SUCCESS(status)) { ··· 578 519 const char *buf, size_t count) 579 520 { 580 521 acpi_status status; 581 - struct hdmi_args args; 522 + struct wmax_basic_args args; 582 523 if (strcmp(buf, "gpu\n") == 0) 583 524 args.arg = 1; 584 525 else if (strcmp(buf, "input\n") == 0) ··· 587 528 args.arg = 3; 588 529 pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf); 589 530 590 - status = alienware_hdmi_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); 531 + status = alienware_wmax_command(&args, WMAX_METHOD_HDMI_SOURCE, NULL); 591 532 592 533 if (ACPI_FAILURE(status)) 593 534 pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ··· 622 563 623 564 ret = sysfs_create_group(&dev->dev.kobj, &hdmi_attribute_group); 624 565 if (ret) 625 - goto error_create_hdmi; 626 - return 0; 566 + remove_hdmi(dev); 567 + return ret; 568 + } 627 569 628 - error_create_hdmi: 629 - remove_hdmi(dev); 570 + /* 571 + * Alienware GFX amplifier support 572 + * - Currently supports reading cable status 573 + * - Leaving expansion room to possibly support dock/undock events later 574 + */ 575 + static ssize_t show_amplifier_status(struct device *dev, 576 + struct device_attribute *attr, char *buf) 577 + { 578 + acpi_status status; 579 + u32 out_data; 580 + struct wmax_basic_args in_args = { 581 + .arg = 0, 582 + }; 583 + status = 584 + alienware_wmax_command(&in_args, WMAX_METHOD_AMPLIFIER_CABLE, 585 + (u32 *) &out_data); 586 + if (ACPI_SUCCESS(status)) { 587 + if (out_data == 0) 588 + return scnprintf(buf, PAGE_SIZE, 589 + "[unconnected] connected unknown\n"); 590 + else if (out_data == 1) 591 + return scnprintf(buf, PAGE_SIZE, 592 + "unconnected [connected] unknown\n"); 593 + } 594 + pr_err("alienware-wmi: unknown amplifier cable status: %d\n", status); 595 + return scnprintf(buf, PAGE_SIZE, "unconnected connected [unknown]\n"); 596 + } 597 + 598 + static DEVICE_ATTR(status, S_IRUGO, show_amplifier_status, NULL); 599 + 600 + static struct attribute *amplifier_attrs[] = { 601 + &dev_attr_status.attr, 602 + NULL, 603 + }; 604 + 605 + static struct attribute_group amplifier_attribute_group = { 606 + .name = "amplifier", 607 + .attrs = amplifier_attrs, 608 + }; 609 + 610 + static void remove_amplifier(struct platform_device *dev) 611 + { 612 + if (quirks->amplifier > 0) 613 + sysfs_remove_group(&dev->dev.kobj, &amplifier_attribute_group); 614 + } 615 + 616 + static int create_amplifier(struct platform_device *dev) 617 + { 618 + int ret; 619 + 620 + ret = sysfs_create_group(&dev->dev.kobj, &amplifier_attribute_group); 621 + if (ret) 622 + remove_amplifier(dev); 623 + return ret; 624 + } 625 + 626 + /* 627 + * Deep Sleep Control support 628 + * - Modifies BIOS setting for deep sleep control allowing extra wakeup events 629 + */ 630 + static ssize_t show_deepsleep_status(struct device *dev, 631 + struct device_attribute *attr, char *buf) 632 + { 633 + acpi_status status; 634 + u32 out_data; 635 + struct wmax_basic_args in_args = { 636 + .arg = 0, 637 + }; 638 + status = alienware_wmax_command(&in_args, WMAX_METHOD_DEEP_SLEEP_STATUS, 639 + (u32 *) &out_data); 640 + if (ACPI_SUCCESS(status)) { 641 + if (out_data == 0) 642 + return scnprintf(buf, PAGE_SIZE, 643 + "[disabled] s5 s5_s4\n"); 644 + else if (out_data == 1) 645 + return scnprintf(buf, PAGE_SIZE, 646 + "disabled [s5] s5_s4\n"); 647 + else if (out_data == 2) 648 + return scnprintf(buf, PAGE_SIZE, 649 + "disabled s5 [s5_s4]\n"); 650 + } 651 + pr_err("alienware-wmi: unknown deep sleep status: %d\n", status); 652 + return scnprintf(buf, PAGE_SIZE, "disabled s5 s5_s4 [unknown]\n"); 653 + } 654 + 655 + static ssize_t toggle_deepsleep(struct device *dev, 656 + struct device_attribute *attr, 657 + const char *buf, size_t count) 658 + { 659 + acpi_status status; 660 + struct wmax_basic_args args; 661 + 662 + if (strcmp(buf, "disabled\n") == 0) 663 + args.arg = 0; 664 + else if (strcmp(buf, "s5\n") == 0) 665 + args.arg = 1; 666 + else 667 + args.arg = 2; 668 + pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf); 669 + 670 + status = alienware_wmax_command(&args, WMAX_METHOD_DEEP_SLEEP_CONTROL, 671 + NULL); 672 + 673 + if (ACPI_FAILURE(status)) 674 + pr_err("alienware-wmi: deep sleep control failed: results: %u\n", 675 + status); 676 + return count; 677 + } 678 + 679 + static DEVICE_ATTR(deepsleep, S_IRUGO | S_IWUSR, show_deepsleep_status, toggle_deepsleep); 680 + 681 + static struct attribute *deepsleep_attrs[] = { 682 + &dev_attr_deepsleep.attr, 683 + NULL, 684 + }; 685 + 686 + static struct attribute_group deepsleep_attribute_group = { 687 + .name = "deepsleep", 688 + .attrs = deepsleep_attrs, 689 + }; 690 + 691 + static void remove_deepsleep(struct platform_device *dev) 692 + { 693 + if (quirks->deepslp > 0) 694 + sysfs_remove_group(&dev->dev.kobj, &deepsleep_attribute_group); 695 + } 696 + 697 + static int create_deepsleep(struct platform_device *dev) 698 + { 699 + int ret; 700 + 701 + ret = sysfs_create_group(&dev->dev.kobj, &deepsleep_attribute_group); 702 + if (ret) 703 + remove_deepsleep(dev); 630 704 return ret; 631 705 } 632 706 ··· 798 606 goto fail_prep_hdmi; 799 607 } 800 608 609 + if (quirks->amplifier > 0) { 610 + ret = create_amplifier(platform_device); 611 + if (ret) 612 + goto fail_prep_amplifier; 613 + } 614 + 615 + if (quirks->deepslp > 0) { 616 + ret = create_deepsleep(platform_device); 617 + if (ret) 618 + goto fail_prep_deepsleep; 619 + } 620 + 801 621 ret = alienware_zone_init(platform_device); 802 622 if (ret) 803 623 goto fail_prep_zones; ··· 818 614 819 615 fail_prep_zones: 820 616 alienware_zone_exit(platform_device); 617 + fail_prep_deepsleep: 618 + fail_prep_amplifier: 821 619 fail_prep_hdmi: 822 620 platform_device_del(platform_device); 823 621 fail_platform_device2:
+9
drivers/platform/x86/asus-nb-wmi.c
··· 272 272 }, 273 273 { 274 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 284 .ident = "ASUSTeK COMPUTER INC. 1015E", 276 285 .matches = { 277 286 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+105 -265
drivers/platform/x86/dell-laptop.c
··· 28 28 #include <linux/acpi.h> 29 29 #include <linux/mm.h> 30 30 #include <linux/i8042.h> 31 - #include <linux/slab.h> 32 31 #include <linux/debugfs.h> 33 32 #include <linux/seq_file.h> 34 33 #include <acpi/video.h> 35 - #include "../../firmware/dcdbas.h" 36 34 #include "dell-rbtn.h" 35 + #include "dell-smbios.h" 37 36 38 37 #define BRIGHTNESS_TOKEN 0x7d 39 38 #define KBD_LED_OFF_TOKEN 0x01E1 ··· 42 43 #define KBD_LED_AUTO_50_TOKEN 0x02EB 43 44 #define KBD_LED_AUTO_75_TOKEN 0x02EC 44 45 #define KBD_LED_AUTO_100_TOKEN 0x02F6 45 - 46 - /* This structure will be modified by the firmware when we enter 47 - * system management mode, hence the volatiles */ 48 - 49 - struct calling_interface_buffer { 50 - u16 class; 51 - u16 select; 52 - volatile u32 input[4]; 53 - volatile u32 output[4]; 54 - } __packed; 55 - 56 - struct calling_interface_token { 57 - u16 tokenID; 58 - u16 location; 59 - union { 60 - u16 value; 61 - u16 stringlength; 62 - }; 63 - }; 64 - 65 - struct calling_interface_structure { 66 - struct dmi_header header; 67 - u16 cmdIOAddress; 68 - u8 cmdIOCode; 69 - u32 supportedCmds; 70 - struct calling_interface_token tokens[]; 71 - } __packed; 72 46 73 47 struct quirk_entry { 74 48 u8 touchpad_led; ··· 74 102 .needs_kbd_timeouts = 1, 75 103 .kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 }, 76 104 }; 77 - 78 - static int da_command_address; 79 - static int da_command_code; 80 - static int da_num_tokens; 81 - static struct calling_interface_token *da_tokens; 82 105 83 106 static struct platform_driver platform_driver = { 84 107 .driver = { ··· 273 306 { } 274 307 }; 275 308 276 - static struct calling_interface_buffer *buffer; 277 - static DEFINE_MUTEX(buffer_mutex); 278 - 279 - static void clear_buffer(void) 280 - { 281 - memset(buffer, 0, sizeof(struct calling_interface_buffer)); 282 - } 283 - 284 - static void get_buffer(void) 285 - { 286 - mutex_lock(&buffer_mutex); 287 - clear_buffer(); 288 - } 289 - 290 - static void release_buffer(void) 291 - { 292 - mutex_unlock(&buffer_mutex); 293 - } 294 - 295 - static void __init parse_da_table(const struct dmi_header *dm) 296 - { 297 - /* Final token is a terminator, so we don't want to copy it */ 298 - int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; 299 - struct calling_interface_token *new_da_tokens; 300 - struct calling_interface_structure *table = 301 - container_of(dm, struct calling_interface_structure, header); 302 - 303 - /* 4 bytes of table header, plus 7 bytes of Dell header, plus at least 304 - 6 bytes of entry */ 305 - 306 - if (dm->length < 17) 307 - return; 308 - 309 - da_command_address = table->cmdIOAddress; 310 - da_command_code = table->cmdIOCode; 311 - 312 - new_da_tokens = krealloc(da_tokens, (da_num_tokens + tokens) * 313 - sizeof(struct calling_interface_token), 314 - GFP_KERNEL); 315 - 316 - if (!new_da_tokens) 317 - return; 318 - da_tokens = new_da_tokens; 319 - 320 - memcpy(da_tokens+da_num_tokens, table->tokens, 321 - sizeof(struct calling_interface_token) * tokens); 322 - 323 - da_num_tokens += tokens; 324 - } 325 - 326 - static void __init find_tokens(const struct dmi_header *dm, void *dummy) 327 - { 328 - switch (dm->type) { 329 - case 0xd4: /* Indexed IO */ 330 - case 0xd5: /* Protected Area Type 1 */ 331 - case 0xd6: /* Protected Area Type 2 */ 332 - break; 333 - case 0xda: /* Calling interface */ 334 - parse_da_table(dm); 335 - break; 336 - } 337 - } 338 - 339 - static int find_token_id(int tokenid) 340 - { 341 - int i; 342 - 343 - for (i = 0; i < da_num_tokens; i++) { 344 - if (da_tokens[i].tokenID == tokenid) 345 - return i; 346 - } 347 - 348 - return -1; 349 - } 350 - 351 - static int find_token_location(int tokenid) 352 - { 353 - int id; 354 - 355 - id = find_token_id(tokenid); 356 - if (id == -1) 357 - return -1; 358 - 359 - return da_tokens[id].location; 360 - } 361 - 362 - static struct calling_interface_buffer * 363 - dell_send_request(struct calling_interface_buffer *buffer, int class, 364 - int select) 365 - { 366 - struct smi_cmd command; 367 - 368 - command.magic = SMI_CMD_MAGIC; 369 - command.command_address = da_command_address; 370 - command.command_code = da_command_code; 371 - command.ebx = virt_to_phys(buffer); 372 - command.ecx = 0x42534931; 373 - 374 - buffer->class = class; 375 - buffer->select = select; 376 - 377 - dcdbas_smi_request(&command); 378 - 379 - return buffer; 380 - } 381 - 382 - static inline int dell_smi_error(int value) 383 - { 384 - switch (value) { 385 - case 0: /* Completed successfully */ 386 - return 0; 387 - case -1: /* Completed with error */ 388 - return -EIO; 389 - case -2: /* Function not supported */ 390 - return -ENXIO; 391 - default: /* Unknown error */ 392 - return -EINVAL; 393 - } 394 - } 395 - 396 309 /* 397 310 * Derived from information in smbios-wireless-ctl: 398 311 * ··· 395 548 396 549 static int dell_rfkill_set(void *data, bool blocked) 397 550 { 551 + struct calling_interface_buffer *buffer; 398 552 int disable = blocked ? 1 : 0; 399 553 unsigned long radio = (unsigned long)data; 400 554 int hwswitch_bit = (unsigned long)data - 1; ··· 403 555 int status; 404 556 int ret; 405 557 406 - get_buffer(); 558 + buffer = dell_smbios_get_buffer(); 407 559 408 - dell_send_request(buffer, 17, 11); 560 + dell_smbios_send_request(17, 11); 409 561 ret = buffer->output[0]; 410 562 status = buffer->output[1]; 411 563 412 564 if (ret != 0) 413 565 goto out; 414 566 415 - clear_buffer(); 567 + dell_smbios_clear_buffer(); 416 568 417 569 buffer->input[0] = 0x2; 418 - dell_send_request(buffer, 17, 11); 570 + dell_smbios_send_request(17, 11); 419 571 ret = buffer->output[0]; 420 572 hwswitch = buffer->output[1]; 421 573 ··· 425 577 (status & BIT(0)) && !(status & BIT(16))) 426 578 disable = 1; 427 579 428 - clear_buffer(); 580 + dell_smbios_clear_buffer(); 429 581 430 582 buffer->input[0] = (1 | (radio<<8) | (disable << 16)); 431 - dell_send_request(buffer, 17, 11); 583 + dell_smbios_send_request(17, 11); 432 584 ret = buffer->output[0]; 433 585 434 586 out: 435 - release_buffer(); 436 - return dell_smi_error(ret); 587 + dell_smbios_release_buffer(); 588 + return dell_smbios_error(ret); 437 589 } 438 590 439 591 /* Must be called with the buffer held */ 440 592 static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio, 441 - int status) 593 + int status, 594 + struct calling_interface_buffer *buffer) 442 595 { 443 596 if (status & BIT(0)) { 444 597 /* Has hw-switch, sync sw_state to BIOS */ 445 598 int block = rfkill_blocked(rfkill); 446 - clear_buffer(); 599 + dell_smbios_clear_buffer(); 447 600 buffer->input[0] = (1 | (radio << 8) | (block << 16)); 448 - dell_send_request(buffer, 17, 11); 601 + dell_smbios_send_request(17, 11); 449 602 } else { 450 603 /* No hw-switch, sync BIOS state to sw_state */ 451 604 rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16))); ··· 462 613 463 614 static void dell_rfkill_query(struct rfkill *rfkill, void *data) 464 615 { 616 + struct calling_interface_buffer *buffer; 465 617 int radio = ((unsigned long)data & 0xF); 466 618 int hwswitch; 467 619 int status; 468 620 int ret; 469 621 470 - get_buffer(); 622 + buffer = dell_smbios_get_buffer(); 471 623 472 - dell_send_request(buffer, 17, 11); 624 + dell_smbios_send_request(17, 11); 473 625 ret = buffer->output[0]; 474 626 status = buffer->output[1]; 475 627 476 628 if (ret != 0 || !(status & BIT(0))) { 477 - release_buffer(); 629 + dell_smbios_release_buffer(); 478 630 return; 479 631 } 480 632 481 - clear_buffer(); 633 + dell_smbios_clear_buffer(); 482 634 483 635 buffer->input[0] = 0x2; 484 - dell_send_request(buffer, 17, 11); 636 + dell_smbios_send_request(17, 11); 485 637 ret = buffer->output[0]; 486 638 hwswitch = buffer->output[1]; 487 639 488 - release_buffer(); 640 + dell_smbios_release_buffer(); 489 641 490 642 if (ret != 0) 491 643 return; ··· 503 653 504 654 static int dell_debugfs_show(struct seq_file *s, void *data) 505 655 { 656 + struct calling_interface_buffer *buffer; 506 657 int hwswitch_state; 507 658 int hwswitch_ret; 508 659 int status; 509 660 int ret; 510 661 511 - get_buffer(); 662 + buffer = dell_smbios_get_buffer(); 512 663 513 - dell_send_request(buffer, 17, 11); 664 + dell_smbios_send_request(17, 11); 514 665 ret = buffer->output[0]; 515 666 status = buffer->output[1]; 516 667 517 - clear_buffer(); 668 + dell_smbios_clear_buffer(); 518 669 519 670 buffer->input[0] = 0x2; 520 - dell_send_request(buffer, 17, 11); 671 + dell_smbios_send_request(17, 11); 521 672 hwswitch_ret = buffer->output[0]; 522 673 hwswitch_state = buffer->output[1]; 523 674 524 - release_buffer(); 675 + dell_smbios_release_buffer(); 525 676 526 677 seq_printf(s, "return:\t%d\n", ret); 527 678 seq_printf(s, "status:\t0x%X\n", status); ··· 603 752 604 753 static void dell_update_rfkill(struct work_struct *ignored) 605 754 { 755 + struct calling_interface_buffer *buffer; 606 756 int hwswitch = 0; 607 757 int status; 608 758 int ret; 609 759 610 - get_buffer(); 760 + buffer = dell_smbios_get_buffer(); 611 761 612 - dell_send_request(buffer, 17, 11); 762 + dell_smbios_send_request(17, 11); 613 763 ret = buffer->output[0]; 614 764 status = buffer->output[1]; 615 765 616 766 if (ret != 0) 617 767 goto out; 618 768 619 - clear_buffer(); 769 + dell_smbios_clear_buffer(); 620 770 621 771 buffer->input[0] = 0x2; 622 - dell_send_request(buffer, 17, 11); 772 + dell_smbios_send_request(17, 11); 623 773 ret = buffer->output[0]; 624 774 625 775 if (ret == 0 && (status & BIT(0))) ··· 628 776 629 777 if (wifi_rfkill) { 630 778 dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch); 631 - dell_rfkill_update_sw_state(wifi_rfkill, 1, status); 779 + dell_rfkill_update_sw_state(wifi_rfkill, 1, status, buffer); 632 780 } 633 781 if (bluetooth_rfkill) { 634 782 dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status, 635 783 hwswitch); 636 - dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status); 784 + dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status, 785 + buffer); 637 786 } 638 787 if (wwan_rfkill) { 639 788 dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch); 640 - dell_rfkill_update_sw_state(wwan_rfkill, 3, status); 789 + dell_rfkill_update_sw_state(wwan_rfkill, 3, status, buffer); 641 790 } 642 791 643 792 out: 644 - release_buffer(); 793 + dell_smbios_release_buffer(); 645 794 } 646 795 static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill); 647 796 ··· 686 833 687 834 static int __init dell_setup_rfkill(void) 688 835 { 836 + struct calling_interface_buffer *buffer; 689 837 int status, ret, whitelisted; 690 838 const char *product; 691 839 ··· 702 848 if (!force_rfkill && !whitelisted) 703 849 return 0; 704 850 705 - get_buffer(); 706 - dell_send_request(buffer, 17, 11); 851 + buffer = dell_smbios_get_buffer(); 852 + dell_smbios_send_request(17, 11); 707 853 ret = buffer->output[0]; 708 854 status = buffer->output[1]; 709 - release_buffer(); 855 + dell_smbios_release_buffer(); 710 856 711 857 /* dell wireless info smbios call is not supported */ 712 858 if (ret != 0) ··· 859 1005 860 1006 static int dell_send_intensity(struct backlight_device *bd) 861 1007 { 862 - int token; 1008 + struct calling_interface_buffer *buffer; 1009 + struct calling_interface_token *token; 863 1010 int ret; 864 1011 865 - token = find_token_location(BRIGHTNESS_TOKEN); 866 - if (token == -1) 1012 + token = dell_smbios_find_token(BRIGHTNESS_TOKEN); 1013 + if (!token) 867 1014 return -ENODEV; 868 1015 869 - get_buffer(); 870 - buffer->input[0] = token; 1016 + buffer = dell_smbios_get_buffer(); 1017 + buffer->input[0] = token->location; 871 1018 buffer->input[1] = bd->props.brightness; 872 1019 873 1020 if (power_supply_is_system_supplied() > 0) 874 - dell_send_request(buffer, 1, 2); 1021 + dell_smbios_send_request(1, 2); 875 1022 else 876 - dell_send_request(buffer, 1, 1); 1023 + dell_smbios_send_request(1, 1); 877 1024 878 - ret = dell_smi_error(buffer->output[0]); 1025 + ret = dell_smbios_error(buffer->output[0]); 879 1026 880 - release_buffer(); 1027 + dell_smbios_release_buffer(); 881 1028 return ret; 882 1029 } 883 1030 884 1031 static int dell_get_intensity(struct backlight_device *bd) 885 1032 { 886 - int token; 1033 + struct calling_interface_buffer *buffer; 1034 + struct calling_interface_token *token; 887 1035 int ret; 888 1036 889 - token = find_token_location(BRIGHTNESS_TOKEN); 890 - if (token == -1) 1037 + token = dell_smbios_find_token(BRIGHTNESS_TOKEN); 1038 + if (!token) 891 1039 return -ENODEV; 892 1040 893 - get_buffer(); 894 - buffer->input[0] = token; 1041 + buffer = dell_smbios_get_buffer(); 1042 + buffer->input[0] = token->location; 895 1043 896 1044 if (power_supply_is_system_supplied() > 0) 897 - dell_send_request(buffer, 0, 2); 1045 + dell_smbios_send_request(0, 2); 898 1046 else 899 - dell_send_request(buffer, 0, 1); 1047 + dell_smbios_send_request(0, 1); 900 1048 901 1049 if (buffer->output[0]) 902 - ret = dell_smi_error(buffer->output[0]); 1050 + ret = dell_smbios_error(buffer->output[0]); 903 1051 else 904 1052 ret = buffer->output[1]; 905 1053 906 - release_buffer(); 1054 + dell_smbios_release_buffer(); 907 1055 return ret; 908 1056 } 909 1057 ··· 1149 1293 1150 1294 static int kbd_get_info(struct kbd_info *info) 1151 1295 { 1296 + struct calling_interface_buffer *buffer; 1152 1297 u8 units; 1153 1298 int ret; 1154 1299 1155 - get_buffer(); 1300 + buffer = dell_smbios_get_buffer(); 1156 1301 1157 1302 buffer->input[0] = 0x0; 1158 - dell_send_request(buffer, 4, 11); 1303 + dell_smbios_send_request(4, 11); 1159 1304 ret = buffer->output[0]; 1160 1305 1161 1306 if (ret) { 1162 - ret = dell_smi_error(ret); 1307 + ret = dell_smbios_error(ret); 1163 1308 goto out; 1164 1309 } 1165 1310 ··· 1180 1323 info->days = (buffer->output[3] >> 24) & 0xFF; 1181 1324 1182 1325 out: 1183 - release_buffer(); 1326 + dell_smbios_release_buffer(); 1184 1327 return ret; 1185 1328 } 1186 1329 ··· 1239 1382 1240 1383 static int kbd_get_state(struct kbd_state *state) 1241 1384 { 1385 + struct calling_interface_buffer *buffer; 1242 1386 int ret; 1243 1387 1244 - get_buffer(); 1388 + buffer = dell_smbios_get_buffer(); 1245 1389 1246 1390 buffer->input[0] = 0x1; 1247 - dell_send_request(buffer, 4, 11); 1391 + dell_smbios_send_request(4, 11); 1248 1392 ret = buffer->output[0]; 1249 1393 1250 1394 if (ret) { 1251 - ret = dell_smi_error(ret); 1395 + ret = dell_smbios_error(ret); 1252 1396 goto out; 1253 1397 } 1254 1398 ··· 1265 1407 state->level = (buffer->output[2] >> 16) & 0xFF; 1266 1408 1267 1409 out: 1268 - release_buffer(); 1410 + dell_smbios_release_buffer(); 1269 1411 return ret; 1270 1412 } 1271 1413 1272 1414 static int kbd_set_state(struct kbd_state *state) 1273 1415 { 1416 + struct calling_interface_buffer *buffer; 1274 1417 int ret; 1275 1418 1276 - get_buffer(); 1419 + buffer = dell_smbios_get_buffer(); 1277 1420 buffer->input[0] = 0x2; 1278 1421 buffer->input[1] = BIT(state->mode_bit) & 0xFFFF; 1279 1422 buffer->input[1] |= (state->triggers & 0xFF) << 16; ··· 1282 1423 buffer->input[1] |= (state->timeout_unit & 0x3) << 30; 1283 1424 buffer->input[2] = state->als_setting & 0xFF; 1284 1425 buffer->input[2] |= (state->level & 0xFF) << 16; 1285 - dell_send_request(buffer, 4, 11); 1426 + dell_smbios_send_request(4, 11); 1286 1427 ret = buffer->output[0]; 1287 - release_buffer(); 1428 + dell_smbios_release_buffer(); 1288 1429 1289 - return dell_smi_error(ret); 1430 + return dell_smbios_error(ret); 1290 1431 } 1291 1432 1292 1433 static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old) ··· 1311 1452 1312 1453 static int kbd_set_token_bit(u8 bit) 1313 1454 { 1314 - int id; 1455 + struct calling_interface_buffer *buffer; 1456 + struct calling_interface_token *token; 1315 1457 int ret; 1316 1458 1317 1459 if (bit >= ARRAY_SIZE(kbd_tokens)) 1318 1460 return -EINVAL; 1319 1461 1320 - id = find_token_id(kbd_tokens[bit]); 1321 - if (id == -1) 1462 + token = dell_smbios_find_token(kbd_tokens[bit]); 1463 + if (!token) 1322 1464 return -EINVAL; 1323 1465 1324 - get_buffer(); 1325 - buffer->input[0] = da_tokens[id].location; 1326 - buffer->input[1] = da_tokens[id].value; 1327 - dell_send_request(buffer, 1, 0); 1466 + buffer = dell_smbios_get_buffer(); 1467 + buffer->input[0] = token->location; 1468 + buffer->input[1] = token->value; 1469 + dell_smbios_send_request(1, 0); 1328 1470 ret = buffer->output[0]; 1329 - release_buffer(); 1471 + dell_smbios_release_buffer(); 1330 1472 1331 - return dell_smi_error(ret); 1473 + return dell_smbios_error(ret); 1332 1474 } 1333 1475 1334 1476 static int kbd_get_token_bit(u8 bit) 1335 1477 { 1336 - int id; 1478 + struct calling_interface_buffer *buffer; 1479 + struct calling_interface_token *token; 1337 1480 int ret; 1338 1481 int val; 1339 1482 1340 1483 if (bit >= ARRAY_SIZE(kbd_tokens)) 1341 1484 return -EINVAL; 1342 1485 1343 - id = find_token_id(kbd_tokens[bit]); 1344 - if (id == -1) 1486 + token = dell_smbios_find_token(kbd_tokens[bit]); 1487 + if (!token) 1345 1488 return -EINVAL; 1346 1489 1347 - get_buffer(); 1348 - buffer->input[0] = da_tokens[id].location; 1349 - dell_send_request(buffer, 0, 0); 1490 + buffer = dell_smbios_get_buffer(); 1491 + buffer->input[0] = token->location; 1492 + dell_smbios_send_request(0, 0); 1350 1493 ret = buffer->output[0]; 1351 1494 val = buffer->output[1]; 1352 - release_buffer(); 1495 + dell_smbios_release_buffer(); 1353 1496 1354 1497 if (ret) 1355 - return dell_smi_error(ret); 1498 + return dell_smbios_error(ret); 1356 1499 1357 - return (val == da_tokens[id].value); 1500 + return (val == token->value); 1358 1501 } 1359 1502 1360 1503 static int kbd_get_first_active_token_bit(void) ··· 1458 1597 int i; 1459 1598 1460 1599 for (i = 0; i < ARRAY_SIZE(kbd_tokens); ++i) 1461 - if (find_token_id(kbd_tokens[i]) != -1) 1600 + if (dell_smbios_find_token(kbd_tokens[i])) 1462 1601 kbd_token_bits |= BIT(i); 1463 1602 } 1464 1603 ··· 1972 2111 1973 2112 static int __init dell_init(void) 1974 2113 { 2114 + struct calling_interface_buffer *buffer; 2115 + struct calling_interface_token *token; 1975 2116 int max_intensity = 0; 1976 - int token; 1977 2117 int ret; 1978 2118 1979 2119 if (!dmi_check_system(dell_device_table)) ··· 1983 2121 quirks = NULL; 1984 2122 /* find if this machine support other functions */ 1985 2123 dmi_check_system(dell_quirks); 1986 - 1987 - dmi_walk(find_tokens, NULL); 1988 - 1989 - if (!da_tokens) { 1990 - pr_info("Unable to find dmi tokens\n"); 1991 - return -ENODEV; 1992 - } 1993 2124 1994 2125 ret = platform_driver_register(&platform_driver); 1995 2126 if (ret) ··· 1995 2140 ret = platform_device_add(platform_device); 1996 2141 if (ret) 1997 2142 goto fail_platform_device2; 1998 - 1999 - /* 2000 - * Allocate buffer below 4GB for SMI data--only 32-bit physical addr 2001 - * is passed to SMI handler. 2002 - */ 2003 - buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32); 2004 - if (!buffer) { 2005 - ret = -ENOMEM; 2006 - goto fail_buffer; 2007 - } 2008 2143 2009 2144 ret = dell_setup_rfkill(); 2010 2145 ··· 2016 2171 if (acpi_video_get_backlight_type() != acpi_backlight_vendor) 2017 2172 return 0; 2018 2173 2019 - token = find_token_location(BRIGHTNESS_TOKEN); 2020 - if (token != -1) { 2021 - get_buffer(); 2022 - buffer->input[0] = token; 2023 - dell_send_request(buffer, 0, 2); 2174 + token = dell_smbios_find_token(BRIGHTNESS_TOKEN); 2175 + if (token) { 2176 + buffer = dell_smbios_get_buffer(); 2177 + buffer->input[0] = token->location; 2178 + dell_smbios_send_request(0, 2); 2024 2179 if (buffer->output[0] == 0) 2025 2180 max_intensity = buffer->output[3]; 2026 - release_buffer(); 2181 + dell_smbios_release_buffer(); 2027 2182 } 2028 2183 2029 2184 if (max_intensity) { ··· 2053 2208 fail_backlight: 2054 2209 dell_cleanup_rfkill(); 2055 2210 fail_rfkill: 2056 - free_page((unsigned long)buffer); 2057 - fail_buffer: 2058 2211 platform_device_del(platform_device); 2059 2212 fail_platform_device2: 2060 2213 platform_device_put(platform_device); 2061 2214 fail_platform_device1: 2062 2215 platform_driver_unregister(&platform_driver); 2063 2216 fail_platform_driver: 2064 - kfree(da_tokens); 2065 2217 return ret; 2066 2218 } 2067 2219 ··· 2074 2232 platform_device_unregister(platform_device); 2075 2233 platform_driver_unregister(&platform_driver); 2076 2234 } 2077 - kfree(da_tokens); 2078 - free_page((unsigned long)buffer); 2079 2235 } 2080 2236 2081 2237 /* dell-rbtn.c driver export functions which will not work correctly (and could
+15
drivers/platform/x86/dell-rbtn.c
··· 217 217 static const struct acpi_device_id rbtn_ids[] = { 218 218 { "DELRBTN", 0 }, 219 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 235 { "", 0 }, 221 236 }; 222 237
+193
drivers/platform/x86/dell-smbios.c
··· 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 + 27 + struct 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 + 35 + static struct calling_interface_buffer *buffer; 36 + static DEFINE_MUTEX(buffer_mutex); 37 + 38 + static int da_command_address; 39 + static int da_command_code; 40 + static int da_num_tokens; 41 + static struct calling_interface_token *da_tokens; 42 + 43 + int 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 + } 56 + EXPORT_SYMBOL_GPL(dell_smbios_error); 57 + 58 + struct calling_interface_buffer *dell_smbios_get_buffer(void) 59 + { 60 + mutex_lock(&buffer_mutex); 61 + dell_smbios_clear_buffer(); 62 + return buffer; 63 + } 64 + EXPORT_SYMBOL_GPL(dell_smbios_get_buffer); 65 + 66 + void dell_smbios_clear_buffer(void) 67 + { 68 + memset(buffer, 0, sizeof(struct calling_interface_buffer)); 69 + } 70 + EXPORT_SYMBOL_GPL(dell_smbios_clear_buffer); 71 + 72 + void dell_smbios_release_buffer(void) 73 + { 74 + mutex_unlock(&buffer_mutex); 75 + } 76 + EXPORT_SYMBOL_GPL(dell_smbios_release_buffer); 77 + 78 + void 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 + } 93 + EXPORT_SYMBOL_GPL(dell_smbios_send_request); 94 + 95 + struct 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 + } 106 + EXPORT_SYMBOL_GPL(dell_smbios_find_token); 107 + 108 + static 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 + 139 + static 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 + 152 + static 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 + 175 + fail_buffer: 176 + kfree(da_tokens); 177 + return ret; 178 + } 179 + 180 + static void __exit dell_smbios_exit(void) 181 + { 182 + kfree(da_tokens); 183 + free_page((unsigned long)buffer); 184 + } 185 + 186 + subsys_initcall(dell_smbios_init); 187 + module_exit(dell_smbios_exit); 188 + 189 + MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 190 + MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>"); 191 + MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); 192 + MODULE_DESCRIPTION("Common functions for kernel modules using Dell SMBIOS"); 193 + MODULE_LICENSE("GPL");
+46
drivers/platform/x86/dell-smbios.h
··· 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 + 22 + struct calling_interface_buffer { 23 + u16 class; 24 + u16 select; 25 + volatile u32 input[4]; 26 + volatile u32 output[4]; 27 + } __packed; 28 + 29 + struct calling_interface_token { 30 + u16 tokenID; 31 + u16 location; 32 + union { 33 + u16 value; 34 + u16 stringlength; 35 + }; 36 + }; 37 + 38 + int dell_smbios_error(int value); 39 + 40 + struct calling_interface_buffer *dell_smbios_get_buffer(void); 41 + void dell_smbios_clear_buffer(void); 42 + void dell_smbios_release_buffer(void); 43 + void dell_smbios_send_request(int class, int select); 44 + 45 + struct calling_interface_token *dell_smbios_find_token(int tokenid); 46 + #endif
+202 -36
drivers/platform/x86/dell-wmi.c
··· 37 37 #include <linux/string.h> 38 38 #include <linux/dmi.h> 39 39 #include <acpi/video.h> 40 + #include "dell-smbios.h" 40 41 41 42 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 42 43 MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>"); ··· 48 47 #define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492" 49 48 50 49 static u32 dell_wmi_interface_version; 50 + static bool wmi_requires_smbios_request; 51 51 52 52 MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 53 53 MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID); 54 + 55 + static int __init dmi_matched(const struct dmi_system_id *dmi) 56 + { 57 + wmi_requires_smbios_request = 1; 58 + return 1; 59 + } 60 + 61 + static const struct dmi_system_id dell_wmi_smbios_list[] __initconst = { 62 + { 63 + .callback = dmi_matched, 64 + .ident = "Dell Inspiron M5110", 65 + .matches = { 66 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 67 + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron M5110"), 68 + }, 69 + }, 70 + { 71 + .callback = dmi_matched, 72 + .ident = "Dell Vostro V131", 73 + .matches = { 74 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 75 + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), 76 + }, 77 + }, 78 + { } 79 + }; 54 80 55 81 /* 56 82 * Certain keys are flagged as KE_IGNORE. All of these are either ··· 118 90 119 91 { KE_IGNORE, 0xe020, { KEY_MUTE } }, 120 92 121 - /* Shortcut and audio panel keys */ 122 - { KE_IGNORE, 0xe025, { KEY_RESERVED } }, 93 + /* Dell Instant Launch key */ 94 + { KE_KEY, 0xe025, { KEY_PROG4 } }, 95 + { KE_KEY, 0xe029, { KEY_PROG4 } }, 96 + 97 + /* Audio panel key */ 123 98 { KE_IGNORE, 0xe026, { KEY_RESERVED } }, 124 99 125 100 { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } }, ··· 151 120 152 121 }; 153 122 154 - static const struct dell_bios_hotkey_table *dell_bios_hotkey_table; 123 + struct dell_dmi_results { 124 + int err; 125 + struct key_entry *keymap; 126 + }; 155 127 156 128 /* Uninitialized entries here are KEY_RESERVED == 0. */ 157 129 static const u16 bios_to_linux_keycode[256] __initconst = { ··· 200 166 [255] = KEY_PROG3, 201 167 }; 202 168 169 + /* 170 + * These are applied if the 0xB2 DMI hotkey table is present and doesn't 171 + * override them. 172 + */ 173 + static const struct key_entry dell_wmi_extra_keymap[] __initconst = { 174 + /* Fn-lock */ 175 + { KE_IGNORE, 0x151, { KEY_RESERVED } }, 176 + 177 + /* Change keyboard illumination */ 178 + { KE_IGNORE, 0x152, { KEY_KBDILLUMTOGGLE } }, 179 + 180 + /* 181 + * Radio disable (notify only -- there is no model for which the 182 + * WMI event is supposed to trigger an action). 183 + */ 184 + { KE_IGNORE, 0x153, { KEY_RFKILL } }, 185 + 186 + /* RGB keyboard backlight control */ 187 + { KE_IGNORE, 0x154, { KEY_RESERVED } }, 188 + 189 + /* Stealth mode toggle */ 190 + { KE_IGNORE, 0x155, { KEY_RESERVED } }, 191 + }; 192 + 203 193 static struct input_dev *dell_wmi_input_dev; 204 194 205 195 static void dell_wmi_process_key(int reported_key) ··· 244 186 if ((key->keycode == KEY_BRIGHTNESSUP || 245 187 key->keycode == KEY_BRIGHTNESSDOWN) && 246 188 acpi_video_handles_brightness_key_presses()) 189 + return; 190 + 191 + if (reported_key == 0xe025 && !wmi_requires_smbios_request) 247 192 return; 248 193 249 194 sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true); ··· 398 337 kfree(obj); 399 338 } 400 339 401 - static const struct key_entry * __init dell_wmi_prepare_new_keymap(void) 340 + static bool have_scancode(u32 scancode, const struct key_entry *keymap, int len) 402 341 { 403 - int hotkey_num = (dell_bios_hotkey_table->header.length - 4) / 404 - sizeof(struct dell_bios_keymap_entry); 405 - struct key_entry *keymap; 406 342 int i; 407 343 408 - keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL); 409 - if (!keymap) 410 - return NULL; 344 + for (i = 0; i < len; i++) 345 + if (keymap[i].code == scancode) 346 + return true; 347 + 348 + return false; 349 + } 350 + 351 + static void __init handle_dmi_entry(const struct dmi_header *dm, 352 + 353 + void *opaque) 354 + 355 + { 356 + struct dell_dmi_results *results = opaque; 357 + struct dell_bios_hotkey_table *table; 358 + int hotkey_num, i, pos = 0; 359 + struct key_entry *keymap; 360 + int num_bios_keys; 361 + 362 + if (results->err || results->keymap) 363 + return; /* We already found the hotkey table. */ 364 + 365 + if (dm->type != 0xb2) 366 + return; 367 + 368 + table = container_of(dm, struct dell_bios_hotkey_table, header); 369 + 370 + hotkey_num = (table->header.length - 371 + sizeof(struct dell_bios_hotkey_table)) / 372 + sizeof(struct dell_bios_keymap_entry); 373 + if (hotkey_num < 1) { 374 + /* 375 + * Historically, dell-wmi would ignore a DMI entry of 376 + * fewer than 7 bytes. Sizes between 4 and 8 bytes are 377 + * nonsensical (both the header and all entries are 4 378 + * bytes), so we approximate the old behavior by 379 + * ignoring tables with fewer than one entry. 380 + */ 381 + return; 382 + } 383 + 384 + keymap = kcalloc(hotkey_num + ARRAY_SIZE(dell_wmi_extra_keymap) + 1, 385 + sizeof(struct key_entry), GFP_KERNEL); 386 + if (!keymap) { 387 + results->err = -ENOMEM; 388 + return; 389 + } 411 390 412 391 for (i = 0; i < hotkey_num; i++) { 413 392 const struct dell_bios_keymap_entry *bios_entry = 414 - &dell_bios_hotkey_table->keymap[i]; 393 + &table->keymap[i]; 415 394 416 395 /* Uninitialized entries are 0 aka KEY_RESERVED. */ 417 396 u16 keycode = (bios_entry->keycode < ··· 471 370 } 472 371 473 372 if (keycode == KEY_KBDILLUMTOGGLE) 474 - keymap[i].type = KE_IGNORE; 373 + keymap[pos].type = KE_IGNORE; 475 374 else 476 - keymap[i].type = KE_KEY; 477 - keymap[i].code = bios_entry->scancode; 478 - keymap[i].keycode = keycode; 375 + keymap[pos].type = KE_KEY; 376 + keymap[pos].code = bios_entry->scancode; 377 + keymap[pos].keycode = keycode; 378 + 379 + pos++; 479 380 } 480 381 481 - keymap[hotkey_num].type = KE_END; 382 + num_bios_keys = pos; 482 383 483 - return keymap; 384 + for (i = 0; i < ARRAY_SIZE(dell_wmi_extra_keymap); i++) { 385 + const struct key_entry *entry = &dell_wmi_extra_keymap[i]; 386 + 387 + /* 388 + * Check if we've already found this scancode. This takes 389 + * quadratic time, but it doesn't matter unless the list 390 + * of extra keys gets very long. 391 + */ 392 + if (!have_scancode(entry->code, keymap, num_bios_keys)) { 393 + keymap[pos] = *entry; 394 + pos++; 395 + } 396 + } 397 + 398 + keymap[pos].type = KE_END; 399 + 400 + results->keymap = keymap; 484 401 } 485 402 486 403 static int __init dell_wmi_input_setup(void) 487 404 { 405 + struct dell_dmi_results dmi_results = {}; 488 406 int err; 489 407 490 408 dell_wmi_input_dev = input_allocate_device(); ··· 514 394 dell_wmi_input_dev->phys = "wmi/input0"; 515 395 dell_wmi_input_dev->id.bustype = BUS_HOST; 516 396 517 - if (dell_new_hk_type) { 518 - const struct key_entry *keymap = dell_wmi_prepare_new_keymap(); 519 - if (!keymap) { 520 - err = -ENOMEM; 521 - goto err_free_dev; 522 - } 397 + if (dmi_walk(handle_dmi_entry, &dmi_results)) { 398 + /* 399 + * Historically, dell-wmi ignored dmi_walk errors. A failure 400 + * is certainly surprising, but it probably just indicates 401 + * a very old laptop. 402 + */ 403 + pr_warn("no DMI; using the old-style hotkey interface\n"); 404 + } 523 405 524 - err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL); 406 + if (dmi_results.err) { 407 + err = dmi_results.err; 408 + goto err_free_dev; 409 + } 410 + 411 + if (dmi_results.keymap) { 412 + dell_new_hk_type = true; 413 + 414 + err = sparse_keymap_setup(dell_wmi_input_dev, 415 + dmi_results.keymap, NULL); 525 416 526 417 /* 527 418 * Sparse keymap library makes a copy of keymap so we 528 419 * don't need the original one that was allocated. 529 420 */ 530 - kfree(keymap); 421 + kfree(dmi_results.keymap); 531 422 } else { 532 423 err = sparse_keymap_setup(dell_wmi_input_dev, 533 424 dell_wmi_legacy_keymap, NULL); ··· 563 432 { 564 433 sparse_keymap_free(dell_wmi_input_dev); 565 434 input_unregister_device(dell_wmi_input_dev); 566 - } 567 - 568 - static void __init find_hk_type(const struct dmi_header *dm, void *dummy) 569 - { 570 - if (dm->type == 0xb2 && dm->length > 6) { 571 - dell_new_hk_type = true; 572 - dell_bios_hotkey_table = 573 - container_of(dm, struct dell_bios_hotkey_table, header); 574 - } 575 435 } 576 436 577 437 /* ··· 631 509 return 0; 632 510 } 633 511 512 + /* 513 + * According to Dell SMBIOS documentation: 514 + * 515 + * 17 3 Application Program Registration 516 + * 517 + * cbArg1 Application ID 1 = 0x00010000 518 + * cbArg2 Application ID 2 519 + * QUICKSET/DCP = 0x51534554 "QSET" 520 + * ALS Driver = 0x416c7353 "AlsS" 521 + * Latitude ON = 0x4c6f6e52 "LonR" 522 + * cbArg3 Application version or revision number 523 + * cbArg4 0 = Unregister application 524 + * 1 = Register application 525 + * cbRes1 Standard return codes (0, -1, -2) 526 + */ 527 + 528 + static int dell_wmi_events_set_enabled(bool enable) 529 + { 530 + struct calling_interface_buffer *buffer; 531 + int ret; 532 + 533 + buffer = dell_smbios_get_buffer(); 534 + buffer->input[0] = 0x10000; 535 + buffer->input[1] = 0x51534554; 536 + buffer->input[3] = enable; 537 + dell_smbios_send_request(17, 3); 538 + ret = buffer->output[0]; 539 + dell_smbios_release_buffer(); 540 + 541 + return dell_smbios_error(ret); 542 + } 543 + 634 544 static int __init dell_wmi_init(void) 635 545 { 636 546 int err; ··· 678 524 if (err) 679 525 return err; 680 526 681 - dmi_walk(find_hk_type, NULL); 682 - 683 527 err = dell_wmi_input_setup(); 684 528 if (err) 685 529 return err; ··· 690 538 return -ENODEV; 691 539 } 692 540 541 + dmi_check_system(dell_wmi_smbios_list); 542 + 543 + if (wmi_requires_smbios_request) { 544 + err = dell_wmi_events_set_enabled(true); 545 + if (err) { 546 + pr_err("Failed to enable WMI events\n"); 547 + wmi_remove_notify_handler(DELL_EVENT_GUID); 548 + dell_wmi_input_destroy(); 549 + return err; 550 + } 551 + } 552 + 693 553 return 0; 694 554 } 695 555 module_init(dell_wmi_init); 696 556 697 557 static void __exit dell_wmi_exit(void) 698 558 { 559 + if (wmi_requires_smbios_request) 560 + dell_wmi_events_set_enabled(false); 699 561 wmi_remove_notify_handler(DELL_EVENT_GUID); 700 562 dell_wmi_input_destroy(); 701 563 }
+7 -1
drivers/platform/x86/fujitsu-laptop.c
··· 114 114 #define KEY2_CODE 0x411 115 115 #define KEY3_CODE 0x412 116 116 #define KEY4_CODE 0x413 117 + #define KEY5_CODE 0x420 117 118 118 119 #define MAX_HOTKEY_RINGBUFFER_SIZE 100 119 120 #define RINGBUFFERSIZE 40 ··· 150 149 char phys[32]; 151 150 struct backlight_device *bl_device; 152 151 struct platform_device *pf_device; 153 - int keycode1, keycode2, keycode3, keycode4; 152 + int keycode1, keycode2, keycode3, keycode4, keycode5; 154 153 155 154 unsigned int max_brightness; 156 155 unsigned int brightness_changed; ··· 824 823 set_bit(fujitsu->keycode2, input->keybit); 825 824 set_bit(fujitsu->keycode3, input->keybit); 826 825 set_bit(fujitsu->keycode4, input->keybit); 826 + set_bit(fujitsu->keycode5, input->keybit); 827 827 set_bit(KEY_UNKNOWN, input->keybit); 828 828 829 829 error = input_register_device(input); ··· 964 962 case KEY4_CODE: 965 963 keycode = fujitsu->keycode4; 966 964 break; 965 + case KEY5_CODE: 966 + keycode = fujitsu->keycode5; 967 + break; 967 968 case 0: 968 969 keycode = 0; 969 970 break; ··· 1077 1072 fujitsu->keycode2 = KEY_PROG2; 1078 1073 fujitsu->keycode3 = KEY_PROG3; 1079 1074 fujitsu->keycode4 = KEY_PROG4; 1075 + fujitsu->keycode5 = KEY_RFKILL; 1080 1076 dmi_check_system(fujitsu_dmi_table); 1081 1077 1082 1078 result = acpi_bus_register_driver(&acpi_fujitsu_driver);
+5 -41
drivers/platform/x86/hp-wmi.c
··· 157 157 static struct rfkill *wifi_rfkill; 158 158 static struct rfkill *bluetooth_rfkill; 159 159 static struct rfkill *wwan_rfkill; 160 - static struct rfkill *gps_rfkill; 161 160 162 161 struct rfkill2_device { 163 162 u8 id; ··· 612 613 rfkill_set_states(wwan_rfkill, 613 614 hp_wmi_get_sw_state(HPWMI_WWAN), 614 615 hp_wmi_get_hw_state(HPWMI_WWAN)); 615 - if (gps_rfkill) 616 - rfkill_set_states(gps_rfkill, 617 - hp_wmi_get_sw_state(HPWMI_GPS), 618 - hp_wmi_get_hw_state(HPWMI_GPS)); 619 616 break; 620 617 case HPWMI_CPU_BATTERY_THROTTLE: 621 618 pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n"); ··· 741 746 (void *) HPWMI_BLUETOOTH); 742 747 if (!bluetooth_rfkill) { 743 748 err = -ENOMEM; 744 - goto register_wifi_error; 749 + goto register_bluetooth_error; 745 750 } 746 751 rfkill_init_sw_state(bluetooth_rfkill, 747 752 hp_wmi_get_sw_state(HPWMI_BLUETOOTH)); ··· 759 764 (void *) HPWMI_WWAN); 760 765 if (!wwan_rfkill) { 761 766 err = -ENOMEM; 762 - goto register_bluetooth_error; 767 + goto register_wwan_error; 763 768 } 764 769 rfkill_init_sw_state(wwan_rfkill, 765 770 hp_wmi_get_sw_state(HPWMI_WWAN)); ··· 770 775 goto register_wwan_error; 771 776 } 772 777 773 - if (wireless & 0x8) { 774 - gps_rfkill = rfkill_alloc("hp-gps", &device->dev, 775 - RFKILL_TYPE_GPS, 776 - &hp_wmi_rfkill_ops, 777 - (void *) HPWMI_GPS); 778 - if (!gps_rfkill) { 779 - err = -ENOMEM; 780 - goto register_wwan_error; 781 - } 782 - rfkill_init_sw_state(gps_rfkill, 783 - hp_wmi_get_sw_state(HPWMI_GPS)); 784 - rfkill_set_hw_state(gps_rfkill, 785 - hp_wmi_get_hw_state(HPWMI_GPS)); 786 - err = rfkill_register(gps_rfkill); 787 - if (err) 788 - goto register_gps_error; 789 - } 790 - 791 778 return 0; 792 - register_gps_error: 793 - rfkill_destroy(gps_rfkill); 794 - gps_rfkill = NULL; 795 - if (bluetooth_rfkill) 796 - rfkill_unregister(bluetooth_rfkill); 779 + 797 780 register_wwan_error: 798 781 rfkill_destroy(wwan_rfkill); 799 782 wwan_rfkill = NULL; 800 - if (gps_rfkill) 801 - rfkill_unregister(gps_rfkill); 783 + if (bluetooth_rfkill) 784 + rfkill_unregister(bluetooth_rfkill); 802 785 register_bluetooth_error: 803 786 rfkill_destroy(bluetooth_rfkill); 804 787 bluetooth_rfkill = NULL; ··· 880 907 wifi_rfkill = NULL; 881 908 bluetooth_rfkill = NULL; 882 909 wwan_rfkill = NULL; 883 - gps_rfkill = NULL; 884 910 rfkill2_count = 0; 885 911 886 912 if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device)) ··· 932 960 rfkill_unregister(wwan_rfkill); 933 961 rfkill_destroy(wwan_rfkill); 934 962 } 935 - if (gps_rfkill) { 936 - rfkill_unregister(gps_rfkill); 937 - rfkill_destroy(gps_rfkill); 938 - } 939 963 940 964 return 0; 941 965 } ··· 967 999 rfkill_set_states(wwan_rfkill, 968 1000 hp_wmi_get_sw_state(HPWMI_WWAN), 969 1001 hp_wmi_get_hw_state(HPWMI_WWAN)); 970 - if (gps_rfkill) 971 - rfkill_set_states(gps_rfkill, 972 - hp_wmi_get_sw_state(HPWMI_GPS), 973 - hp_wmi_get_hw_state(HPWMI_GPS)); 974 1002 975 1003 return 0; 976 1004 }
+14
drivers/platform/x86/ideapad-laptop.c
··· 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 882 .ident = "Lenovo ideapad Y700-17ISK", 869 883 .matches = { 870 884 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+1 -2
drivers/platform/x86/intel-hid.c
··· 180 180 return -ENODEV; 181 181 } 182 182 183 - priv = devm_kzalloc(&device->dev, 184 - sizeof(struct intel_hid_priv *), GFP_KERNEL); 183 + priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); 185 184 if (!priv) 186 185 return -ENOMEM; 187 186 dev_set_drvdata(&device->dev, priv);
+5 -3
drivers/platform/x86/intel_pmc_ipc.c
··· 67 67 /* exported resources from IFWI */ 68 68 #define PLAT_RESOURCE_IPC_INDEX 0 69 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 72 #define PLAT_RESOURCE_BIOS_DATA_INDEX 1 72 73 #define PLAT_RESOURCE_BIOS_IFACE_INDEX 2 73 74 #define PLAT_RESOURCE_TELEM_SSRAM_INDEX 3 ··· 767 766 } 768 767 ipcdev.ipc_base = addr; 769 768 770 - ipcdev.gcr_base = res->start + size; 769 + ipcdev.gcr_base = res->start + PLAT_RESOURCE_GCR_OFFSET; 771 770 ipcdev.gcr_size = PLAT_RESOURCE_GCR_SIZE; 772 771 dev_info(&pdev->dev, "ipc res: %pR\n", res); 773 772 ··· 825 824 goto err_device; 826 825 } 827 826 828 - if (request_irq(ipcdev.irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) { 827 + if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND, 828 + "intel_pmc_ipc", &ipcdev)) { 829 829 dev_err(&pdev->dev, "Failed to request irq\n"); 830 830 ret = -EBUSY; 831 831 goto err_irq;
+4 -31
drivers/platform/x86/intel_scu_ipc.c
··· 24 24 #include <linux/pci.h> 25 25 #include <linux/interrupt.h> 26 26 #include <linux/sfi.h> 27 - #include <linux/module.h> 28 27 #include <asm/intel-mid.h> 29 28 #include <asm/intel_scu_ipc.h> 30 29 ··· 610 611 return 0; 611 612 } 612 613 613 - /** 614 - * ipc_remove - remove a bound IPC device 615 - * @pdev: PCI device 616 - * 617 - * In practice the SCU is not removable but this function is also 618 - * called for each device on a module unload or cleanup which is the 619 - * path that will get used. 620 - * 621 - * Free up the mappings and release the PCI resources 622 - */ 623 - static void ipc_remove(struct pci_dev *pdev) 624 - { 625 - struct intel_scu_ipc_dev *scu = pci_get_drvdata(pdev); 626 - 627 - mutex_lock(&ipclock); 628 - scu->dev = NULL; 629 - mutex_unlock(&ipclock); 630 - 631 - iounmap(scu->i2c_base); 632 - intel_scu_devices_destroy(); 633 - } 634 - 635 614 static const struct pci_device_id pci_ids[] = { 636 615 { 637 616 PCI_VDEVICE(INTEL, PCI_DEVICE_ID_LINCROFT), ··· 627 650 0, 628 651 } 629 652 }; 630 - MODULE_DEVICE_TABLE(pci, pci_ids); 631 653 632 654 static struct pci_driver ipc_driver = { 655 + .driver = { 656 + .suppress_bind_attrs = true, 657 + }, 633 658 .name = "intel_scu_ipc", 634 659 .id_table = pci_ids, 635 660 .probe = ipc_probe, 636 - .remove = ipc_remove, 637 661 }; 638 - 639 - module_pci_driver(ipc_driver); 640 - 641 - MODULE_AUTHOR("Sreedhara DS <sreedhara.ds@intel.com>"); 642 - MODULE_DESCRIPTION("Intel SCU IPC driver"); 643 - MODULE_LICENSE("GPL"); 662 + builtin_pci_driver(ipc_driver);
+12 -1
drivers/platform/x86/intel_telemetry_pltdrv.c
··· 1030 1030 switch (telem_unit) { 1031 1031 case TELEM_PSS: 1032 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 1044 IPC_PUNIT_BIOS_WRITE_TELE_TRACE_CTRL, 1034 - 0, 0, &verbosity, NULL); 1045 + 0, 0, &temp, NULL); 1035 1046 if (ret) { 1036 1047 pr_err("PSS TRACE_CTRL Verbosity Set Failed\n"); 1037 1048 goto out;
+1 -3
drivers/platform/x86/thinkpad_acpi.c
··· 6653 6653 switch (b) { 6654 6654 case 16: 6655 6655 bright_maxlvl = 15; 6656 - pr_info("detected a 16-level brightness capable ThinkPad\n"); 6657 6656 break; 6658 6657 case 8: 6659 6658 case 0: 6660 6659 bright_maxlvl = 7; 6661 - pr_info("detected a 8-level brightness capable ThinkPad\n"); 6662 6660 break; 6663 6661 default: 6664 - pr_info("Unsupported brightness interface\n"); 6665 6662 tp_features.bright_unkfw = 1; 6666 6663 bright_maxlvl = b - 1; 6667 6664 } 6665 + pr_debug("detected %u brightness levels\n", bright_maxlvl + 1); 6668 6666 } 6669 6667 6670 6668 static int __init brightness_init(struct ibm_init_struct *iibm)
+115
drivers/platform/x86/toshiba_acpi.c
··· 36 36 37 37 #include <linux/kernel.h> 38 38 #include <linux/module.h> 39 + #include <linux/moduleparam.h> 39 40 #include <linux/init.h> 40 41 #include <linux/types.h> 41 42 #include <linux/proc_fs.h> ··· 118 117 #define HCI_LCD_BRIGHTNESS 0x002a 119 118 #define HCI_WIRELESS 0x0056 120 119 #define HCI_ACCELEROMETER 0x006d 120 + #define HCI_COOLING_METHOD 0x007f 121 121 #define HCI_KBD_ILLUMINATION 0x0095 122 122 #define HCI_ECO_MODE 0x0097 123 123 #define HCI_ACCELEROMETER2 0x00a6 ··· 188 186 int usbsc_bat_level; 189 187 int usbsc_mode_base; 190 188 int hotkey_event_type; 189 + int max_cooling_method; 191 190 192 191 unsigned int illumination_supported:1; 193 192 unsigned int video_supported:1; ··· 208 205 unsigned int panel_power_on_supported:1; 209 206 unsigned int usb_three_supported:1; 210 207 unsigned int wwan_supported:1; 208 + unsigned int cooling_method_supported:1; 211 209 unsigned int sysfs_created:1; 212 210 unsigned int special_functions; 213 211 ··· 220 216 }; 221 217 222 218 static struct toshiba_acpi_dev *toshiba_acpi; 219 + 220 + static bool disable_hotkeys; 221 + module_param(disable_hotkeys, bool, 0444); 222 + MODULE_PARM_DESC(disable_hotkeys, "Disables the hotkeys activation"); 223 223 224 224 static const struct acpi_device_id toshiba_device_ids[] = { 225 225 {"TOS6200", 0}, ··· 1200 1192 return -ENODEV; 1201 1193 1202 1194 return out[0] == TOS_SUCCESS ? 0 : -EIO; 1195 + } 1196 + 1197 + /* Cooling Method */ 1198 + static void toshiba_cooling_method_available(struct toshiba_acpi_dev *dev) 1199 + { 1200 + u32 in[TCI_WORDS] = { HCI_GET, HCI_COOLING_METHOD, 0, 0, 0, 0 }; 1201 + u32 out[TCI_WORDS]; 1202 + acpi_status status; 1203 + 1204 + dev->cooling_method_supported = 0; 1205 + dev->max_cooling_method = 0; 1206 + 1207 + status = tci_raw(dev, in, out); 1208 + if (ACPI_FAILURE(status)) 1209 + pr_err("ACPI call to get Cooling Method failed\n"); 1210 + 1211 + if (out[0] != TOS_SUCCESS && out[0] != TOS_SUCCESS2) 1212 + return; 1213 + 1214 + dev->cooling_method_supported = 1; 1215 + dev->max_cooling_method = out[3]; 1216 + } 1217 + 1218 + static int toshiba_cooling_method_get(struct toshiba_acpi_dev *dev, u32 *state) 1219 + { 1220 + u32 result = hci_read(dev, HCI_COOLING_METHOD, state); 1221 + 1222 + if (result == TOS_FAILURE) 1223 + pr_err("ACPI call to get Cooling Method failed\n"); 1224 + 1225 + if (result == TOS_NOT_SUPPORTED) 1226 + return -ENODEV; 1227 + 1228 + return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; 1229 + } 1230 + 1231 + static int toshiba_cooling_method_set(struct toshiba_acpi_dev *dev, u32 state) 1232 + { 1233 + u32 result = hci_write(dev, HCI_COOLING_METHOD, state); 1234 + 1235 + if (result == TOS_FAILURE) 1236 + pr_err("ACPI call to get Cooling Method failed\n"); 1237 + 1238 + if (result == TOS_NOT_SUPPORTED) 1239 + return -ENODEV; 1240 + 1241 + return (result == TOS_SUCCESS || result == TOS_SUCCESS2) ? 0 : -EIO; 1203 1242 } 1204 1243 1205 1244 /* Transflective Backlight */ ··· 2294 2239 } 2295 2240 static DEVICE_ATTR_RW(usb_three); 2296 2241 2242 + static ssize_t cooling_method_show(struct device *dev, 2243 + struct device_attribute *attr, char *buf) 2244 + { 2245 + struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); 2246 + int state; 2247 + int ret; 2248 + 2249 + ret = toshiba_cooling_method_get(toshiba, &state); 2250 + if (ret < 0) 2251 + return ret; 2252 + 2253 + return sprintf(buf, "%d %d\n", state, toshiba->max_cooling_method); 2254 + } 2255 + 2256 + static ssize_t cooling_method_store(struct device *dev, 2257 + struct device_attribute *attr, 2258 + const char *buf, size_t count) 2259 + { 2260 + struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev); 2261 + int state; 2262 + int ret; 2263 + 2264 + ret = kstrtoint(buf, 0, &state); 2265 + if (ret) 2266 + return ret; 2267 + 2268 + /* 2269 + * Check for supported values 2270 + * Depending on the laptop model, some only support these two: 2271 + * 0 - Maximum Performance 2272 + * 1 - Battery Optimized 2273 + * 2274 + * While some others support all three methods: 2275 + * 0 - Maximum Performance 2276 + * 1 - Performance 2277 + * 2 - Battery Optimized 2278 + */ 2279 + if (state < 0 || state > toshiba->max_cooling_method) 2280 + return -EINVAL; 2281 + 2282 + ret = toshiba_cooling_method_set(toshiba, state); 2283 + if (ret) 2284 + return ret; 2285 + 2286 + return count; 2287 + } 2288 + static DEVICE_ATTR_RW(cooling_method); 2289 + 2297 2290 static struct attribute *toshiba_attributes[] = { 2298 2291 &dev_attr_version.attr, 2299 2292 &dev_attr_fan.attr, ··· 2358 2255 &dev_attr_kbd_function_keys.attr, 2359 2256 &dev_attr_panel_power_on.attr, 2360 2257 &dev_attr_usb_three.attr, 2258 + &dev_attr_cooling_method.attr, 2361 2259 NULL, 2362 2260 }; 2363 2261 ··· 2393 2289 exists = (drv->panel_power_on_supported) ? true : false; 2394 2290 else if (attr == &dev_attr_usb_three.attr) 2395 2291 exists = (drv->usb_three_supported) ? true : false; 2292 + else if (attr == &dev_attr_cooling_method.attr) 2293 + exists = (drv->cooling_method_supported) ? true : false; 2396 2294 2397 2295 return exists ? attr->mode : 0; 2398 2296 } ··· 2697 2591 acpi_handle ec_handle; 2698 2592 int error; 2699 2593 2594 + if (disable_hotkeys) { 2595 + pr_info("Hotkeys disabled by module parameter\n"); 2596 + return 0; 2597 + } 2598 + 2700 2599 if (wmi_has_guid(TOSHIBA_WMI_EVENT_GUID)) { 2701 2600 pr_info("WMI event detected, hotkeys will not be monitored\n"); 2702 2601 return 0; ··· 2890 2779 pr_cont(" usb3"); 2891 2780 if (dev->wwan_supported) 2892 2781 pr_cont(" wwan"); 2782 + if (dev->cooling_method_supported) 2783 + pr_cont(" cooling-method"); 2893 2784 2894 2785 pr_cont("\n"); 2895 2786 } ··· 3075 2962 toshiba_wwan_available(dev); 3076 2963 if (dev->wwan_supported) 3077 2964 toshiba_acpi_setup_wwan_rfkill(dev); 2965 + 2966 + toshiba_cooling_method_available(dev); 3078 2967 3079 2968 print_supported_features(dev); 3080 2969