brintos

brintos / linux-shallow public Read only

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