xref: /OK3568_Linux_fs/kernel/drivers/platform/x86/asus-nb-wmi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Asus Notebooks WMI hotkey driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/input.h>
14*4882a593Smuzhiyun #include <linux/input/sparse-keymap.h>
15*4882a593Smuzhiyun #include <linux/fb.h>
16*4882a593Smuzhiyun #include <linux/dmi.h>
17*4882a593Smuzhiyun #include <linux/i8042.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include "asus-wmi.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define	ASUS_NB_WMI_FILE	"asus-nb-wmi"
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>");
24*4882a593Smuzhiyun MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");
25*4882a593Smuzhiyun MODULE_LICENSE("GPL");
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define ASUS_NB_WMI_EVENT_GUID	"0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /*
32*4882a593Smuzhiyun  * WAPF defines the behavior of the Fn+Fx wlan key
33*4882a593Smuzhiyun  * The significance of values is yet to be found, but
34*4882a593Smuzhiyun  * most of the time:
35*4882a593Smuzhiyun  * Bit | Bluetooth | WLAN
36*4882a593Smuzhiyun  *  0  | Hardware  | Hardware
37*4882a593Smuzhiyun  *  1  | Hardware  | Software
38*4882a593Smuzhiyun  *  4  | Software  | Software
39*4882a593Smuzhiyun  */
40*4882a593Smuzhiyun static int wapf = -1;
41*4882a593Smuzhiyun module_param(wapf, uint, 0444);
42*4882a593Smuzhiyun MODULE_PARM_DESC(wapf, "WAPF value");
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static struct quirk_entry *quirks;
45*4882a593Smuzhiyun 
asus_q500a_i8042_filter(unsigned char data,unsigned char str,struct serio * port)46*4882a593Smuzhiyun static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str,
47*4882a593Smuzhiyun 			      struct serio *port)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun 	static bool extended;
50*4882a593Smuzhiyun 	bool ret = false;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	if (str & I8042_STR_AUXDATA)
53*4882a593Smuzhiyun 		return false;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	if (unlikely(data == 0xe1)) {
56*4882a593Smuzhiyun 		extended = true;
57*4882a593Smuzhiyun 		ret = true;
58*4882a593Smuzhiyun 	} else if (unlikely(extended)) {
59*4882a593Smuzhiyun 		extended = false;
60*4882a593Smuzhiyun 		ret = true;
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	return ret;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static struct quirk_entry quirk_asus_unknown = {
67*4882a593Smuzhiyun 	.wapf = 0,
68*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static struct quirk_entry quirk_asus_q500a = {
72*4882a593Smuzhiyun 	.i8042_filter = asus_q500a_i8042_filter,
73*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /*
77*4882a593Smuzhiyun  * For those machines that need software to control bt/wifi status
78*4882a593Smuzhiyun  * and can't adjust brightness through ACPI interface
79*4882a593Smuzhiyun  * and have duplicate events(ACPI and WMI) for display toggle
80*4882a593Smuzhiyun  */
81*4882a593Smuzhiyun static struct quirk_entry quirk_asus_x55u = {
82*4882a593Smuzhiyun 	.wapf = 4,
83*4882a593Smuzhiyun 	.wmi_backlight_power = true,
84*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
85*4882a593Smuzhiyun 	.no_display_toggle = true,
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun static struct quirk_entry quirk_asus_wapf4 = {
89*4882a593Smuzhiyun 	.wapf = 4,
90*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun static struct quirk_entry quirk_asus_x200ca = {
94*4882a593Smuzhiyun 	.wapf = 2,
95*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static struct quirk_entry quirk_asus_ux303ub = {
99*4882a593Smuzhiyun 	.wmi_backlight_native = true,
100*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
101*4882a593Smuzhiyun };
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun static struct quirk_entry quirk_asus_x550lb = {
104*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
105*4882a593Smuzhiyun 	.xusb2pr = 0x01D9,
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static struct quirk_entry quirk_asus_forceals = {
109*4882a593Smuzhiyun 	.wmi_backlight_set_devstate = true,
110*4882a593Smuzhiyun 	.wmi_force_als_set = true,
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun static struct quirk_entry quirk_asus_use_kbd_dock_devid = {
114*4882a593Smuzhiyun 	.use_kbd_dock_devid = true,
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun 
dmi_matched(const struct dmi_system_id * dmi)117*4882a593Smuzhiyun static int dmi_matched(const struct dmi_system_id *dmi)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	pr_info("Identified laptop model '%s'\n", dmi->ident);
120*4882a593Smuzhiyun 	quirks = dmi->driver_data;
121*4882a593Smuzhiyun 	return 1;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun static const struct dmi_system_id asus_quirks[] = {
125*4882a593Smuzhiyun 	{
126*4882a593Smuzhiyun 		.callback = dmi_matched,
127*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. Q500A",
128*4882a593Smuzhiyun 		.matches = {
129*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
130*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "Q500A"),
131*4882a593Smuzhiyun 		},
132*4882a593Smuzhiyun 		.driver_data = &quirk_asus_q500a,
133*4882a593Smuzhiyun 	},
134*4882a593Smuzhiyun 	{
135*4882a593Smuzhiyun 		.callback = dmi_matched,
136*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. U32U",
137*4882a593Smuzhiyun 		.matches = {
138*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
139*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "U32U"),
140*4882a593Smuzhiyun 		},
141*4882a593Smuzhiyun 		/*
142*4882a593Smuzhiyun 		 * Note this machine has a Brazos APU, and most Brazos Asus
143*4882a593Smuzhiyun 		 * machines need quirk_asus_x55u / wmi_backlight_power but
144*4882a593Smuzhiyun 		 * here acpi-video seems to work fine for backlight control.
145*4882a593Smuzhiyun 		 */
146*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
147*4882a593Smuzhiyun 	},
148*4882a593Smuzhiyun 	{
149*4882a593Smuzhiyun 		.callback = dmi_matched,
150*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X302UA",
151*4882a593Smuzhiyun 		.matches = {
152*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
153*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X302UA"),
154*4882a593Smuzhiyun 		},
155*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
156*4882a593Smuzhiyun 	},
157*4882a593Smuzhiyun 	{
158*4882a593Smuzhiyun 		.callback = dmi_matched,
159*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X401U",
160*4882a593Smuzhiyun 		.matches = {
161*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
162*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X401U"),
163*4882a593Smuzhiyun 		},
164*4882a593Smuzhiyun 		.driver_data = &quirk_asus_x55u,
165*4882a593Smuzhiyun 	},
166*4882a593Smuzhiyun 	{
167*4882a593Smuzhiyun 		.callback = dmi_matched,
168*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X401A",
169*4882a593Smuzhiyun 		.matches = {
170*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
171*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X401A"),
172*4882a593Smuzhiyun 		},
173*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
174*4882a593Smuzhiyun 	},
175*4882a593Smuzhiyun 	{
176*4882a593Smuzhiyun 		.callback = dmi_matched,
177*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X401A1",
178*4882a593Smuzhiyun 		.matches = {
179*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
180*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X401A1"),
181*4882a593Smuzhiyun 		},
182*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
183*4882a593Smuzhiyun 	},
184*4882a593Smuzhiyun 	{
185*4882a593Smuzhiyun 		.callback = dmi_matched,
186*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X45U",
187*4882a593Smuzhiyun 		.matches = {
188*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
189*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X45U"),
190*4882a593Smuzhiyun 		},
191*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
192*4882a593Smuzhiyun 	},
193*4882a593Smuzhiyun 	{
194*4882a593Smuzhiyun 		.callback = dmi_matched,
195*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X456UA",
196*4882a593Smuzhiyun 		.matches = {
197*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
198*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X456UA"),
199*4882a593Smuzhiyun 		},
200*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
201*4882a593Smuzhiyun 	},
202*4882a593Smuzhiyun 	{
203*4882a593Smuzhiyun 		.callback = dmi_matched,
204*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X456UF",
205*4882a593Smuzhiyun 		.matches = {
206*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
207*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X456UF"),
208*4882a593Smuzhiyun 		},
209*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
210*4882a593Smuzhiyun 	},
211*4882a593Smuzhiyun 	{
212*4882a593Smuzhiyun 		.callback = dmi_matched,
213*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X501U",
214*4882a593Smuzhiyun 		.matches = {
215*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
216*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X501U"),
217*4882a593Smuzhiyun 		},
218*4882a593Smuzhiyun 		.driver_data = &quirk_asus_x55u,
219*4882a593Smuzhiyun 	},
220*4882a593Smuzhiyun 	{
221*4882a593Smuzhiyun 		.callback = dmi_matched,
222*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X501A",
223*4882a593Smuzhiyun 		.matches = {
224*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
225*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X501A"),
226*4882a593Smuzhiyun 		},
227*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
228*4882a593Smuzhiyun 	},
229*4882a593Smuzhiyun 	{
230*4882a593Smuzhiyun 		.callback = dmi_matched,
231*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X501A1",
232*4882a593Smuzhiyun 		.matches = {
233*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
234*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X501A1"),
235*4882a593Smuzhiyun 		},
236*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
237*4882a593Smuzhiyun 	},
238*4882a593Smuzhiyun 	{
239*4882a593Smuzhiyun 		.callback = dmi_matched,
240*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X550CA",
241*4882a593Smuzhiyun 		.matches = {
242*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
243*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X550CA"),
244*4882a593Smuzhiyun 		},
245*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
246*4882a593Smuzhiyun 	},
247*4882a593Smuzhiyun 	{
248*4882a593Smuzhiyun 		.callback = dmi_matched,
249*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X550CC",
250*4882a593Smuzhiyun 		.matches = {
251*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
252*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X550CC"),
253*4882a593Smuzhiyun 		},
254*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
255*4882a593Smuzhiyun 	},
256*4882a593Smuzhiyun 	{
257*4882a593Smuzhiyun 		.callback = dmi_matched,
258*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X550CL",
259*4882a593Smuzhiyun 		.matches = {
260*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
261*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X550CL"),
262*4882a593Smuzhiyun 		},
263*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
264*4882a593Smuzhiyun 	},
265*4882a593Smuzhiyun 	{
266*4882a593Smuzhiyun 		.callback = dmi_matched,
267*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X550VB",
268*4882a593Smuzhiyun 		.matches = {
269*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
270*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X550VB"),
271*4882a593Smuzhiyun 		},
272*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
273*4882a593Smuzhiyun 	},
274*4882a593Smuzhiyun 	{
275*4882a593Smuzhiyun 		.callback = dmi_matched,
276*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X551CA",
277*4882a593Smuzhiyun 		.matches = {
278*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
279*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X551CA"),
280*4882a593Smuzhiyun 		},
281*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
282*4882a593Smuzhiyun 	},
283*4882a593Smuzhiyun 	{
284*4882a593Smuzhiyun 		.callback = dmi_matched,
285*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X55A",
286*4882a593Smuzhiyun 		.matches = {
287*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
288*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X55A"),
289*4882a593Smuzhiyun 		},
290*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
291*4882a593Smuzhiyun 	},
292*4882a593Smuzhiyun 	{
293*4882a593Smuzhiyun 		.callback = dmi_matched,
294*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X55C",
295*4882a593Smuzhiyun 		.matches = {
296*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
297*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X55C"),
298*4882a593Smuzhiyun 		},
299*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
300*4882a593Smuzhiyun 	},
301*4882a593Smuzhiyun 	{
302*4882a593Smuzhiyun 		.callback = dmi_matched,
303*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X55U",
304*4882a593Smuzhiyun 		.matches = {
305*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
306*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X55U"),
307*4882a593Smuzhiyun 		},
308*4882a593Smuzhiyun 		.driver_data = &quirk_asus_x55u,
309*4882a593Smuzhiyun 	},
310*4882a593Smuzhiyun 	{
311*4882a593Smuzhiyun 		.callback = dmi_matched,
312*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X55VD",
313*4882a593Smuzhiyun 		.matches = {
314*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
315*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X55VD"),
316*4882a593Smuzhiyun 		},
317*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
318*4882a593Smuzhiyun 	},
319*4882a593Smuzhiyun 	{
320*4882a593Smuzhiyun 		.callback = dmi_matched,
321*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X75A",
322*4882a593Smuzhiyun 		.matches = {
323*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
324*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X75A"),
325*4882a593Smuzhiyun 		},
326*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
327*4882a593Smuzhiyun 	},
328*4882a593Smuzhiyun 	{
329*4882a593Smuzhiyun 		.callback = dmi_matched,
330*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X75VBP",
331*4882a593Smuzhiyun 		.matches = {
332*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
333*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X75VBP"),
334*4882a593Smuzhiyun 		},
335*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
336*4882a593Smuzhiyun 	},
337*4882a593Smuzhiyun 	{
338*4882a593Smuzhiyun 		.callback = dmi_matched,
339*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X75VD",
340*4882a593Smuzhiyun 		.matches = {
341*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
342*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X75VD"),
343*4882a593Smuzhiyun 		},
344*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
345*4882a593Smuzhiyun 	},
346*4882a593Smuzhiyun 	{
347*4882a593Smuzhiyun 		.callback = dmi_matched,
348*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. 1015E",
349*4882a593Smuzhiyun 		.matches = {
350*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
351*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "1015E"),
352*4882a593Smuzhiyun 		},
353*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
354*4882a593Smuzhiyun 	},
355*4882a593Smuzhiyun 	{
356*4882a593Smuzhiyun 		.callback = dmi_matched,
357*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. 1015U",
358*4882a593Smuzhiyun 		.matches = {
359*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
360*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "1015U"),
361*4882a593Smuzhiyun 		},
362*4882a593Smuzhiyun 		.driver_data = &quirk_asus_wapf4,
363*4882a593Smuzhiyun 	},
364*4882a593Smuzhiyun 	{
365*4882a593Smuzhiyun 		.callback = dmi_matched,
366*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X200CA",
367*4882a593Smuzhiyun 		.matches = {
368*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
369*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X200CA"),
370*4882a593Smuzhiyun 		},
371*4882a593Smuzhiyun 		.driver_data = &quirk_asus_x200ca,
372*4882a593Smuzhiyun 	},
373*4882a593Smuzhiyun 	{
374*4882a593Smuzhiyun 		.callback = dmi_matched,
375*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. UX303UB",
376*4882a593Smuzhiyun 		.matches = {
377*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
378*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "UX303UB"),
379*4882a593Smuzhiyun 		},
380*4882a593Smuzhiyun 		.driver_data = &quirk_asus_ux303ub,
381*4882a593Smuzhiyun 	},
382*4882a593Smuzhiyun 	{
383*4882a593Smuzhiyun 		.callback = dmi_matched,
384*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. UX330UAK",
385*4882a593Smuzhiyun 		.matches = {
386*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
387*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "UX330UAK"),
388*4882a593Smuzhiyun 		},
389*4882a593Smuzhiyun 		.driver_data = &quirk_asus_forceals,
390*4882a593Smuzhiyun 	},
391*4882a593Smuzhiyun 	{
392*4882a593Smuzhiyun 		.callback = dmi_matched,
393*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. X550LB",
394*4882a593Smuzhiyun 		.matches = {
395*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
396*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "X550LB"),
397*4882a593Smuzhiyun 		},
398*4882a593Smuzhiyun 		.driver_data = &quirk_asus_x550lb,
399*4882a593Smuzhiyun 	},
400*4882a593Smuzhiyun 	{
401*4882a593Smuzhiyun 		.callback = dmi_matched,
402*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. UX430UQ",
403*4882a593Smuzhiyun 		.matches = {
404*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
405*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "UX430UQ"),
406*4882a593Smuzhiyun 		},
407*4882a593Smuzhiyun 		.driver_data = &quirk_asus_forceals,
408*4882a593Smuzhiyun 	},
409*4882a593Smuzhiyun 	{
410*4882a593Smuzhiyun 		.callback = dmi_matched,
411*4882a593Smuzhiyun 		.ident = "ASUSTeK COMPUTER INC. UX430UNR",
412*4882a593Smuzhiyun 		.matches = {
413*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
414*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "UX430UNR"),
415*4882a593Smuzhiyun 		},
416*4882a593Smuzhiyun 		.driver_data = &quirk_asus_forceals,
417*4882a593Smuzhiyun 	},
418*4882a593Smuzhiyun 	{
419*4882a593Smuzhiyun 		.callback = dmi_matched,
420*4882a593Smuzhiyun 		.ident = "Asus Transformer T100TA / T100HA / T100CHI",
421*4882a593Smuzhiyun 		.matches = {
422*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
423*4882a593Smuzhiyun 			/* Match *T100* */
424*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "T100"),
425*4882a593Smuzhiyun 		},
426*4882a593Smuzhiyun 		.driver_data = &quirk_asus_use_kbd_dock_devid,
427*4882a593Smuzhiyun 	},
428*4882a593Smuzhiyun 	{
429*4882a593Smuzhiyun 		.callback = dmi_matched,
430*4882a593Smuzhiyun 		.ident = "Asus Transformer T101HA",
431*4882a593Smuzhiyun 		.matches = {
432*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
433*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "T101HA"),
434*4882a593Smuzhiyun 		},
435*4882a593Smuzhiyun 		.driver_data = &quirk_asus_use_kbd_dock_devid,
436*4882a593Smuzhiyun 	},
437*4882a593Smuzhiyun 	{
438*4882a593Smuzhiyun 		.callback = dmi_matched,
439*4882a593Smuzhiyun 		.ident = "Asus Transformer T200TA",
440*4882a593Smuzhiyun 		.matches = {
441*4882a593Smuzhiyun 			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
442*4882a593Smuzhiyun 			DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"),
443*4882a593Smuzhiyun 		},
444*4882a593Smuzhiyun 		.driver_data = &quirk_asus_use_kbd_dock_devid,
445*4882a593Smuzhiyun 	},
446*4882a593Smuzhiyun 	{},
447*4882a593Smuzhiyun };
448*4882a593Smuzhiyun 
asus_nb_wmi_quirks(struct asus_wmi_driver * driver)449*4882a593Smuzhiyun static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun 	int ret;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	quirks = &quirk_asus_unknown;
454*4882a593Smuzhiyun 	dmi_check_system(asus_quirks);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	driver->quirks = quirks;
457*4882a593Smuzhiyun 	driver->panel_power = FB_BLANK_UNBLANK;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	/* overwrite the wapf setting if the wapf paramater is specified */
460*4882a593Smuzhiyun 	if (wapf != -1)
461*4882a593Smuzhiyun 		quirks->wapf = wapf;
462*4882a593Smuzhiyun 	else
463*4882a593Smuzhiyun 		wapf = quirks->wapf;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	if (quirks->i8042_filter) {
466*4882a593Smuzhiyun 		ret = i8042_install_filter(quirks->i8042_filter);
467*4882a593Smuzhiyun 		if (ret) {
468*4882a593Smuzhiyun 			pr_warn("Unable to install key filter\n");
469*4882a593Smuzhiyun 			return;
470*4882a593Smuzhiyun 		}
471*4882a593Smuzhiyun 		pr_info("Using i8042 filter function for receiving events\n");
472*4882a593Smuzhiyun 	}
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun static const struct key_entry asus_nb_wmi_keymap[] = {
476*4882a593Smuzhiyun 	{ KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } },
477*4882a593Smuzhiyun 	{ KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } },
478*4882a593Smuzhiyun 	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
479*4882a593Smuzhiyun 	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
480*4882a593Smuzhiyun 	{ KE_KEY, 0x32, { KEY_MUTE } },
481*4882a593Smuzhiyun 	{ KE_KEY, 0x35, { KEY_SCREENLOCK } },
482*4882a593Smuzhiyun 	{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
483*4882a593Smuzhiyun 	{ KE_KEY, 0x41, { KEY_NEXTSONG } },
484*4882a593Smuzhiyun 	{ KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */
485*4882a593Smuzhiyun 	{ KE_KEY, 0x45, { KEY_PLAYPAUSE } },
486*4882a593Smuzhiyun 	{ KE_KEY, 0x4c, { KEY_MEDIA } }, /* WMP Key */
487*4882a593Smuzhiyun 	{ KE_KEY, 0x50, { KEY_EMAIL } },
488*4882a593Smuzhiyun 	{ KE_KEY, 0x51, { KEY_WWW } },
489*4882a593Smuzhiyun 	{ KE_KEY, 0x55, { KEY_CALC } },
490*4882a593Smuzhiyun 	{ KE_IGNORE, 0x57, },  /* Battery mode */
491*4882a593Smuzhiyun 	{ KE_IGNORE, 0x58, },  /* AC mode */
492*4882a593Smuzhiyun 	{ KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
493*4882a593Smuzhiyun 	{ KE_KEY, 0x5D, { KEY_WLAN } }, /* Wireless console Toggle */
494*4882a593Smuzhiyun 	{ KE_KEY, 0x5E, { KEY_WLAN } }, /* Wireless console Enable */
495*4882a593Smuzhiyun 	{ KE_KEY, 0x5F, { KEY_WLAN } }, /* Wireless console Disable */
496*4882a593Smuzhiyun 	{ KE_KEY, 0x60, { KEY_TOUCHPAD_ON } },
497*4882a593Smuzhiyun 	{ KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD only */
498*4882a593Smuzhiyun 	{ KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT only */
499*4882a593Smuzhiyun 	{ KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT */
500*4882a593Smuzhiyun 	{ KE_KEY, 0x64, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV */
501*4882a593Smuzhiyun 	{ KE_KEY, 0x65, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV */
502*4882a593Smuzhiyun 	{ KE_KEY, 0x66, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV */
503*4882a593Smuzhiyun 	{ KE_KEY, 0x67, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV */
504*4882a593Smuzhiyun 	{ KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
505*4882a593Smuzhiyun 	{ KE_IGNORE, 0x6E, },  /* Low Battery notification */
506*4882a593Smuzhiyun 	{ KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */
507*4882a593Smuzhiyun 	{ KE_IGNORE, 0x79, },  /* Charger type dectection notification */
508*4882a593Smuzhiyun 	{ KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */
509*4882a593Smuzhiyun 	{ KE_KEY, 0x7c, { KEY_MICMUTE } },
510*4882a593Smuzhiyun 	{ KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */
511*4882a593Smuzhiyun 	{ KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */
512*4882a593Smuzhiyun 	{ KE_KEY, 0x82, { KEY_CAMERA } },
513*4882a593Smuzhiyun 	{ KE_KEY, 0x88, { KEY_RFKILL  } }, /* Radio Toggle Key */
514*4882a593Smuzhiyun 	{ KE_KEY, 0x8A, { KEY_PROG1 } }, /* Color enhancement mode */
515*4882a593Smuzhiyun 	{ KE_KEY, 0x8C, { KEY_SWITCHVIDEOMODE } }, /* SDSP DVI only */
516*4882a593Smuzhiyun 	{ KE_KEY, 0x8D, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + DVI */
517*4882a593Smuzhiyun 	{ KE_KEY, 0x8E, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + DVI */
518*4882a593Smuzhiyun 	{ KE_KEY, 0x8F, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + DVI */
519*4882a593Smuzhiyun 	{ KE_KEY, 0x90, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + DVI */
520*4882a593Smuzhiyun 	{ KE_KEY, 0x91, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + DVI */
521*4882a593Smuzhiyun 	{ KE_KEY, 0x92, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + DVI */
522*4882a593Smuzhiyun 	{ KE_KEY, 0x93, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + DVI */
523*4882a593Smuzhiyun 	{ KE_KEY, 0x95, { KEY_MEDIA } },
524*4882a593Smuzhiyun 	{ KE_KEY, 0x99, { KEY_PHONE } }, /* Conflicts with fan mode switch */
525*4882a593Smuzhiyun 	{ KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */
526*4882a593Smuzhiyun 	{ KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */
527*4882a593Smuzhiyun 	{ KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */
528*4882a593Smuzhiyun 	{ KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */
529*4882a593Smuzhiyun 	{ KE_KEY, 0xA4, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + HDMI */
530*4882a593Smuzhiyun 	{ KE_KEY, 0xA5, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + TV + HDMI */
531*4882a593Smuzhiyun 	{ KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */
532*4882a593Smuzhiyun 	{ KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */
533*4882a593Smuzhiyun 	{ KE_KEY, 0xB5, { KEY_CALC } },
534*4882a593Smuzhiyun 	{ KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
535*4882a593Smuzhiyun 	{ KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
536*4882a593Smuzhiyun 	{ KE_IGNORE, 0xC6, },  /* Ambient Light Sensor notification */
537*4882a593Smuzhiyun 	{ KE_KEY, 0xFA, { KEY_PROG2 } },           /* Lid flip action */
538*4882a593Smuzhiyun 	{ KE_END, 0},
539*4882a593Smuzhiyun };
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun static struct asus_wmi_driver asus_nb_wmi_driver = {
542*4882a593Smuzhiyun 	.name = ASUS_NB_WMI_FILE,
543*4882a593Smuzhiyun 	.owner = THIS_MODULE,
544*4882a593Smuzhiyun 	.event_guid = ASUS_NB_WMI_EVENT_GUID,
545*4882a593Smuzhiyun 	.keymap = asus_nb_wmi_keymap,
546*4882a593Smuzhiyun 	.input_name = "Asus WMI hotkeys",
547*4882a593Smuzhiyun 	.input_phys = ASUS_NB_WMI_FILE "/input0",
548*4882a593Smuzhiyun 	.detect_quirks = asus_nb_wmi_quirks,
549*4882a593Smuzhiyun };
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 
asus_nb_wmi_init(void)552*4882a593Smuzhiyun static int __init asus_nb_wmi_init(void)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun 	return asus_wmi_register_driver(&asus_nb_wmi_driver);
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun 
asus_nb_wmi_exit(void)557*4882a593Smuzhiyun static void __exit asus_nb_wmi_exit(void)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun 	asus_wmi_unregister_driver(&asus_nb_wmi_driver);
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun module_init(asus_nb_wmi_init);
563*4882a593Smuzhiyun module_exit(asus_nb_wmi_exit);
564