cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acer-wmi.c (62086B)


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