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