Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/x86: asus-wmi: Add support for SW_TABLET_MODE on UX360

The UX360CA has a WMI device id 0x00060062, which reports whether the
lid is flipped in tablet mode (1) or in normal laptop mode (0).

Add a quirk (quirk_asus_use_lid_flip_devid) for devices on which this
WMI device should be used to figure out the SW_TABLET_MODE state, as
opposed to the quirk_asus_use_kbd_dock_devid.

Additionally, the device needs to be queried on resume and restore
because the firmware does not generate an event if the laptop is put to
sleep while in tablet mode, flipped to normal mode, and later awoken.

It is assumed other UX360* models have the same WMI device. As such, the
quirk is applied to devices with DMI_MATCH(DMI_PRODUCT_NAME, "UX360").
More devices with this feature need to be tested and added accordingly.

The reason for using an allowlist via the quirk mechanism is that the new
WMI device (0x00060062) is also present on some models which do not have
a 360 degree hinge (at least FX503VD and GL503VD from Hans' DSTS
collection) and therefore its presence cannot be relied on.

Signed-off-by: Samuel Čavoj <samuel@cavoj.net>
Cc: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20201020220944.1075530-1-samuel@cavoj.net
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Samuel Čavoj and committed by
Hans de Goede
ea856ec2 61982193

+57
+15
drivers/platform/x86/asus-nb-wmi.c
··· 119 119 .use_kbd_dock_devid = true, 120 120 }; 121 121 122 + static struct quirk_entry quirk_asus_use_lid_flip_devid = { 123 + .wmi_backlight_set_devstate = true, 124 + .use_lid_flip_devid = true, 125 + }; 126 + 122 127 static int dmi_matched(const struct dmi_system_id *dmi) 123 128 { 124 129 pr_info("Identified laptop model '%s'\n", dmi->ident); ··· 524 519 DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"), 525 520 }, 526 521 .driver_data = &quirk_asus_use_kbd_dock_devid, 522 + }, 523 + { 524 + .callback = dmi_matched, 525 + .ident = "ASUS ZenBook Flip UX360", 526 + .matches = { 527 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 528 + /* Match UX360* */ 529 + DMI_MATCH(DMI_PRODUCT_NAME, "UX360"), 530 + }, 531 + .driver_data = &quirk_asus_use_lid_flip_devid, 527 532 }, 528 533 {}, 529 534 };
+40
drivers/platform/x86/asus-wmi.c
··· 63 63 #define NOTIFY_KBD_BRTTOGGLE 0xc7 64 64 #define NOTIFY_KBD_FBM 0x99 65 65 #define NOTIFY_KBD_TTP 0xae 66 + #define NOTIFY_LID_FLIP 0xfa 66 67 67 68 #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0) 68 69 ··· 376 375 } 377 376 } 378 377 378 + if (asus->driver->quirks->use_lid_flip_devid) { 379 + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); 380 + if (result < 0) 381 + asus->driver->quirks->use_lid_flip_devid = 0; 382 + if (result >= 0) { 383 + input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); 384 + input_report_switch(asus->inputdev, SW_TABLET_MODE, result); 385 + } else if (result == -ENODEV) { 386 + pr_err("This device has lid_flip quirk but got ENODEV checking it. This is a bug."); 387 + } else { 388 + pr_err("Error checking for lid-flip: %d\n", result); 389 + } 390 + } 391 + 379 392 err = input_register_device(asus->inputdev); 380 393 if (err) 381 394 goto err_free_dev; ··· 407 392 input_unregister_device(asus->inputdev); 408 393 409 394 asus->inputdev = NULL; 395 + } 396 + 397 + /* Tablet mode ****************************************************************/ 398 + 399 + static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) 400 + { 401 + int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); 402 + 403 + if (result >= 0) { 404 + input_report_switch(asus->inputdev, SW_TABLET_MODE, result); 405 + input_sync(asus->inputdev); 406 + } 410 407 } 411 408 412 409 /* Battery ********************************************************************/ ··· 2155 2128 return; 2156 2129 } 2157 2130 2131 + if (asus->driver->quirks->use_lid_flip_devid && code == NOTIFY_LID_FLIP) { 2132 + lid_flip_tablet_mode_get_state(asus); 2133 + return; 2134 + } 2135 + 2158 2136 if (asus->fan_boost_mode_available && code == NOTIFY_KBD_FBM) { 2159 2137 fan_boost_mode_switch_next(asus); 2160 2138 return; ··· 2751 2719 2752 2720 if (asus_wmi_has_fnlock_key(asus)) 2753 2721 asus_wmi_fnlock_update(asus); 2722 + 2723 + if (asus->driver->quirks->use_lid_flip_devid) 2724 + lid_flip_tablet_mode_get_state(asus); 2725 + 2754 2726 return 0; 2755 2727 } 2756 2728 ··· 2793 2757 2794 2758 if (asus_wmi_has_fnlock_key(asus)) 2795 2759 asus_wmi_fnlock_update(asus); 2760 + 2761 + if (asus->driver->quirks->use_lid_flip_devid) 2762 + lid_flip_tablet_mode_get_state(asus); 2763 + 2796 2764 return 0; 2797 2765 } 2798 2766
+1
drivers/platform/x86/asus-wmi.h
··· 34 34 bool wmi_backlight_set_devstate; 35 35 bool wmi_force_als_set; 36 36 bool use_kbd_dock_devid; 37 + bool use_lid_flip_devid; 37 38 int wapf; 38 39 /* 39 40 * For machines with AMD graphic chips, it will send out WMI event
+1
include/linux/platform_data/x86/asus-wmi.h
··· 62 62 63 63 /* Misc */ 64 64 #define ASUS_WMI_DEVID_CAMERA 0x00060013 65 + #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 65 66 66 67 /* Storage */ 67 68 #define ASUS_WMI_DEVID_CARDREADER 0x00080013