2899 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Acer WMI Laptop Extras4 *5 * Copyright (C) 2007-2009 Carlos Corbacho <carlos@strangeworlds.co.uk>6 *7 * Based on acer_acpi:8 * Copyright (C) 2005-2007 E.M. Smith9 * Copyright (C) 2007-2008 Carlos Corbacho <cathectic@gmail.com>10 */11 12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt13 14#include <linux/kernel.h>15#include <linux/module.h>16#include <linux/init.h>17#include <linux/types.h>18#include <linux/dmi.h>19#include <linux/backlight.h>20#include <linux/leds.h>21#include <linux/platform_device.h>22#include <linux/platform_profile.h>23#include <linux/acpi.h>24#include <linux/i8042.h>25#include <linux/rfkill.h>26#include <linux/workqueue.h>27#include <linux/debugfs.h>28#include <linux/slab.h>29#include <linux/input.h>30#include <linux/input/sparse-keymap.h>31#include <acpi/video.h>32#include <linux/hwmon.h>33#include <linux/bitfield.h>34 35MODULE_AUTHOR("Carlos Corbacho");36MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");37MODULE_LICENSE("GPL");38 39/*40 * Magic Number41 * Meaning is unknown - this number is required for writing to ACPI for AMW042 * (it's also used in acerhk when directly accessing the BIOS)43 */44#define ACER_AMW0_WRITE 0x961045 46/*47 * Bit masks for the AMW0 interface48 */49#define ACER_AMW0_WIRELESS_MASK 0x3550#define ACER_AMW0_BLUETOOTH_MASK 0x3451#define ACER_AMW0_MAILLED_MASK 0x3152 53/*54 * Method IDs for WMID interface55 */56#define ACER_WMID_GET_WIRELESS_METHODID 157#define ACER_WMID_GET_BLUETOOTH_METHODID 258#define ACER_WMID_GET_BRIGHTNESS_METHODID 359#define ACER_WMID_SET_WIRELESS_METHODID 460#define ACER_WMID_SET_BLUETOOTH_METHODID 561#define ACER_WMID_SET_BRIGHTNESS_METHODID 662#define ACER_WMID_GET_THREEG_METHODID 1063#define ACER_WMID_SET_THREEG_METHODID 1164 65#define ACER_WMID_SET_GAMING_LED_METHODID 266#define ACER_WMID_GET_GAMING_LED_METHODID 467#define ACER_WMID_GET_GAMING_SYS_INFO_METHODID 568#define ACER_WMID_SET_GAMING_FAN_BEHAVIOR 1469#define ACER_WMID_SET_GAMING_MISC_SETTING_METHODID 2270 71#define ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET 0x5472 73#define ACER_PREDATOR_V4_FAN_SPEED_READ_BIT_MASK GENMASK(20, 8)74 75/*76 * Acer ACPI method GUIDs77 */78#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB"79#define AMW0_GUID2 "431F16ED-0C2B-444C-B267-27DEB140CF9C"80#define WMID_GUID1 "6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"81#define WMID_GUID2 "95764E09-FB56-4E83-B31A-37761F60994A"82#define WMID_GUID3 "61EF69EA-865C-4BC3-A502-A0DEBA0CB531"83#define WMID_GUID4 "7A4DDFE7-5B5D-40B4-8595-4408E0CC7F56"84 85/*86 * Acer ACPI event GUIDs87 */88#define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"89 90MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");91MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");92MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");93 94enum acer_wmi_event_ids {95 WMID_HOTKEY_EVENT = 0x1,96 WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,97 WMID_GAMING_TURBO_KEY_EVENT = 0x7,98};99 100enum acer_wmi_predator_v4_sys_info_command {101 ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS = 0x02,102 ACER_WMID_CMD_GET_PREDATOR_V4_CPU_FAN_SPEED = 0x0201,103 ACER_WMID_CMD_GET_PREDATOR_V4_GPU_FAN_SPEED = 0x0601,104};105 106static const struct key_entry acer_wmi_keymap[] __initconst = {107 {KE_KEY, 0x01, {KEY_WLAN} }, /* WiFi */108 {KE_KEY, 0x03, {KEY_WLAN} }, /* WiFi */109 {KE_KEY, 0x04, {KEY_WLAN} }, /* WiFi */110 {KE_KEY, 0x12, {KEY_BLUETOOTH} }, /* BT */111 {KE_KEY, 0x21, {KEY_PROG1} }, /* Backup */112 {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */113 {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */114 {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */115 {KE_KEY, 0x27, {KEY_HELP} },116 {KE_KEY, 0x29, {KEY_PROG3} }, /* P_Key for TM8372 */117 {KE_IGNORE, 0x41, {KEY_MUTE} },118 {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },119 {KE_IGNORE, 0x4d, {KEY_PREVIOUSSONG} },120 {KE_IGNORE, 0x43, {KEY_NEXTSONG} },121 {KE_IGNORE, 0x4e, {KEY_NEXTSONG} },122 {KE_IGNORE, 0x44, {KEY_PLAYPAUSE} },123 {KE_IGNORE, 0x4f, {KEY_PLAYPAUSE} },124 {KE_IGNORE, 0x45, {KEY_STOP} },125 {KE_IGNORE, 0x50, {KEY_STOP} },126 {KE_IGNORE, 0x48, {KEY_VOLUMEUP} },127 {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },128 {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },129 /*130 * 0x61 is KEY_SWITCHVIDEOMODE. Usually this is a duplicate input event131 * with the "Video Bus" input device events. But sometimes it is not132 * a dup. Map it to KEY_UNKNOWN instead of using KE_IGNORE so that133 * udev/hwdb can override it on systems where it is not a dup.134 */135 {KE_KEY, 0x61, {KEY_UNKNOWN} },136 {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },137 {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },138 {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */139 {KE_IGNORE, 0x81, {KEY_SLEEP} },140 {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */141 {KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */142 {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },143 {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },144 {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },145 {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },146 {KE_KEY, 0x86, {KEY_WLAN} },147 {KE_KEY, 0x87, {KEY_POWER} },148 {KE_END, 0}149};150 151static struct input_dev *acer_wmi_input_dev;152static struct input_dev *acer_wmi_accel_dev;153 154struct event_return_value {155 u8 function;156 u8 key_num;157 u16 device_state;158 u16 reserved1;159 u8 kbd_dock_state;160 u8 reserved2;161} __packed;162 163/*164 * GUID3 Get Device Status device flags165 */166#define ACER_WMID3_GDS_WIRELESS (1<<0) /* WiFi */167#define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */168#define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */169#define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */170#define ACER_WMID3_GDS_RFBTN (1<<14) /* RF Button */171 172#define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */173 174/* Hotkey Customized Setting and Acer Application Status.175 * Set Device Default Value and Report Acer Application Status.176 * When Acer Application starts, it will run this method to inform177 * BIOS/EC that Acer Application is on.178 * App Status179 * Bit[0]: Launch Manager Status180 * Bit[1]: ePM Status181 * Bit[2]: Device Control Status182 * Bit[3]: Acer Power Button Utility Status183 * Bit[4]: RF Button Status184 * Bit[5]: ODD PM Status185 * Bit[6]: Device Default Value Control186 * Bit[7]: Hall Sensor Application Status187 */188struct func_input_params {189 u8 function_num; /* Function Number */190 u16 commun_devices; /* Communication type devices default status */191 u16 devices; /* Other type devices default status */192 u8 app_status; /* Acer Device Status. LM, ePM, RF Button... */193 u8 app_mask; /* Bit mask to app_status */194 u8 reserved;195} __packed;196 197struct func_return_value {198 u8 error_code; /* Error Code */199 u8 ec_return_value; /* EC Return Value */200 u16 reserved;201} __packed;202 203struct wmid3_gds_set_input_param { /* Set Device Status input parameter */204 u8 function_num; /* Function Number */205 u8 hotkey_number; /* Hotkey Number */206 u16 devices; /* Set Device */207 u8 volume_value; /* Volume Value */208} __packed;209 210struct wmid3_gds_get_input_param { /* Get Device Status input parameter */211 u8 function_num; /* Function Number */212 u8 hotkey_number; /* Hotkey Number */213 u16 devices; /* Get Device */214} __packed;215 216struct wmid3_gds_return_value { /* Get Device Status return value*/217 u8 error_code; /* Error Code */218 u8 ec_return_value; /* EC Return Value */219 u16 devices; /* Current Device Status */220 u32 reserved;221} __packed;222 223struct hotkey_function_type_aa {224 u8 type;225 u8 length;226 u16 handle;227 u16 commun_func_bitmap;228 u16 application_func_bitmap;229 u16 media_func_bitmap;230 u16 display_func_bitmap;231 u16 others_func_bitmap;232 u8 commun_fn_key_number;233} __packed;234 235/*236 * Interface capability flags237 */238#define ACER_CAP_MAILLED BIT(0)239#define ACER_CAP_WIRELESS BIT(1)240#define ACER_CAP_BLUETOOTH BIT(2)241#define ACER_CAP_BRIGHTNESS BIT(3)242#define ACER_CAP_THREEG BIT(4)243#define ACER_CAP_SET_FUNCTION_MODE BIT(5)244#define ACER_CAP_KBD_DOCK BIT(6)245#define ACER_CAP_TURBO_OC BIT(7)246#define ACER_CAP_TURBO_LED BIT(8)247#define ACER_CAP_TURBO_FAN BIT(9)248#define ACER_CAP_PLATFORM_PROFILE BIT(10)249#define ACER_CAP_FAN_SPEED_READ BIT(11)250 251/*252 * Interface type flags253 */254enum interface_flags {255 ACER_AMW0,256 ACER_AMW0_V2,257 ACER_WMID,258 ACER_WMID_v2,259};260 261#define ACER_DEFAULT_WIRELESS 0262#define ACER_DEFAULT_BLUETOOTH 0263#define ACER_DEFAULT_MAILLED 0264#define ACER_DEFAULT_THREEG 0265 266static int max_brightness = 0xF;267 268static int mailled = -1;269static int brightness = -1;270static int threeg = -1;271static int force_series;272static int force_caps = -1;273static bool ec_raw_mode;274static bool has_type_aa;275static u16 commun_func_bitmap;276static u8 commun_fn_key_number;277static bool cycle_gaming_thermal_profile = true;278static bool predator_v4;279 280module_param(mailled, int, 0444);281module_param(brightness, int, 0444);282module_param(threeg, int, 0444);283module_param(force_series, int, 0444);284module_param(force_caps, int, 0444);285module_param(ec_raw_mode, bool, 0444);286module_param(cycle_gaming_thermal_profile, bool, 0644);287module_param(predator_v4, bool, 0444);288MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");289MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");290MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");291MODULE_PARM_DESC(force_series, "Force a different laptop series");292MODULE_PARM_DESC(force_caps, "Force the capability bitmask to this value");293MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");294MODULE_PARM_DESC(cycle_gaming_thermal_profile,295 "Set thermal mode key in cycle mode. Disabling it sets the mode key in turbo toggle mode");296MODULE_PARM_DESC(predator_v4,297 "Enable features for predator laptops that use predator sense v4");298 299struct acer_data {300 int mailled;301 int threeg;302 int brightness;303};304 305struct acer_debug {306 struct dentry *root;307 u32 wmid_devices;308};309 310static struct rfkill *wireless_rfkill;311static struct rfkill *bluetooth_rfkill;312static struct rfkill *threeg_rfkill;313static bool rfkill_inited;314 315/* Each low-level interface must define at least some of the following */316struct wmi_interface {317 /* The WMI device type */318 u32 type;319 320 /* The capabilities this interface provides */321 u32 capability;322 323 /* Private data for the current interface */324 struct acer_data data;325 326 /* debugfs entries associated with this interface */327 struct acer_debug debug;328};329 330/* The static interface pointer, points to the currently detected interface */331static struct wmi_interface *interface;332 333/*334 * Embedded Controller quirks335 * Some laptops require us to directly access the EC to either enable or query336 * features that are not available through WMI.337 */338 339struct quirk_entry {340 u8 wireless;341 u8 mailled;342 s8 brightness;343 u8 bluetooth;344 u8 turbo;345 u8 cpu_fans;346 u8 gpu_fans;347 u8 predator_v4;348};349 350static struct quirk_entry *quirks;351 352static void __init set_quirks(void)353{354 if (quirks->mailled)355 interface->capability |= ACER_CAP_MAILLED;356 357 if (quirks->brightness)358 interface->capability |= ACER_CAP_BRIGHTNESS;359 360 if (quirks->turbo)361 interface->capability |= ACER_CAP_TURBO_OC | ACER_CAP_TURBO_LED362 | ACER_CAP_TURBO_FAN;363 364 if (quirks->predator_v4)365 interface->capability |= ACER_CAP_PLATFORM_PROFILE |366 ACER_CAP_FAN_SPEED_READ;367}368 369static int __init dmi_matched(const struct dmi_system_id *dmi)370{371 quirks = dmi->driver_data;372 return 1;373}374 375static int __init set_force_caps(const struct dmi_system_id *dmi)376{377 if (force_caps == -1) {378 force_caps = (uintptr_t)dmi->driver_data;379 pr_info("Found %s, set force_caps to 0x%x\n", dmi->ident, force_caps);380 }381 return 1;382}383 384static struct quirk_entry quirk_unknown = {385};386 387static struct quirk_entry quirk_acer_aspire_1520 = {388 .brightness = -1,389};390 391static struct quirk_entry quirk_acer_travelmate_2490 = {392 .mailled = 1,393};394 395static struct quirk_entry quirk_acer_predator_ph315_53 = {396 .turbo = 1,397 .cpu_fans = 1,398 .gpu_fans = 1,399};400 401static struct quirk_entry quirk_acer_predator_v4 = {402 .predator_v4 = 1,403};404 405/* This AMW0 laptop has no bluetooth */406static struct quirk_entry quirk_medion_md_98300 = {407 .wireless = 1,408};409 410static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {411 .wireless = 2,412};413 414static struct quirk_entry quirk_lenovo_ideapad_s205 = {415 .wireless = 3,416};417 418/* The Aspire One has a dummy ACPI-WMI interface - disable it */419static const struct dmi_system_id acer_blacklist[] __initconst = {420 {421 .ident = "Acer Aspire One (SSD)",422 .matches = {423 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),424 DMI_MATCH(DMI_PRODUCT_NAME, "AOA110"),425 },426 },427 {428 .ident = "Acer Aspire One (HDD)",429 .matches = {430 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),431 DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),432 },433 },434 {}435};436 437static const struct dmi_system_id amw0_whitelist[] __initconst = {438 {439 .ident = "Acer",440 .matches = {441 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),442 },443 },444 {445 .ident = "Gateway",446 .matches = {447 DMI_MATCH(DMI_SYS_VENDOR, "Gateway"),448 },449 },450 {451 .ident = "Packard Bell",452 .matches = {453 DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"),454 },455 },456 {}457};458 459/*460 * This quirk table is only for Acer/Gateway/Packard Bell family461 * that those machines are supported by acer-wmi driver.462 */463static const struct dmi_system_id acer_quirks[] __initconst = {464 {465 .callback = dmi_matched,466 .ident = "Acer Aspire 1360",467 .matches = {468 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),469 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),470 },471 .driver_data = &quirk_acer_aspire_1520,472 },473 {474 .callback = dmi_matched,475 .ident = "Acer Aspire 1520",476 .matches = {477 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),478 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1520"),479 },480 .driver_data = &quirk_acer_aspire_1520,481 },482 {483 .callback = dmi_matched,484 .ident = "Acer Aspire 3100",485 .matches = {486 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),487 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"),488 },489 .driver_data = &quirk_acer_travelmate_2490,490 },491 {492 .callback = dmi_matched,493 .ident = "Acer Aspire 3610",494 .matches = {495 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),496 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3610"),497 },498 .driver_data = &quirk_acer_travelmate_2490,499 },500 {501 .callback = dmi_matched,502 .ident = "Acer Aspire 5100",503 .matches = {504 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),505 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),506 },507 .driver_data = &quirk_acer_travelmate_2490,508 },509 {510 .callback = dmi_matched,511 .ident = "Acer Aspire 5610",512 .matches = {513 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),514 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),515 },516 .driver_data = &quirk_acer_travelmate_2490,517 },518 {519 .callback = dmi_matched,520 .ident = "Acer Aspire 5630",521 .matches = {522 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),523 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),524 },525 .driver_data = &quirk_acer_travelmate_2490,526 },527 {528 .callback = dmi_matched,529 .ident = "Acer Aspire 5650",530 .matches = {531 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),532 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),533 },534 .driver_data = &quirk_acer_travelmate_2490,535 },536 {537 .callback = dmi_matched,538 .ident = "Acer Aspire 5680",539 .matches = {540 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),541 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),542 },543 .driver_data = &quirk_acer_travelmate_2490,544 },545 {546 .callback = dmi_matched,547 .ident = "Acer Aspire 9110",548 .matches = {549 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),550 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),551 },552 .driver_data = &quirk_acer_travelmate_2490,553 },554 {555 .callback = dmi_matched,556 .ident = "Acer TravelMate 2490",557 .matches = {558 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),559 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),560 },561 .driver_data = &quirk_acer_travelmate_2490,562 },563 {564 .callback = dmi_matched,565 .ident = "Acer TravelMate 4200",566 .matches = {567 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),568 DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4200"),569 },570 .driver_data = &quirk_acer_travelmate_2490,571 },572 {573 .callback = dmi_matched,574 .ident = "Acer Predator PH315-53",575 .matches = {576 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),577 DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH315-53"),578 },579 .driver_data = &quirk_acer_predator_ph315_53,580 },581 {582 .callback = dmi_matched,583 .ident = "Acer Predator PHN16-71",584 .matches = {585 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),586 DMI_MATCH(DMI_PRODUCT_NAME, "Predator PHN16-71"),587 },588 .driver_data = &quirk_acer_predator_v4,589 },590 {591 .callback = dmi_matched,592 .ident = "Acer Predator PH16-71",593 .matches = {594 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),595 DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH16-71"),596 },597 .driver_data = &quirk_acer_predator_v4,598 },599 {600 .callback = dmi_matched,601 .ident = "Acer Predator PH18-71",602 .matches = {603 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),604 DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH18-71"),605 },606 .driver_data = &quirk_acer_predator_v4,607 },608 {609 .callback = set_force_caps,610 .ident = "Acer Aspire Switch 10E SW3-016",611 .matches = {612 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),613 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-016"),614 },615 .driver_data = (void *)ACER_CAP_KBD_DOCK,616 },617 {618 .callback = set_force_caps,619 .ident = "Acer Aspire Switch 10 SW5-012",620 .matches = {621 DMI_MATCH(DMI_SYS_VENDOR, "Acer"),622 DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),623 },624 .driver_data = (void *)ACER_CAP_KBD_DOCK,625 },626 {627 .callback = set_force_caps,628 .ident = "Acer Aspire Switch V 10 SW5-017",629 .matches = {630 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),631 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"),632 },633 .driver_data = (void *)ACER_CAP_KBD_DOCK,634 },635 {636 .callback = set_force_caps,637 .ident = "Acer One 10 (S1003)",638 .matches = {639 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),640 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),641 },642 .driver_data = (void *)ACER_CAP_KBD_DOCK,643 },644 {}645};646 647/*648 * This quirk list is for those non-acer machines that have AMW0_GUID1649 * but supported by acer-wmi in past days. Keeping this quirk list here650 * is only for backward compatible. Please do not add new machine to651 * here anymore. Those non-acer machines should be supported by652 * appropriate wmi drivers.653 */654static const struct dmi_system_id non_acer_quirks[] __initconst = {655 {656 .callback = dmi_matched,657 .ident = "Fujitsu Siemens Amilo Li 1718",658 .matches = {659 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),660 DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Li 1718"),661 },662 .driver_data = &quirk_fujitsu_amilo_li_1718,663 },664 {665 .callback = dmi_matched,666 .ident = "Medion MD 98300",667 .matches = {668 DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),669 DMI_MATCH(DMI_PRODUCT_NAME, "WAM2030"),670 },671 .driver_data = &quirk_medion_md_98300,672 },673 {674 .callback = dmi_matched,675 .ident = "Lenovo Ideapad S205",676 .matches = {677 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),678 DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),679 },680 .driver_data = &quirk_lenovo_ideapad_s205,681 },682 {683 .callback = dmi_matched,684 .ident = "Lenovo Ideapad S205 (Brazos)",685 .matches = {686 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),687 DMI_MATCH(DMI_PRODUCT_NAME, "Brazos"),688 },689 .driver_data = &quirk_lenovo_ideapad_s205,690 },691 {692 .callback = dmi_matched,693 .ident = "Lenovo 3000 N200",694 .matches = {695 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),696 DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),697 },698 .driver_data = &quirk_fujitsu_amilo_li_1718,699 },700 {701 .callback = dmi_matched,702 .ident = "Lenovo Ideapad S205-10382JG",703 .matches = {704 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),705 DMI_MATCH(DMI_PRODUCT_NAME, "10382JG"),706 },707 .driver_data = &quirk_lenovo_ideapad_s205,708 },709 {710 .callback = dmi_matched,711 .ident = "Lenovo Ideapad S205-1038DPG",712 .matches = {713 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),714 DMI_MATCH(DMI_PRODUCT_NAME, "1038DPG"),715 },716 .driver_data = &quirk_lenovo_ideapad_s205,717 },718 {}719};720 721static struct platform_profile_handler platform_profile_handler;722static bool platform_profile_support;723 724/*725 * The profile used before turbo mode. This variable is needed for726 * returning from turbo mode when the mode key is in toggle mode.727 */728static int last_non_turbo_profile;729 730enum acer_predator_v4_thermal_profile_ec {731 ACER_PREDATOR_V4_THERMAL_PROFILE_ECO = 0x04,732 ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO = 0x03,733 ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE = 0x02,734 ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET = 0x01,735 ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED = 0x00,736};737 738enum acer_predator_v4_thermal_profile_wmi {739 ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI = 0x060B,740 ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI = 0x050B,741 ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE_WMI = 0x040B,742 ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET_WMI = 0x0B,743 ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI = 0x010B,744};745 746/* Find which quirks are needed for a particular vendor/ model pair */747static void __init find_quirks(void)748{749 if (predator_v4) {750 quirks = &quirk_acer_predator_v4;751 } else if (!force_series) {752 dmi_check_system(acer_quirks);753 dmi_check_system(non_acer_quirks);754 } else if (force_series == 2490) {755 quirks = &quirk_acer_travelmate_2490;756 }757 758 if (quirks == NULL)759 quirks = &quirk_unknown;760}761 762/*763 * General interface convenience methods764 */765 766static bool has_cap(u32 cap)767{768 return interface->capability & cap;769}770 771/*772 * AMW0 (V1) interface773 */774struct wmab_args {775 u32 eax;776 u32 ebx;777 u32 ecx;778 u32 edx;779};780 781struct wmab_ret {782 u32 eax;783 u32 ebx;784 u32 ecx;785 u32 edx;786 u32 eex;787};788 789static acpi_status wmab_execute(struct wmab_args *regbuf,790struct acpi_buffer *result)791{792 struct acpi_buffer input;793 acpi_status status;794 input.length = sizeof(struct wmab_args);795 input.pointer = (u8 *)regbuf;796 797 status = wmi_evaluate_method(AMW0_GUID1, 0, 1, &input, result);798 799 return status;800}801 802static acpi_status AMW0_get_u32(u32 *value, u32 cap)803{804 int err;805 u8 result;806 807 switch (cap) {808 case ACER_CAP_MAILLED:809 switch (quirks->mailled) {810 default:811 err = ec_read(0xA, &result);812 if (err)813 return AE_ERROR;814 *value = (result >> 7) & 0x1;815 return AE_OK;816 }817 break;818 case ACER_CAP_WIRELESS:819 switch (quirks->wireless) {820 case 1:821 err = ec_read(0x7B, &result);822 if (err)823 return AE_ERROR;824 *value = result & 0x1;825 return AE_OK;826 case 2:827 err = ec_read(0x71, &result);828 if (err)829 return AE_ERROR;830 *value = result & 0x1;831 return AE_OK;832 case 3:833 err = ec_read(0x78, &result);834 if (err)835 return AE_ERROR;836 *value = result & 0x1;837 return AE_OK;838 default:839 err = ec_read(0xA, &result);840 if (err)841 return AE_ERROR;842 *value = (result >> 2) & 0x1;843 return AE_OK;844 }845 break;846 case ACER_CAP_BLUETOOTH:847 switch (quirks->bluetooth) {848 default:849 err = ec_read(0xA, &result);850 if (err)851 return AE_ERROR;852 *value = (result >> 4) & 0x1;853 return AE_OK;854 }855 break;856 case ACER_CAP_BRIGHTNESS:857 switch (quirks->brightness) {858 default:859 err = ec_read(0x83, &result);860 if (err)861 return AE_ERROR;862 *value = result;863 return AE_OK;864 }865 break;866 default:867 return AE_ERROR;868 }869 return AE_OK;870}871 872static acpi_status AMW0_set_u32(u32 value, u32 cap)873{874 struct wmab_args args;875 876 args.eax = ACER_AMW0_WRITE;877 args.ebx = value ? (1<<8) : 0;878 args.ecx = args.edx = 0;879 880 switch (cap) {881 case ACER_CAP_MAILLED:882 if (value > 1)883 return AE_BAD_PARAMETER;884 args.ebx |= ACER_AMW0_MAILLED_MASK;885 break;886 case ACER_CAP_WIRELESS:887 if (value > 1)888 return AE_BAD_PARAMETER;889 args.ebx |= ACER_AMW0_WIRELESS_MASK;890 break;891 case ACER_CAP_BLUETOOTH:892 if (value > 1)893 return AE_BAD_PARAMETER;894 args.ebx |= ACER_AMW0_BLUETOOTH_MASK;895 break;896 case ACER_CAP_BRIGHTNESS:897 if (value > max_brightness)898 return AE_BAD_PARAMETER;899 switch (quirks->brightness) {900 default:901 return ec_write(0x83, value);902 }903 default:904 return AE_ERROR;905 }906 907 /* Actually do the set */908 return wmab_execute(&args, NULL);909}910 911static acpi_status __init AMW0_find_mailled(void)912{913 struct wmab_args args;914 struct wmab_ret ret;915 acpi_status status = AE_OK;916 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };917 union acpi_object *obj;918 919 args.eax = 0x86;920 args.ebx = args.ecx = args.edx = 0;921 922 status = wmab_execute(&args, &out);923 if (ACPI_FAILURE(status))924 return status;925 926 obj = (union acpi_object *) out.pointer;927 if (obj && obj->type == ACPI_TYPE_BUFFER &&928 obj->buffer.length == sizeof(struct wmab_ret)) {929 ret = *((struct wmab_ret *) obj->buffer.pointer);930 } else {931 kfree(out.pointer);932 return AE_ERROR;933 }934 935 if (ret.eex & 0x1)936 interface->capability |= ACER_CAP_MAILLED;937 938 kfree(out.pointer);939 940 return AE_OK;941}942 943static const struct acpi_device_id norfkill_ids[] __initconst = {944 { "VPC2004", 0},945 { "IBM0068", 0},946 { "LEN0068", 0},947 { "SNY5001", 0}, /* sony-laptop in charge */948 { "HPQ6601", 0},949 { "", 0},950};951 952static int __init AMW0_set_cap_acpi_check_device(void)953{954 const struct acpi_device_id *id;955 956 for (id = norfkill_ids; id->id[0]; id++)957 if (acpi_dev_found(id->id))958 return true;959 960 return false;961}962 963static acpi_status __init AMW0_set_capabilities(void)964{965 struct wmab_args args;966 struct wmab_ret ret;967 acpi_status status;968 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };969 union acpi_object *obj;970 971 /*972 * On laptops with this strange GUID (non Acer), normal probing doesn't973 * work.974 */975 if (wmi_has_guid(AMW0_GUID2)) {976 if ((quirks != &quirk_unknown) ||977 !AMW0_set_cap_acpi_check_device())978 interface->capability |= ACER_CAP_WIRELESS;979 return AE_OK;980 }981 982 args.eax = ACER_AMW0_WRITE;983 args.ecx = args.edx = 0;984 985 args.ebx = 0xa2 << 8;986 args.ebx |= ACER_AMW0_WIRELESS_MASK;987 988 status = wmab_execute(&args, &out);989 if (ACPI_FAILURE(status))990 return status;991 992 obj = out.pointer;993 if (obj && obj->type == ACPI_TYPE_BUFFER &&994 obj->buffer.length == sizeof(struct wmab_ret)) {995 ret = *((struct wmab_ret *) obj->buffer.pointer);996 } else {997 status = AE_ERROR;998 goto out;999 }1000 1001 if (ret.eax & 0x1)1002 interface->capability |= ACER_CAP_WIRELESS;1003 1004 args.ebx = 2 << 8;1005 args.ebx |= ACER_AMW0_BLUETOOTH_MASK;1006 1007 /*1008 * It's ok to use existing buffer for next wmab_execute call.1009 * But we need to kfree(out.pointer) if next wmab_execute fail.1010 */1011 status = wmab_execute(&args, &out);1012 if (ACPI_FAILURE(status))1013 goto out;1014 1015 obj = (union acpi_object *) out.pointer;1016 if (obj && obj->type == ACPI_TYPE_BUFFER1017 && obj->buffer.length == sizeof(struct wmab_ret)) {1018 ret = *((struct wmab_ret *) obj->buffer.pointer);1019 } else {1020 status = AE_ERROR;1021 goto out;1022 }1023 1024 if (ret.eax & 0x1)1025 interface->capability |= ACER_CAP_BLUETOOTH;1026 1027 /*1028 * This appears to be safe to enable, since all Wistron based laptops1029 * appear to use the same EC register for brightness, even if they1030 * differ for wireless, etc1031 */1032 if (quirks->brightness >= 0)1033 interface->capability |= ACER_CAP_BRIGHTNESS;1034 1035 status = AE_OK;1036out:1037 kfree(out.pointer);1038 return status;1039}1040 1041static struct wmi_interface AMW0_interface = {1042 .type = ACER_AMW0,1043};1044 1045static struct wmi_interface AMW0_V2_interface = {1046 .type = ACER_AMW0_V2,1047};1048 1049/*1050 * New interface (The WMID interface)1051 */1052static acpi_status1053WMI_execute_u32(u32 method_id, u32 in, u32 *out)1054{1055 struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };1056 struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };1057 union acpi_object *obj;1058 u32 tmp = 0;1059 acpi_status status;1060 1061 status = wmi_evaluate_method(WMID_GUID1, 0, method_id, &input, &result);1062 1063 if (ACPI_FAILURE(status))1064 return status;1065 1066 obj = (union acpi_object *) result.pointer;1067 if (obj) {1068 if (obj->type == ACPI_TYPE_BUFFER &&1069 (obj->buffer.length == sizeof(u32) ||1070 obj->buffer.length == sizeof(u64))) {1071 tmp = *((u32 *) obj->buffer.pointer);1072 } else if (obj->type == ACPI_TYPE_INTEGER) {1073 tmp = (u32) obj->integer.value;1074 }1075 }1076 1077 if (out)1078 *out = tmp;1079 1080 kfree(result.pointer);1081 1082 return status;1083}1084 1085static acpi_status WMID_get_u32(u32 *value, u32 cap)1086{1087 acpi_status status;1088 u8 tmp;1089 u32 result, method_id = 0;1090 1091 switch (cap) {1092 case ACER_CAP_WIRELESS:1093 method_id = ACER_WMID_GET_WIRELESS_METHODID;1094 break;1095 case ACER_CAP_BLUETOOTH:1096 method_id = ACER_WMID_GET_BLUETOOTH_METHODID;1097 break;1098 case ACER_CAP_BRIGHTNESS:1099 method_id = ACER_WMID_GET_BRIGHTNESS_METHODID;1100 break;1101 case ACER_CAP_THREEG:1102 method_id = ACER_WMID_GET_THREEG_METHODID;1103 break;1104 case ACER_CAP_MAILLED:1105 if (quirks->mailled == 1) {1106 ec_read(0x9f, &tmp);1107 *value = tmp & 0x1;1108 return 0;1109 }1110 fallthrough;1111 default:1112 return AE_ERROR;1113 }1114 status = WMI_execute_u32(method_id, 0, &result);1115 1116 if (ACPI_SUCCESS(status))1117 *value = (u8)result;1118 1119 return status;1120}1121 1122static acpi_status WMID_set_u32(u32 value, u32 cap)1123{1124 u32 method_id = 0;1125 char param;1126 1127 switch (cap) {1128 case ACER_CAP_BRIGHTNESS:1129 if (value > max_brightness)1130 return AE_BAD_PARAMETER;1131 method_id = ACER_WMID_SET_BRIGHTNESS_METHODID;1132 break;1133 case ACER_CAP_WIRELESS:1134 if (value > 1)1135 return AE_BAD_PARAMETER;1136 method_id = ACER_WMID_SET_WIRELESS_METHODID;1137 break;1138 case ACER_CAP_BLUETOOTH:1139 if (value > 1)1140 return AE_BAD_PARAMETER;1141 method_id = ACER_WMID_SET_BLUETOOTH_METHODID;1142 break;1143 case ACER_CAP_THREEG:1144 if (value > 1)1145 return AE_BAD_PARAMETER;1146 method_id = ACER_WMID_SET_THREEG_METHODID;1147 break;1148 case ACER_CAP_MAILLED:1149 if (value > 1)1150 return AE_BAD_PARAMETER;1151 if (quirks->mailled == 1) {1152 param = value ? 0x92 : 0x93;1153 i8042_lock_chip();1154 i8042_command(¶m, 0x1059);1155 i8042_unlock_chip();1156 return 0;1157 }1158 break;1159 default:1160 return AE_ERROR;1161 }1162 return WMI_execute_u32(method_id, (u32)value, NULL);1163}1164 1165static acpi_status wmid3_get_device_status(u32 *value, u16 device)1166{1167 struct wmid3_gds_return_value return_value;1168 acpi_status status;1169 union acpi_object *obj;1170 struct wmid3_gds_get_input_param params = {1171 .function_num = 0x1,1172 .hotkey_number = commun_fn_key_number,1173 .devices = device,1174 };1175 struct acpi_buffer input = {1176 sizeof(struct wmid3_gds_get_input_param),1177 ¶ms1178 };1179 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };1180 1181 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input, &output);1182 if (ACPI_FAILURE(status))1183 return status;1184 1185 obj = output.pointer;1186 1187 if (!obj)1188 return AE_ERROR;1189 else if (obj->type != ACPI_TYPE_BUFFER) {1190 kfree(obj);1191 return AE_ERROR;1192 }1193 if (obj->buffer.length != 8) {1194 pr_warn("Unknown buffer length %d\n", obj->buffer.length);1195 kfree(obj);1196 return AE_ERROR;1197 }1198 1199 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);1200 kfree(obj);1201 1202 if (return_value.error_code || return_value.ec_return_value)1203 pr_warn("Get 0x%x Device Status failed: 0x%x - 0x%x\n",1204 device,1205 return_value.error_code,1206 return_value.ec_return_value);1207 else1208 *value = !!(return_value.devices & device);1209 1210 return status;1211}1212 1213static acpi_status wmid_v2_get_u32(u32 *value, u32 cap)1214{1215 u16 device;1216 1217 switch (cap) {1218 case ACER_CAP_WIRELESS:1219 device = ACER_WMID3_GDS_WIRELESS;1220 break;1221 case ACER_CAP_BLUETOOTH:1222 device = ACER_WMID3_GDS_BLUETOOTH;1223 break;1224 case ACER_CAP_THREEG:1225 device = ACER_WMID3_GDS_THREEG;1226 break;1227 default:1228 return AE_ERROR;1229 }1230 return wmid3_get_device_status(value, device);1231}1232 1233static acpi_status wmid3_set_device_status(u32 value, u16 device)1234{1235 struct wmid3_gds_return_value return_value;1236 acpi_status status;1237 union acpi_object *obj;1238 u16 devices;1239 struct wmid3_gds_get_input_param get_params = {1240 .function_num = 0x1,1241 .hotkey_number = commun_fn_key_number,1242 .devices = commun_func_bitmap,1243 };1244 struct acpi_buffer get_input = {1245 sizeof(struct wmid3_gds_get_input_param),1246 &get_params1247 };1248 struct wmid3_gds_set_input_param set_params = {1249 .function_num = 0x2,1250 .hotkey_number = commun_fn_key_number,1251 .devices = commun_func_bitmap,1252 };1253 struct acpi_buffer set_input = {1254 sizeof(struct wmid3_gds_set_input_param),1255 &set_params1256 };1257 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };1258 struct acpi_buffer output2 = { ACPI_ALLOCATE_BUFFER, NULL };1259 1260 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &get_input, &output);1261 if (ACPI_FAILURE(status))1262 return status;1263 1264 obj = output.pointer;1265 1266 if (!obj)1267 return AE_ERROR;1268 else if (obj->type != ACPI_TYPE_BUFFER) {1269 kfree(obj);1270 return AE_ERROR;1271 }1272 if (obj->buffer.length != 8) {1273 pr_warn("Unknown buffer length %d\n", obj->buffer.length);1274 kfree(obj);1275 return AE_ERROR;1276 }1277 1278 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);1279 kfree(obj);1280 1281 if (return_value.error_code || return_value.ec_return_value) {1282 pr_warn("Get Current Device Status failed: 0x%x - 0x%x\n",1283 return_value.error_code,1284 return_value.ec_return_value);1285 return status;1286 }1287 1288 devices = return_value.devices;1289 set_params.devices = (value) ? (devices | device) : (devices & ~device);1290 1291 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &set_input, &output2);1292 if (ACPI_FAILURE(status))1293 return status;1294 1295 obj = output2.pointer;1296 1297 if (!obj)1298 return AE_ERROR;1299 else if (obj->type != ACPI_TYPE_BUFFER) {1300 kfree(obj);1301 return AE_ERROR;1302 }1303 if (obj->buffer.length != 4) {1304 pr_warn("Unknown buffer length %d\n", obj->buffer.length);1305 kfree(obj);1306 return AE_ERROR;1307 }1308 1309 return_value = *((struct wmid3_gds_return_value *)obj->buffer.pointer);1310 kfree(obj);1311 1312 if (return_value.error_code || return_value.ec_return_value)1313 pr_warn("Set Device Status failed: 0x%x - 0x%x\n",1314 return_value.error_code,1315 return_value.ec_return_value);1316 1317 return status;1318}1319 1320static acpi_status wmid_v2_set_u32(u32 value, u32 cap)1321{1322 u16 device;1323 1324 switch (cap) {1325 case ACER_CAP_WIRELESS:1326 device = ACER_WMID3_GDS_WIRELESS;1327 break;1328 case ACER_CAP_BLUETOOTH:1329 device = ACER_WMID3_GDS_BLUETOOTH;1330 break;1331 case ACER_CAP_THREEG:1332 device = ACER_WMID3_GDS_THREEG;1333 break;1334 default:1335 return AE_ERROR;1336 }1337 return wmid3_set_device_status(value, device);1338}1339 1340static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d)1341{1342 struct hotkey_function_type_aa *type_aa;1343 1344 /* We are looking for OEM-specific Type AAh */1345 if (header->type != 0xAA)1346 return;1347 1348 has_type_aa = true;1349 type_aa = (struct hotkey_function_type_aa *) header;1350 1351 pr_info("Function bitmap for Communication Button: 0x%x\n",1352 type_aa->commun_func_bitmap);1353 commun_func_bitmap = type_aa->commun_func_bitmap;1354 1355 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)1356 interface->capability |= ACER_CAP_WIRELESS;1357 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_THREEG)1358 interface->capability |= ACER_CAP_THREEG;1359 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)1360 interface->capability |= ACER_CAP_BLUETOOTH;1361 if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN)1362 commun_func_bitmap &= ~ACER_WMID3_GDS_RFBTN;1363 1364 commun_fn_key_number = type_aa->commun_fn_key_number;1365}1366 1367static acpi_status __init WMID_set_capabilities(void)1368{1369 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};1370 union acpi_object *obj;1371 acpi_status status;1372 u32 devices;1373 1374 status = wmi_query_block(WMID_GUID2, 0, &out);1375 if (ACPI_FAILURE(status))1376 return status;1377 1378 obj = (union acpi_object *) out.pointer;1379 if (obj) {1380 if (obj->type == ACPI_TYPE_BUFFER &&1381 (obj->buffer.length == sizeof(u32) ||1382 obj->buffer.length == sizeof(u64))) {1383 devices = *((u32 *) obj->buffer.pointer);1384 } else if (obj->type == ACPI_TYPE_INTEGER) {1385 devices = (u32) obj->integer.value;1386 } else {1387 kfree(out.pointer);1388 return AE_ERROR;1389 }1390 } else {1391 kfree(out.pointer);1392 return AE_ERROR;1393 }1394 1395 pr_info("Function bitmap for Communication Device: 0x%x\n", devices);1396 if (devices & 0x07)1397 interface->capability |= ACER_CAP_WIRELESS;1398 if (devices & 0x40)1399 interface->capability |= ACER_CAP_THREEG;1400 if (devices & 0x10)1401 interface->capability |= ACER_CAP_BLUETOOTH;1402 1403 if (!(devices & 0x20))1404 max_brightness = 0x9;1405 1406 kfree(out.pointer);1407 return status;1408}1409 1410static struct wmi_interface wmid_interface = {1411 .type = ACER_WMID,1412};1413 1414static struct wmi_interface wmid_v2_interface = {1415 .type = ACER_WMID_v2,1416};1417 1418/*1419 * WMID Gaming interface1420 */1421 1422static acpi_status1423WMI_gaming_execute_u64(u32 method_id, u64 in, u64 *out)1424{1425 struct acpi_buffer input = { (acpi_size) sizeof(u64), (void *)(&in) };1426 struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };1427 union acpi_object *obj;1428 u64 tmp = 0;1429 acpi_status status;1430 1431 status = wmi_evaluate_method(WMID_GUID4, 0, method_id, &input, &result);1432 1433 if (ACPI_FAILURE(status))1434 return status;1435 obj = (union acpi_object *) result.pointer;1436 1437 if (obj) {1438 if (obj->type == ACPI_TYPE_BUFFER) {1439 if (obj->buffer.length == sizeof(u32))1440 tmp = *((u32 *) obj->buffer.pointer);1441 else if (obj->buffer.length == sizeof(u64))1442 tmp = *((u64 *) obj->buffer.pointer);1443 } else if (obj->type == ACPI_TYPE_INTEGER) {1444 tmp = (u64) obj->integer.value;1445 }1446 }1447 1448 if (out)1449 *out = tmp;1450 1451 kfree(result.pointer);1452 1453 return status;1454}1455 1456static acpi_status WMID_gaming_set_u64(u64 value, u32 cap)1457{1458 u32 method_id = 0;1459 1460 if (!(interface->capability & cap))1461 return AE_BAD_PARAMETER;1462 1463 switch (cap) {1464 case ACER_CAP_TURBO_LED:1465 method_id = ACER_WMID_SET_GAMING_LED_METHODID;1466 break;1467 case ACER_CAP_TURBO_FAN:1468 method_id = ACER_WMID_SET_GAMING_FAN_BEHAVIOR;1469 break;1470 case ACER_CAP_TURBO_OC:1471 method_id = ACER_WMID_SET_GAMING_MISC_SETTING_METHODID;1472 break;1473 default:1474 return AE_BAD_PARAMETER;1475 }1476 1477 return WMI_gaming_execute_u64(method_id, value, NULL);1478}1479 1480static acpi_status WMID_gaming_get_u64(u64 *value, u32 cap)1481{1482 acpi_status status;1483 u64 result;1484 u64 input;1485 u32 method_id;1486 1487 if (!(interface->capability & cap))1488 return AE_BAD_PARAMETER;1489 1490 switch (cap) {1491 case ACER_CAP_TURBO_LED:1492 method_id = ACER_WMID_GET_GAMING_LED_METHODID;1493 input = 0x1;1494 break;1495 default:1496 return AE_BAD_PARAMETER;1497 }1498 status = WMI_gaming_execute_u64(method_id, input, &result);1499 if (ACPI_SUCCESS(status))1500 *value = (u64) result;1501 1502 return status;1503}1504 1505static void WMID_gaming_set_fan_mode(u8 fan_mode)1506{1507 /* fan_mode = 1 is used for auto, fan_mode = 2 used for turbo*/1508 u64 gpu_fan_config1 = 0, gpu_fan_config2 = 0;1509 int i;1510 1511 if (quirks->cpu_fans > 0)1512 gpu_fan_config2 |= 1;1513 for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i)1514 gpu_fan_config2 |= 1 << (i + 1);1515 for (i = 0; i < quirks->gpu_fans; ++i)1516 gpu_fan_config2 |= 1 << (i + 3);1517 if (quirks->cpu_fans > 0)1518 gpu_fan_config1 |= fan_mode;1519 for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i)1520 gpu_fan_config1 |= fan_mode << (2 * i + 2);1521 for (i = 0; i < quirks->gpu_fans; ++i)1522 gpu_fan_config1 |= fan_mode << (2 * i + 6);1523 WMID_gaming_set_u64(gpu_fan_config2 | gpu_fan_config1 << 16, ACER_CAP_TURBO_FAN);1524}1525 1526/*1527 * Generic Device (interface-independent)1528 */1529 1530static acpi_status get_u32(u32 *value, u32 cap)1531{1532 acpi_status status = AE_ERROR;1533 1534 switch (interface->type) {1535 case ACER_AMW0:1536 status = AMW0_get_u32(value, cap);1537 break;1538 case ACER_AMW0_V2:1539 if (cap == ACER_CAP_MAILLED) {1540 status = AMW0_get_u32(value, cap);1541 break;1542 }1543 fallthrough;1544 case ACER_WMID:1545 status = WMID_get_u32(value, cap);1546 break;1547 case ACER_WMID_v2:1548 if (cap & (ACER_CAP_WIRELESS |1549 ACER_CAP_BLUETOOTH |1550 ACER_CAP_THREEG))1551 status = wmid_v2_get_u32(value, cap);1552 else if (wmi_has_guid(WMID_GUID2))1553 status = WMID_get_u32(value, cap);1554 break;1555 }1556 1557 return status;1558}1559 1560static acpi_status set_u32(u32 value, u32 cap)1561{1562 acpi_status status;1563 1564 if (interface->capability & cap) {1565 switch (interface->type) {1566 case ACER_AMW0:1567 return AMW0_set_u32(value, cap);1568 case ACER_AMW0_V2:1569 if (cap == ACER_CAP_MAILLED)1570 return AMW0_set_u32(value, cap);1571 1572 /*1573 * On some models, some WMID methods don't toggle1574 * properly. For those cases, we want to run the AMW01575 * method afterwards to be certain we've really toggled1576 * the device state.1577 */1578 if (cap == ACER_CAP_WIRELESS ||1579 cap == ACER_CAP_BLUETOOTH) {1580 status = WMID_set_u32(value, cap);1581 if (ACPI_FAILURE(status))1582 return status;1583 1584 return AMW0_set_u32(value, cap);1585 }1586 fallthrough;1587 case ACER_WMID:1588 return WMID_set_u32(value, cap);1589 case ACER_WMID_v2:1590 if (cap & (ACER_CAP_WIRELESS |1591 ACER_CAP_BLUETOOTH |1592 ACER_CAP_THREEG))1593 return wmid_v2_set_u32(value, cap);1594 else if (wmi_has_guid(WMID_GUID2))1595 return WMID_set_u32(value, cap);1596 fallthrough;1597 default:1598 return AE_BAD_PARAMETER;1599 }1600 }1601 return AE_BAD_PARAMETER;1602}1603 1604static void __init acer_commandline_init(void)1605{1606 /*1607 * These will all fail silently if the value given is invalid, or the1608 * capability isn't available on the given interface1609 */1610 if (mailled >= 0)1611 set_u32(mailled, ACER_CAP_MAILLED);1612 if (!has_type_aa && threeg >= 0)1613 set_u32(threeg, ACER_CAP_THREEG);1614 if (brightness >= 0)1615 set_u32(brightness, ACER_CAP_BRIGHTNESS);1616}1617 1618/*1619 * LED device (Mail LED only, no other LEDs known yet)1620 */1621static void mail_led_set(struct led_classdev *led_cdev,1622enum led_brightness value)1623{1624 set_u32(value, ACER_CAP_MAILLED);1625}1626 1627static struct led_classdev mail_led = {1628 .name = "acer-wmi::mail",1629 .brightness_set = mail_led_set,1630};1631 1632static int acer_led_init(struct device *dev)1633{1634 return led_classdev_register(dev, &mail_led);1635}1636 1637static void acer_led_exit(void)1638{1639 set_u32(LED_OFF, ACER_CAP_MAILLED);1640 led_classdev_unregister(&mail_led);1641}1642 1643/*1644 * Backlight device1645 */1646static struct backlight_device *acer_backlight_device;1647 1648static int read_brightness(struct backlight_device *bd)1649{1650 u32 value;1651 get_u32(&value, ACER_CAP_BRIGHTNESS);1652 return value;1653}1654 1655static int update_bl_status(struct backlight_device *bd)1656{1657 int intensity = backlight_get_brightness(bd);1658 1659 set_u32(intensity, ACER_CAP_BRIGHTNESS);1660 1661 return 0;1662}1663 1664static const struct backlight_ops acer_bl_ops = {1665 .get_brightness = read_brightness,1666 .update_status = update_bl_status,1667};1668 1669static int acer_backlight_init(struct device *dev)1670{1671 struct backlight_properties props;1672 struct backlight_device *bd;1673 1674 memset(&props, 0, sizeof(struct backlight_properties));1675 props.type = BACKLIGHT_PLATFORM;1676 props.max_brightness = max_brightness;1677 bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,1678 &props);1679 if (IS_ERR(bd)) {1680 pr_err("Could not register Acer backlight device\n");1681 acer_backlight_device = NULL;1682 return PTR_ERR(bd);1683 }1684 1685 acer_backlight_device = bd;1686 1687 bd->props.power = BACKLIGHT_POWER_ON;1688 bd->props.brightness = read_brightness(bd);1689 backlight_update_status(bd);1690 return 0;1691}1692 1693static void acer_backlight_exit(void)1694{1695 backlight_device_unregister(acer_backlight_device);1696}1697 1698/*1699 * Accelerometer device1700 */1701static acpi_handle gsensor_handle;1702 1703static int acer_gsensor_init(void)1704{1705 acpi_status status;1706 struct acpi_buffer output;1707 union acpi_object out_obj;1708 1709 output.length = sizeof(out_obj);1710 output.pointer = &out_obj;1711 status = acpi_evaluate_object(gsensor_handle, "_INI", NULL, &output);1712 if (ACPI_FAILURE(status))1713 return -1;1714 1715 return 0;1716}1717 1718static int acer_gsensor_open(struct input_dev *input)1719{1720 return acer_gsensor_init();1721}1722 1723static int acer_gsensor_event(void)1724{1725 acpi_status status;1726 struct acpi_buffer output;1727 union acpi_object out_obj[5];1728 1729 if (!acer_wmi_accel_dev)1730 return -1;1731 1732 output.length = sizeof(out_obj);1733 output.pointer = out_obj;1734 1735 status = acpi_evaluate_object(gsensor_handle, "RDVL", NULL, &output);1736 if (ACPI_FAILURE(status))1737 return -1;1738 1739 if (out_obj->package.count != 4)1740 return -1;1741 1742 input_report_abs(acer_wmi_accel_dev, ABS_X,1743 (s16)out_obj->package.elements[0].integer.value);1744 input_report_abs(acer_wmi_accel_dev, ABS_Y,1745 (s16)out_obj->package.elements[1].integer.value);1746 input_report_abs(acer_wmi_accel_dev, ABS_Z,1747 (s16)out_obj->package.elements[2].integer.value);1748 input_sync(acer_wmi_accel_dev);1749 return 0;1750}1751 1752static int acer_get_fan_speed(int fan)1753{1754 if (quirks->predator_v4) {1755 acpi_status status;1756 u64 fanspeed;1757 1758 status = WMI_gaming_execute_u64(1759 ACER_WMID_GET_GAMING_SYS_INFO_METHODID,1760 fan == 0 ? ACER_WMID_CMD_GET_PREDATOR_V4_CPU_FAN_SPEED :1761 ACER_WMID_CMD_GET_PREDATOR_V4_GPU_FAN_SPEED,1762 &fanspeed);1763 1764 if (ACPI_FAILURE(status))1765 return -EIO;1766 1767 return FIELD_GET(ACER_PREDATOR_V4_FAN_SPEED_READ_BIT_MASK, fanspeed);1768 }1769 return -EOPNOTSUPP;1770}1771 1772/*1773 * Predator series turbo button1774 */1775static int acer_toggle_turbo(void)1776{1777 u64 turbo_led_state;1778 1779 /* Get current state from turbo button */1780 if (ACPI_FAILURE(WMID_gaming_get_u64(&turbo_led_state, ACER_CAP_TURBO_LED)))1781 return -1;1782 1783 if (turbo_led_state) {1784 /* Turn off turbo led */1785 WMID_gaming_set_u64(0x1, ACER_CAP_TURBO_LED);1786 1787 /* Set FAN mode to auto */1788 WMID_gaming_set_fan_mode(0x1);1789 1790 /* Set OC to normal */1791 WMID_gaming_set_u64(0x5, ACER_CAP_TURBO_OC);1792 WMID_gaming_set_u64(0x7, ACER_CAP_TURBO_OC);1793 } else {1794 /* Turn on turbo led */1795 WMID_gaming_set_u64(0x10001, ACER_CAP_TURBO_LED);1796 1797 /* Set FAN mode to turbo */1798 WMID_gaming_set_fan_mode(0x2);1799 1800 /* Set OC to turbo mode */1801 WMID_gaming_set_u64(0x205, ACER_CAP_TURBO_OC);1802 WMID_gaming_set_u64(0x207, ACER_CAP_TURBO_OC);1803 }1804 return turbo_led_state;1805}1806 1807static int1808acer_predator_v4_platform_profile_get(struct platform_profile_handler *pprof,1809 enum platform_profile_option *profile)1810{1811 u8 tp;1812 int err;1813 1814 err = ec_read(ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET, &tp);1815 1816 if (err < 0)1817 return err;1818 1819 switch (tp) {1820 case ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO:1821 *profile = PLATFORM_PROFILE_PERFORMANCE;1822 break;1823 case ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE:1824 *profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;1825 break;1826 case ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED:1827 *profile = PLATFORM_PROFILE_BALANCED;1828 break;1829 case ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET:1830 *profile = PLATFORM_PROFILE_QUIET;1831 break;1832 case ACER_PREDATOR_V4_THERMAL_PROFILE_ECO:1833 *profile = PLATFORM_PROFILE_LOW_POWER;1834 break;1835 default:1836 return -EOPNOTSUPP;1837 }1838 1839 return 0;1840}1841 1842static int1843acer_predator_v4_platform_profile_set(struct platform_profile_handler *pprof,1844 enum platform_profile_option profile)1845{1846 int tp;1847 acpi_status status;1848 1849 switch (profile) {1850 case PLATFORM_PROFILE_PERFORMANCE:1851 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI;1852 break;1853 case PLATFORM_PROFILE_BALANCED_PERFORMANCE:1854 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE_WMI;1855 break;1856 case PLATFORM_PROFILE_BALANCED:1857 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1858 break;1859 case PLATFORM_PROFILE_QUIET:1860 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET_WMI;1861 break;1862 case PLATFORM_PROFILE_LOW_POWER:1863 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI;1864 break;1865 default:1866 return -EOPNOTSUPP;1867 }1868 1869 status = WMI_gaming_execute_u64(1870 ACER_WMID_SET_GAMING_MISC_SETTING_METHODID, tp, NULL);1871 1872 if (ACPI_FAILURE(status))1873 return -EIO;1874 1875 if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI)1876 last_non_turbo_profile = tp;1877 1878 return 0;1879}1880 1881static int acer_platform_profile_setup(void)1882{1883 if (quirks->predator_v4) {1884 int err;1885 1886 platform_profile_handler.profile_get =1887 acer_predator_v4_platform_profile_get;1888 platform_profile_handler.profile_set =1889 acer_predator_v4_platform_profile_set;1890 1891 set_bit(PLATFORM_PROFILE_PERFORMANCE,1892 platform_profile_handler.choices);1893 set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE,1894 platform_profile_handler.choices);1895 set_bit(PLATFORM_PROFILE_BALANCED,1896 platform_profile_handler.choices);1897 set_bit(PLATFORM_PROFILE_QUIET,1898 platform_profile_handler.choices);1899 set_bit(PLATFORM_PROFILE_LOW_POWER,1900 platform_profile_handler.choices);1901 1902 err = platform_profile_register(&platform_profile_handler);1903 if (err)1904 return err;1905 1906 platform_profile_support = true;1907 1908 /* Set default non-turbo profile */1909 last_non_turbo_profile =1910 ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1911 }1912 return 0;1913}1914 1915static int acer_thermal_profile_change(void)1916{1917 /*1918 * This mode key can rotate each mode or toggle turbo mode.1919 * On battery, only ECO and BALANCED mode are available.1920 */1921 if (quirks->predator_v4) {1922 u8 current_tp;1923 int tp, err;1924 u64 on_AC;1925 acpi_status status;1926 1927 err = ec_read(ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET,1928 ¤t_tp);1929 1930 if (err < 0)1931 return err;1932 1933 /* Check power source */1934 status = WMI_gaming_execute_u64(1935 ACER_WMID_GET_GAMING_SYS_INFO_METHODID,1936 ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS, &on_AC);1937 1938 if (ACPI_FAILURE(status))1939 return -EIO;1940 1941 switch (current_tp) {1942 case ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO:1943 if (!on_AC)1944 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1945 else if (cycle_gaming_thermal_profile)1946 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI;1947 else1948 tp = last_non_turbo_profile;1949 break;1950 case ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE:1951 if (!on_AC)1952 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1953 else1954 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI;1955 break;1956 case ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED:1957 if (!on_AC)1958 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_ECO_WMI;1959 else if (cycle_gaming_thermal_profile)1960 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_PERFORMANCE_WMI;1961 else1962 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI;1963 break;1964 case ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET:1965 if (!on_AC)1966 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1967 else if (cycle_gaming_thermal_profile)1968 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1969 else1970 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI;1971 break;1972 case ACER_PREDATOR_V4_THERMAL_PROFILE_ECO:1973 if (!on_AC)1974 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_BALANCED_WMI;1975 else if (cycle_gaming_thermal_profile)1976 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_QUIET_WMI;1977 else1978 tp = ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI;1979 break;1980 default:1981 return -EOPNOTSUPP;1982 }1983 1984 status = WMI_gaming_execute_u64(1985 ACER_WMID_SET_GAMING_MISC_SETTING_METHODID, tp, NULL);1986 1987 if (ACPI_FAILURE(status))1988 return -EIO;1989 1990 /* Store non-turbo profile for turbo mode toggle*/1991 if (tp != ACER_PREDATOR_V4_THERMAL_PROFILE_TURBO_WMI)1992 last_non_turbo_profile = tp;1993 1994 platform_profile_notify();1995 }1996 1997 return 0;1998}1999 2000/*2001 * Switch series keyboard dock status2002 */2003static int acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state)2004{2005 switch (kbd_dock_state) {2006 case 0x01: /* Docked, traditional clamshell laptop mode */2007 return 0;2008 case 0x04: /* Stand-alone tablet */2009 case 0x40: /* Docked, tent mode, keyboard not usable */2010 return 1;2011 default:2012 pr_warn("Unknown kbd_dock_state 0x%02x\n", kbd_dock_state);2013 }2014 2015 return 0;2016}2017 2018static void acer_kbd_dock_get_initial_state(void)2019{2020 u8 *output, input[8] = { 0x05, 0x00, };2021 struct acpi_buffer input_buf = { sizeof(input), input };2022 struct acpi_buffer output_buf = { ACPI_ALLOCATE_BUFFER, NULL };2023 union acpi_object *obj;2024 acpi_status status;2025 int sw_tablet_mode;2026 2027 status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf);2028 if (ACPI_FAILURE(status)) {2029 pr_err("Error getting keyboard-dock initial status: %s\n",2030 acpi_format_exception(status));2031 return;2032 }2033 2034 obj = output_buf.pointer;2035 if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {2036 pr_err("Unexpected output format getting keyboard-dock initial status\n");2037 goto out_free_obj;2038 }2039 2040 output = obj->buffer.pointer;2041 if (output[0] != 0x00 || (output[3] != 0x05 && output[3] != 0x45)) {2042 pr_err("Unexpected output [0]=0x%02x [3]=0x%02x getting keyboard-dock initial status\n",2043 output[0], output[3]);2044 goto out_free_obj;2045 }2046 2047 sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(output[4]);2048 input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);2049 2050out_free_obj:2051 kfree(obj);2052}2053 2054static void acer_kbd_dock_event(const struct event_return_value *event)2055{2056 int sw_tablet_mode;2057 2058 if (!has_cap(ACER_CAP_KBD_DOCK))2059 return;2060 2061 sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(event->kbd_dock_state);2062 input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);2063 input_sync(acer_wmi_input_dev);2064}2065 2066/*2067 * Rfkill devices2068 */2069static void acer_rfkill_update(struct work_struct *ignored);2070static DECLARE_DELAYED_WORK(acer_rfkill_work, acer_rfkill_update);2071static void acer_rfkill_update(struct work_struct *ignored)2072{2073 u32 state;2074 acpi_status status;2075 2076 if (has_cap(ACER_CAP_WIRELESS)) {2077 status = get_u32(&state, ACER_CAP_WIRELESS);2078 if (ACPI_SUCCESS(status)) {2079 if (quirks->wireless == 3)2080 rfkill_set_hw_state(wireless_rfkill, !state);2081 else2082 rfkill_set_sw_state(wireless_rfkill, !state);2083 }2084 }2085 2086 if (has_cap(ACER_CAP_BLUETOOTH)) {2087 status = get_u32(&state, ACER_CAP_BLUETOOTH);2088 if (ACPI_SUCCESS(status))2089 rfkill_set_sw_state(bluetooth_rfkill, !state);2090 }2091 2092 if (has_cap(ACER_CAP_THREEG) && wmi_has_guid(WMID_GUID3)) {2093 status = get_u32(&state, ACER_WMID3_GDS_THREEG);2094 if (ACPI_SUCCESS(status))2095 rfkill_set_sw_state(threeg_rfkill, !state);2096 }2097 2098 schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));2099}2100 2101static int acer_rfkill_set(void *data, bool blocked)2102{2103 acpi_status status;2104 u32 cap = (unsigned long)data;2105 2106 if (rfkill_inited) {2107 status = set_u32(!blocked, cap);2108 if (ACPI_FAILURE(status))2109 return -ENODEV;2110 }2111 2112 return 0;2113}2114 2115static const struct rfkill_ops acer_rfkill_ops = {2116 .set_block = acer_rfkill_set,2117};2118 2119static struct rfkill *acer_rfkill_register(struct device *dev,2120 enum rfkill_type type,2121 char *name, u32 cap)2122{2123 int err;2124 struct rfkill *rfkill_dev;2125 u32 state;2126 acpi_status status;2127 2128 rfkill_dev = rfkill_alloc(name, dev, type,2129 &acer_rfkill_ops,2130 (void *)(unsigned long)cap);2131 if (!rfkill_dev)2132 return ERR_PTR(-ENOMEM);2133 2134 status = get_u32(&state, cap);2135 2136 err = rfkill_register(rfkill_dev);2137 if (err) {2138 rfkill_destroy(rfkill_dev);2139 return ERR_PTR(err);2140 }2141 2142 if (ACPI_SUCCESS(status))2143 rfkill_set_sw_state(rfkill_dev, !state);2144 2145 return rfkill_dev;2146}2147 2148static int acer_rfkill_init(struct device *dev)2149{2150 int err;2151 2152 if (has_cap(ACER_CAP_WIRELESS)) {2153 wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,2154 "acer-wireless", ACER_CAP_WIRELESS);2155 if (IS_ERR(wireless_rfkill)) {2156 err = PTR_ERR(wireless_rfkill);2157 goto error_wireless;2158 }2159 }2160 2161 if (has_cap(ACER_CAP_BLUETOOTH)) {2162 bluetooth_rfkill = acer_rfkill_register(dev,2163 RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",2164 ACER_CAP_BLUETOOTH);2165 if (IS_ERR(bluetooth_rfkill)) {2166 err = PTR_ERR(bluetooth_rfkill);2167 goto error_bluetooth;2168 }2169 }2170 2171 if (has_cap(ACER_CAP_THREEG)) {2172 threeg_rfkill = acer_rfkill_register(dev,2173 RFKILL_TYPE_WWAN, "acer-threeg",2174 ACER_CAP_THREEG);2175 if (IS_ERR(threeg_rfkill)) {2176 err = PTR_ERR(threeg_rfkill);2177 goto error_threeg;2178 }2179 }2180 2181 rfkill_inited = true;2182 2183 if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&2184 has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))2185 schedule_delayed_work(&acer_rfkill_work,2186 round_jiffies_relative(HZ));2187 2188 return 0;2189 2190error_threeg:2191 if (has_cap(ACER_CAP_BLUETOOTH)) {2192 rfkill_unregister(bluetooth_rfkill);2193 rfkill_destroy(bluetooth_rfkill);2194 }2195error_bluetooth:2196 if (has_cap(ACER_CAP_WIRELESS)) {2197 rfkill_unregister(wireless_rfkill);2198 rfkill_destroy(wireless_rfkill);2199 }2200error_wireless:2201 return err;2202}2203 2204static void acer_rfkill_exit(void)2205{2206 if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&2207 has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))2208 cancel_delayed_work_sync(&acer_rfkill_work);2209 2210 if (has_cap(ACER_CAP_WIRELESS)) {2211 rfkill_unregister(wireless_rfkill);2212 rfkill_destroy(wireless_rfkill);2213 }2214 2215 if (has_cap(ACER_CAP_BLUETOOTH)) {2216 rfkill_unregister(bluetooth_rfkill);2217 rfkill_destroy(bluetooth_rfkill);2218 }2219 2220 if (has_cap(ACER_CAP_THREEG)) {2221 rfkill_unregister(threeg_rfkill);2222 rfkill_destroy(threeg_rfkill);2223 }2224}2225 2226static void acer_wmi_notify(union acpi_object *obj, void *context)2227{2228 struct event_return_value return_value;2229 u16 device_state;2230 const struct key_entry *key;2231 u32 scancode;2232 2233 if (!obj)2234 return;2235 if (obj->type != ACPI_TYPE_BUFFER) {2236 pr_warn("Unknown response received %d\n", obj->type);2237 return;2238 }2239 if (obj->buffer.length != 8) {2240 pr_warn("Unknown buffer length %d\n", obj->buffer.length);2241 return;2242 }2243 2244 return_value = *((struct event_return_value *)obj->buffer.pointer);2245 2246 switch (return_value.function) {2247 case WMID_HOTKEY_EVENT:2248 device_state = return_value.device_state;2249 pr_debug("device state: 0x%x\n", device_state);2250 2251 key = sparse_keymap_entry_from_scancode(acer_wmi_input_dev,2252 return_value.key_num);2253 if (!key) {2254 pr_warn("Unknown key number - 0x%x\n",2255 return_value.key_num);2256 } else {2257 scancode = return_value.key_num;2258 switch (key->keycode) {2259 case KEY_WLAN:2260 case KEY_BLUETOOTH:2261 if (has_cap(ACER_CAP_WIRELESS))2262 rfkill_set_sw_state(wireless_rfkill,2263 !(device_state & ACER_WMID3_GDS_WIRELESS));2264 if (has_cap(ACER_CAP_THREEG))2265 rfkill_set_sw_state(threeg_rfkill,2266 !(device_state & ACER_WMID3_GDS_THREEG));2267 if (has_cap(ACER_CAP_BLUETOOTH))2268 rfkill_set_sw_state(bluetooth_rfkill,2269 !(device_state & ACER_WMID3_GDS_BLUETOOTH));2270 break;2271 case KEY_TOUCHPAD_TOGGLE:2272 scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ?2273 KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF;2274 }2275 sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);2276 }2277 break;2278 case WMID_ACCEL_OR_KBD_DOCK_EVENT:2279 acer_gsensor_event();2280 acer_kbd_dock_event(&return_value);2281 break;2282 case WMID_GAMING_TURBO_KEY_EVENT:2283 if (return_value.key_num == 0x4)2284 acer_toggle_turbo();2285 if (return_value.key_num == 0x5 && has_cap(ACER_CAP_PLATFORM_PROFILE))2286 acer_thermal_profile_change();2287 break;2288 default:2289 pr_warn("Unknown function number - %d - %d\n",2290 return_value.function, return_value.key_num);2291 break;2292 }2293}2294 2295static acpi_status __init2296wmid3_set_function_mode(struct func_input_params *params,2297 struct func_return_value *return_value)2298{2299 acpi_status status;2300 union acpi_object *obj;2301 2302 struct acpi_buffer input = { sizeof(struct func_input_params), params };2303 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };2304 2305 status = wmi_evaluate_method(WMID_GUID3, 0, 0x1, &input, &output);2306 if (ACPI_FAILURE(status))2307 return status;2308 2309 obj = output.pointer;2310 2311 if (!obj)2312 return AE_ERROR;2313 else if (obj->type != ACPI_TYPE_BUFFER) {2314 kfree(obj);2315 return AE_ERROR;2316 }2317 if (obj->buffer.length != 4) {2318 pr_warn("Unknown buffer length %d\n", obj->buffer.length);2319 kfree(obj);2320 return AE_ERROR;2321 }2322 2323 *return_value = *((struct func_return_value *)obj->buffer.pointer);2324 kfree(obj);2325 2326 return status;2327}2328 2329static int __init acer_wmi_enable_ec_raw(void)2330{2331 struct func_return_value return_value;2332 acpi_status status;2333 struct func_input_params params = {2334 .function_num = 0x1,2335 .commun_devices = 0xFFFF,2336 .devices = 0xFFFF,2337 .app_status = 0x00, /* Launch Manager Deactive */2338 .app_mask = 0x01,2339 };2340 2341 status = wmid3_set_function_mode(¶ms, &return_value);2342 2343 if (return_value.error_code || return_value.ec_return_value)2344 pr_warn("Enabling EC raw mode failed: 0x%x - 0x%x\n",2345 return_value.error_code,2346 return_value.ec_return_value);2347 else2348 pr_info("Enabled EC raw mode\n");2349 2350 return status;2351}2352 2353static int __init acer_wmi_enable_lm(void)2354{2355 struct func_return_value return_value;2356 acpi_status status;2357 struct func_input_params params = {2358 .function_num = 0x1,2359 .commun_devices = 0xFFFF,2360 .devices = 0xFFFF,2361 .app_status = 0x01, /* Launch Manager Active */2362 .app_mask = 0x01,2363 };2364 2365 status = wmid3_set_function_mode(¶ms, &return_value);2366 2367 if (return_value.error_code || return_value.ec_return_value)2368 pr_warn("Enabling Launch Manager failed: 0x%x - 0x%x\n",2369 return_value.error_code,2370 return_value.ec_return_value);2371 2372 return status;2373}2374 2375static int __init acer_wmi_enable_rf_button(void)2376{2377 struct func_return_value return_value;2378 acpi_status status;2379 struct func_input_params params = {2380 .function_num = 0x1,2381 .commun_devices = 0xFFFF,2382 .devices = 0xFFFF,2383 .app_status = 0x10, /* RF Button Active */2384 .app_mask = 0x10,2385 };2386 2387 status = wmid3_set_function_mode(¶ms, &return_value);2388 2389 if (return_value.error_code || return_value.ec_return_value)2390 pr_warn("Enabling RF Button failed: 0x%x - 0x%x\n",2391 return_value.error_code,2392 return_value.ec_return_value);2393 2394 return status;2395}2396 2397static int __init acer_wmi_accel_setup(void)2398{2399 struct acpi_device *adev;2400 int err;2401 2402 adev = acpi_dev_get_first_match_dev("BST0001", NULL, -1);2403 if (!adev)2404 return -ENODEV;2405 2406 gsensor_handle = acpi_device_handle(adev);2407 acpi_dev_put(adev);2408 2409 acer_wmi_accel_dev = input_allocate_device();2410 if (!acer_wmi_accel_dev)2411 return -ENOMEM;2412 2413 acer_wmi_accel_dev->open = acer_gsensor_open;2414 2415 acer_wmi_accel_dev->name = "Acer BMA150 accelerometer";2416 acer_wmi_accel_dev->phys = "wmi/input1";2417 acer_wmi_accel_dev->id.bustype = BUS_HOST;2418 acer_wmi_accel_dev->evbit[0] = BIT_MASK(EV_ABS);2419 input_set_abs_params(acer_wmi_accel_dev, ABS_X, -16384, 16384, 0, 0);2420 input_set_abs_params(acer_wmi_accel_dev, ABS_Y, -16384, 16384, 0, 0);2421 input_set_abs_params(acer_wmi_accel_dev, ABS_Z, -16384, 16384, 0, 0);2422 2423 err = input_register_device(acer_wmi_accel_dev);2424 if (err)2425 goto err_free_dev;2426 2427 return 0;2428 2429err_free_dev:2430 input_free_device(acer_wmi_accel_dev);2431 return err;2432}2433 2434static int __init acer_wmi_input_setup(void)2435{2436 acpi_status status;2437 int err;2438 2439 acer_wmi_input_dev = input_allocate_device();2440 if (!acer_wmi_input_dev)2441 return -ENOMEM;2442 2443 acer_wmi_input_dev->name = "Acer WMI hotkeys";2444 acer_wmi_input_dev->phys = "wmi/input0";2445 acer_wmi_input_dev->id.bustype = BUS_HOST;2446 2447 err = sparse_keymap_setup(acer_wmi_input_dev, acer_wmi_keymap, NULL);2448 if (err)2449 goto err_free_dev;2450 2451 if (has_cap(ACER_CAP_KBD_DOCK))2452 input_set_capability(acer_wmi_input_dev, EV_SW, SW_TABLET_MODE);2453 2454 status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,2455 acer_wmi_notify, NULL);2456 if (ACPI_FAILURE(status)) {2457 err = -EIO;2458 goto err_free_dev;2459 }2460 2461 if (has_cap(ACER_CAP_KBD_DOCK))2462 acer_kbd_dock_get_initial_state();2463 2464 err = input_register_device(acer_wmi_input_dev);2465 if (err)2466 goto err_uninstall_notifier;2467 2468 return 0;2469 2470err_uninstall_notifier:2471 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);2472err_free_dev:2473 input_free_device(acer_wmi_input_dev);2474 return err;2475}2476 2477static void acer_wmi_input_destroy(void)2478{2479 wmi_remove_notify_handler(ACERWMID_EVENT_GUID);2480 input_unregister_device(acer_wmi_input_dev);2481}2482 2483/*2484 * debugfs functions2485 */2486static u32 get_wmid_devices(void)2487{2488 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};2489 union acpi_object *obj;2490 acpi_status status;2491 u32 devices = 0;2492 2493 status = wmi_query_block(WMID_GUID2, 0, &out);2494 if (ACPI_FAILURE(status))2495 return 0;2496 2497 obj = (union acpi_object *) out.pointer;2498 if (obj) {2499 if (obj->type == ACPI_TYPE_BUFFER &&2500 (obj->buffer.length == sizeof(u32) ||2501 obj->buffer.length == sizeof(u64))) {2502 devices = *((u32 *) obj->buffer.pointer);2503 } else if (obj->type == ACPI_TYPE_INTEGER) {2504 devices = (u32) obj->integer.value;2505 }2506 }2507 2508 kfree(out.pointer);2509 return devices;2510}2511 2512static int acer_wmi_hwmon_init(void);2513 2514/*2515 * Platform device2516 */2517static int acer_platform_probe(struct platform_device *device)2518{2519 int err;2520 2521 if (has_cap(ACER_CAP_MAILLED)) {2522 err = acer_led_init(&device->dev);2523 if (err)2524 goto error_mailled;2525 }2526 2527 if (has_cap(ACER_CAP_BRIGHTNESS)) {2528 err = acer_backlight_init(&device->dev);2529 if (err)2530 goto error_brightness;2531 }2532 2533 err = acer_rfkill_init(&device->dev);2534 if (err)2535 goto error_rfkill;2536 2537 if (has_cap(ACER_CAP_PLATFORM_PROFILE)) {2538 err = acer_platform_profile_setup();2539 if (err)2540 goto error_platform_profile;2541 }2542 2543 if (has_cap(ACER_CAP_FAN_SPEED_READ)) {2544 err = acer_wmi_hwmon_init();2545 if (err)2546 goto error_hwmon;2547 }2548 2549 return 0;2550 2551error_hwmon:2552 if (platform_profile_support)2553 platform_profile_remove();2554error_platform_profile:2555 acer_rfkill_exit();2556error_rfkill:2557 if (has_cap(ACER_CAP_BRIGHTNESS))2558 acer_backlight_exit();2559error_brightness:2560 if (has_cap(ACER_CAP_MAILLED))2561 acer_led_exit();2562error_mailled:2563 return err;2564}2565 2566static void acer_platform_remove(struct platform_device *device)2567{2568 if (has_cap(ACER_CAP_MAILLED))2569 acer_led_exit();2570 if (has_cap(ACER_CAP_BRIGHTNESS))2571 acer_backlight_exit();2572 2573 acer_rfkill_exit();2574 2575 if (platform_profile_support)2576 platform_profile_remove();2577}2578 2579#ifdef CONFIG_PM_SLEEP2580static int acer_suspend(struct device *dev)2581{2582 u32 value;2583 struct acer_data *data = &interface->data;2584 2585 if (!data)2586 return -ENOMEM;2587 2588 if (has_cap(ACER_CAP_MAILLED)) {2589 get_u32(&value, ACER_CAP_MAILLED);2590 set_u32(LED_OFF, ACER_CAP_MAILLED);2591 data->mailled = value;2592 }2593 2594 if (has_cap(ACER_CAP_BRIGHTNESS)) {2595 get_u32(&value, ACER_CAP_BRIGHTNESS);2596 data->brightness = value;2597 }2598 2599 return 0;2600}2601 2602static int acer_resume(struct device *dev)2603{2604 struct acer_data *data = &interface->data;2605 2606 if (!data)2607 return -ENOMEM;2608 2609 if (has_cap(ACER_CAP_MAILLED))2610 set_u32(data->mailled, ACER_CAP_MAILLED);2611 2612 if (has_cap(ACER_CAP_BRIGHTNESS))2613 set_u32(data->brightness, ACER_CAP_BRIGHTNESS);2614 2615 if (acer_wmi_accel_dev)2616 acer_gsensor_init();2617 2618 return 0;2619}2620#else2621#define acer_suspend NULL2622#define acer_resume NULL2623#endif2624 2625static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);2626 2627static void acer_platform_shutdown(struct platform_device *device)2628{2629 struct acer_data *data = &interface->data;2630 2631 if (!data)2632 return;2633 2634 if (has_cap(ACER_CAP_MAILLED))2635 set_u32(LED_OFF, ACER_CAP_MAILLED);2636}2637 2638static struct platform_driver acer_platform_driver = {2639 .driver = {2640 .name = "acer-wmi",2641 .pm = &acer_pm,2642 },2643 .probe = acer_platform_probe,2644 .remove_new = acer_platform_remove,2645 .shutdown = acer_platform_shutdown,2646};2647 2648static struct platform_device *acer_platform_device;2649 2650static void remove_debugfs(void)2651{2652 debugfs_remove_recursive(interface->debug.root);2653}2654 2655static void __init create_debugfs(void)2656{2657 interface->debug.root = debugfs_create_dir("acer-wmi", NULL);2658 2659 debugfs_create_u32("devices", S_IRUGO, interface->debug.root,2660 &interface->debug.wmid_devices);2661}2662 2663static umode_t acer_wmi_hwmon_is_visible(const void *data,2664 enum hwmon_sensor_types type, u32 attr,2665 int channel)2666{2667 switch (type) {2668 case hwmon_fan:2669 if (acer_get_fan_speed(channel) >= 0)2670 return 0444;2671 break;2672 default:2673 return 0;2674 }2675 2676 return 0;2677}2678 2679static int acer_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,2680 u32 attr, int channel, long *val)2681{2682 int ret;2683 2684 switch (type) {2685 case hwmon_fan:2686 ret = acer_get_fan_speed(channel);2687 if (ret < 0)2688 return ret;2689 *val = ret;2690 break;2691 default:2692 return -EOPNOTSUPP;2693 }2694 2695 return 0;2696}2697 2698static const struct hwmon_channel_info *const acer_wmi_hwmon_info[] = {2699 HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), NULL2700};2701 2702static const struct hwmon_ops acer_wmi_hwmon_ops = {2703 .read = acer_wmi_hwmon_read,2704 .is_visible = acer_wmi_hwmon_is_visible,2705};2706 2707static const struct hwmon_chip_info acer_wmi_hwmon_chip_info = {2708 .ops = &acer_wmi_hwmon_ops,2709 .info = acer_wmi_hwmon_info,2710};2711 2712static int acer_wmi_hwmon_init(void)2713{2714 struct device *dev = &acer_platform_device->dev;2715 struct device *hwmon;2716 2717 hwmon = devm_hwmon_device_register_with_info(dev, "acer",2718 &acer_platform_driver,2719 &acer_wmi_hwmon_chip_info,2720 NULL);2721 2722 if (IS_ERR(hwmon)) {2723 dev_err(dev, "Could not register acer hwmon device\n");2724 return PTR_ERR(hwmon);2725 }2726 2727 return 0;2728}2729 2730static int __init acer_wmi_init(void)2731{2732 int err;2733 2734 pr_info("Acer Laptop ACPI-WMI Extras\n");2735 2736 if (dmi_check_system(acer_blacklist)) {2737 pr_info("Blacklisted hardware detected - not loading\n");2738 return -ENODEV;2739 }2740 2741 find_quirks();2742 2743 /*2744 * The AMW0_GUID1 wmi is not only found on Acer family but also other2745 * machines like Lenovo, Fujitsu and Medion. In the past days,2746 * acer-wmi driver handled those non-Acer machines by quirks list.2747 * But actually acer-wmi driver was loaded on any machines that have2748 * AMW0_GUID1. This behavior is strange because those machines should2749 * be supported by appropriate wmi drivers. e.g. fujitsu-laptop,2750 * ideapad-laptop. So, here checks the machine that has AMW0_GUID12751 * should be in Acer/Gateway/Packard Bell white list, or it's already2752 * in the past quirk list.2753 */2754 if (wmi_has_guid(AMW0_GUID1) &&2755 !dmi_check_system(amw0_whitelist) &&2756 quirks == &quirk_unknown) {2757 pr_debug("Unsupported machine has AMW0_GUID1, unable to load\n");2758 return -ENODEV;2759 }2760 2761 /*2762 * Detect which ACPI-WMI interface we're using.2763 */2764 if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))2765 interface = &AMW0_V2_interface;2766 2767 if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1))2768 interface = &wmid_interface;2769 2770 if (wmi_has_guid(WMID_GUID3))2771 interface = &wmid_v2_interface;2772 2773 if (interface)2774 dmi_walk(type_aa_dmi_decode, NULL);2775 2776 if (wmi_has_guid(WMID_GUID2) && interface) {2777 if (!has_type_aa && ACPI_FAILURE(WMID_set_capabilities())) {2778 pr_err("Unable to detect available WMID devices\n");2779 return -ENODEV;2780 }2781 /* WMID always provides brightness methods */2782 interface->capability |= ACER_CAP_BRIGHTNESS;2783 } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa && force_caps == -1) {2784 pr_err("No WMID device detection method found\n");2785 return -ENODEV;2786 }2787 2788 if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) {2789 interface = &AMW0_interface;2790 2791 if (ACPI_FAILURE(AMW0_set_capabilities())) {2792 pr_err("Unable to detect available AMW0 devices\n");2793 return -ENODEV;2794 }2795 }2796 2797 if (wmi_has_guid(AMW0_GUID1))2798 AMW0_find_mailled();2799 2800 if (!interface) {2801 pr_err("No or unsupported WMI interface, unable to load\n");2802 return -ENODEV;2803 }2804 2805 set_quirks();2806 2807 if (acpi_video_get_backlight_type() != acpi_backlight_vendor)2808 interface->capability &= ~ACER_CAP_BRIGHTNESS;2809 2810 if (wmi_has_guid(WMID_GUID3))2811 interface->capability |= ACER_CAP_SET_FUNCTION_MODE;2812 2813 if (force_caps != -1)2814 interface->capability = force_caps;2815 2816 if (wmi_has_guid(WMID_GUID3) &&2817 (interface->capability & ACER_CAP_SET_FUNCTION_MODE)) {2818 if (ACPI_FAILURE(acer_wmi_enable_rf_button()))2819 pr_warn("Cannot enable RF Button Driver\n");2820 2821 if (ec_raw_mode) {2822 if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {2823 pr_err("Cannot enable EC raw mode\n");2824 return -ENODEV;2825 }2826 } else if (ACPI_FAILURE(acer_wmi_enable_lm())) {2827 pr_err("Cannot enable Launch Manager mode\n");2828 return -ENODEV;2829 }2830 } else if (ec_raw_mode) {2831 pr_info("No WMID EC raw mode enable method\n");2832 }2833 2834 if (wmi_has_guid(ACERWMID_EVENT_GUID)) {2835 err = acer_wmi_input_setup();2836 if (err)2837 return err;2838 err = acer_wmi_accel_setup();2839 if (err && err != -ENODEV)2840 pr_warn("Cannot enable accelerometer\n");2841 }2842 2843 err = platform_driver_register(&acer_platform_driver);2844 if (err) {2845 pr_err("Unable to register platform driver\n");2846 goto error_platform_register;2847 }2848 2849 acer_platform_device = platform_device_alloc("acer-wmi", PLATFORM_DEVID_NONE);2850 if (!acer_platform_device) {2851 err = -ENOMEM;2852 goto error_device_alloc;2853 }2854 2855 err = platform_device_add(acer_platform_device);2856 if (err)2857 goto error_device_add;2858 2859 if (wmi_has_guid(WMID_GUID2)) {2860 interface->debug.wmid_devices = get_wmid_devices();2861 create_debugfs();2862 }2863 2864 /* Override any initial settings with values from the commandline */2865 acer_commandline_init();2866 2867 return 0;2868 2869error_device_add:2870 platform_device_put(acer_platform_device);2871error_device_alloc:2872 platform_driver_unregister(&acer_platform_driver);2873error_platform_register:2874 if (wmi_has_guid(ACERWMID_EVENT_GUID))2875 acer_wmi_input_destroy();2876 if (acer_wmi_accel_dev)2877 input_unregister_device(acer_wmi_accel_dev);2878 2879 return err;2880}2881 2882static void __exit acer_wmi_exit(void)2883{2884 if (wmi_has_guid(ACERWMID_EVENT_GUID))2885 acer_wmi_input_destroy();2886 2887 if (acer_wmi_accel_dev)2888 input_unregister_device(acer_wmi_accel_dev);2889 2890 remove_debugfs();2891 platform_device_unregister(acer_platform_device);2892 platform_driver_unregister(&acer_platform_driver);2893 2894 pr_info("Acer Laptop WMI Extras unloaded\n");2895}2896 2897module_init(acer_wmi_init);2898module_exit(acer_wmi_exit);2899