File Index
Files and directories
Sign in
FILE

acer-wmi.c

File preview with syntax highlighting.

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