aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/msi-wmi.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index 739bd4d17c23..70222f265f68 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -37,17 +37,27 @@ MODULE_LICENSE("GPL");
37#define DRV_NAME "msi-wmi" 37#define DRV_NAME "msi-wmi"
38 38
39#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45" 39#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
40#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2" 40#define MSIWMI_MSI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
41#define MSIWMI_WIND_EVENT_GUID "5B3CC38A-40D9-7245-8AE6-1145B751BE3F"
41 42
42MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID); 43MODULE_ALIAS("wmi:" MSIWMI_BIOS_GUID);
43MODULE_ALIAS("wmi:" MSIWMI_EVENT_GUID); 44MODULE_ALIAS("wmi:" MSIWMI_MSI_EVENT_GUID);
45MODULE_ALIAS("wmi:" MSIWMI_WIND_EVENT_GUID);
44 46
45enum msi_scancodes { 47enum msi_scancodes {
48 /* Generic MSI keys (not present on MSI Wind) */
46 MSI_KEY_BRIGHTNESSUP = 0xD0, 49 MSI_KEY_BRIGHTNESSUP = 0xD0,
47 MSI_KEY_BRIGHTNESSDOWN, 50 MSI_KEY_BRIGHTNESSDOWN,
48 MSI_KEY_VOLUMEUP, 51 MSI_KEY_VOLUMEUP,
49 MSI_KEY_VOLUMEDOWN, 52 MSI_KEY_VOLUMEDOWN,
50 MSI_KEY_MUTE, 53 MSI_KEY_MUTE,
54 /* MSI Wind keys */
55 WIND_KEY_TOUCHPAD = 0x08, /* Fn+F3 touchpad toggle */
56 WIND_KEY_BLUETOOTH = 0x56, /* Fn+F11 Bluetooth toggle */
57 WIND_KEY_CAMERA, /* Fn+F6 webcam toggle */
58 WIND_KEY_WLAN = 0x5f, /* Fn+F11 Wi-Fi toggle */
59 WIND_KEY_TURBO, /* Fn+F10 turbo mode toggle */
60 WIND_KEY_ECO = 0x69, /* Fn+F10 ECO mode toggle */
51}; 61};
52static struct key_entry msi_wmi_keymap[] = { 62static struct key_entry msi_wmi_keymap[] = {
53 { KE_KEY, MSI_KEY_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} }, 63 { KE_KEY, MSI_KEY_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} },
@@ -55,13 +65,34 @@ static struct key_entry msi_wmi_keymap[] = {
55 { KE_KEY, MSI_KEY_VOLUMEUP, {KEY_VOLUMEUP} }, 65 { KE_KEY, MSI_KEY_VOLUMEUP, {KEY_VOLUMEUP} },
56 { KE_KEY, MSI_KEY_VOLUMEDOWN, {KEY_VOLUMEDOWN} }, 66 { KE_KEY, MSI_KEY_VOLUMEDOWN, {KEY_VOLUMEDOWN} },
57 { KE_KEY, MSI_KEY_MUTE, {KEY_MUTE} }, 67 { KE_KEY, MSI_KEY_MUTE, {KEY_MUTE} },
68
69 /* These keys work without WMI. Ignore them to avoid double keycodes */
70 { KE_IGNORE, WIND_KEY_TOUCHPAD, {KEY_TOUCHPAD_TOGGLE} },
71 { KE_IGNORE, WIND_KEY_BLUETOOTH, {KEY_BLUETOOTH} },
72 { KE_IGNORE, WIND_KEY_CAMERA, {KEY_CAMERA} },
73 { KE_IGNORE, WIND_KEY_WLAN, {KEY_WLAN} },
74
75 /* These are unknown WMI events found on MSI Wind */
76 { KE_IGNORE, 0x00 },
77 { KE_IGNORE, 0x62 },
78 { KE_IGNORE, 0x63 },
79
80 /* These are MSI Wind keys that should be handled via WMI */
81 { KE_KEY, WIND_KEY_TURBO, {KEY_PROG1} },
82 { KE_KEY, WIND_KEY_ECO, {KEY_PROG2} },
83
58 { KE_END, 0 } 84 { KE_END, 0 }
59}; 85};
60 86
61static ktime_t last_pressed; 87static ktime_t last_pressed;
62static bool quirk_last_pressed;
63 88
64static const char *event_wmi_guid; 89static const struct {
90 const char *guid;
91 bool quirk_last_pressed;
92} *event_wmi, event_wmis[] = {
93 { MSIWMI_MSI_EVENT_GUID, true },
94 { MSIWMI_WIND_EVENT_GUID, false },
95};
65 96
66static struct backlight_device *backlight; 97static struct backlight_device *backlight;
67 98
@@ -174,7 +205,7 @@ static void msi_wmi_notify(u32 value, void *context)
174 goto msi_wmi_notify_exit; 205 goto msi_wmi_notify_exit;
175 } 206 }
176 207
177 if (quirk_last_pressed) { 208 if (event_wmi->quirk_last_pressed) {
178 ktime_t cur = ktime_get_real(); 209 ktime_t cur = ktime_get_real();
179 ktime_t diff = ktime_sub(cur, last_pressed); 210 ktime_t diff = ktime_sub(cur, last_pressed);
180 /* Ignore event if any event happened in a 50 ms 211 /* Ignore event if any event happened in a 50 ms
@@ -265,15 +296,19 @@ err_free_dev:
265static int __init msi_wmi_init(void) 296static int __init msi_wmi_init(void)
266{ 297{
267 int err; 298 int err;
299 int i;
300
301 for (i = 0; i < ARRAY_SIZE(event_wmis); i++) {
302 if (!wmi_has_guid(event_wmis[i].guid))
303 continue;
268 304
269 if (wmi_has_guid(MSIWMI_EVENT_GUID)) {
270 err = msi_wmi_input_setup(); 305 err = msi_wmi_input_setup();
271 if (err) { 306 if (err) {
272 pr_err("Unable to setup input device\n"); 307 pr_err("Unable to setup input device\n");
273 return err; 308 return err;
274 } 309 }
275 310
276 err = wmi_install_notify_handler(MSIWMI_EVENT_GUID, 311 err = wmi_install_notify_handler(event_wmis[i].guid,
277 msi_wmi_notify, NULL); 312 msi_wmi_notify, NULL);
278 if (ACPI_FAILURE(err)) { 313 if (ACPI_FAILURE(err)) {
279 pr_err("Unable to setup WMI notify handler\n"); 314 pr_err("Unable to setup WMI notify handler\n");
@@ -281,8 +316,8 @@ static int __init msi_wmi_init(void)
281 } 316 }
282 317
283 pr_debug("Event handler installed\n"); 318 pr_debug("Event handler installed\n");
284 event_wmi_guid = MSIWMI_EVENT_GUID; 319 event_wmi = &event_wmis[i];
285 quirk_last_pressed = true; 320 break;
286 } 321 }
287 322
288 if (wmi_has_guid(MSIWMI_BIOS_GUID) && !acpi_video_backlight_support()) { 323 if (wmi_has_guid(MSIWMI_BIOS_GUID) && !acpi_video_backlight_support()) {
@@ -294,7 +329,7 @@ static int __init msi_wmi_init(void)
294 pr_debug("Backlight device created\n"); 329 pr_debug("Backlight device created\n");
295 } 330 }
296 331
297 if (!event_wmi_guid && !backlight) { 332 if (!event_wmi && !backlight) {
298 pr_err("This machine doesn't have neither MSI-hotkeys nor backlight through WMI\n"); 333 pr_err("This machine doesn't have neither MSI-hotkeys nor backlight through WMI\n");
299 return -ENODEV; 334 return -ENODEV;
300 } 335 }
@@ -302,10 +337,10 @@ static int __init msi_wmi_init(void)
302 return 0; 337 return 0;
303 338
304err_uninstall_handler: 339err_uninstall_handler:
305 if (event_wmi_guid) 340 if (event_wmi)
306 wmi_remove_notify_handler(event_wmi_guid); 341 wmi_remove_notify_handler(event_wmi->guid);
307err_free_input: 342err_free_input:
308 if (event_wmi_guid) { 343 if (event_wmi) {
309 sparse_keymap_free(msi_wmi_input_dev); 344 sparse_keymap_free(msi_wmi_input_dev);
310 input_unregister_device(msi_wmi_input_dev); 345 input_unregister_device(msi_wmi_input_dev);
311 } 346 }
@@ -314,8 +349,8 @@ err_free_input:
314 349
315static void __exit msi_wmi_exit(void) 350static void __exit msi_wmi_exit(void)
316{ 351{
317 if (event_wmi_guid) { 352 if (event_wmi) {
318 wmi_remove_notify_handler(event_wmi_guid); 353 wmi_remove_notify_handler(event_wmi->guid);
319 sparse_keymap_free(msi_wmi_input_dev); 354 sparse_keymap_free(msi_wmi_input_dev);
320 input_unregister_device(msi_wmi_input_dev); 355 input_unregister_device(msi_wmi_input_dev);
321 } 356 }