Re: [PATCH 1/1] asus-wmi: Add support for ROG X13 tablet mode

From: Hans de Goede
Date: Thu Aug 04 2022 - 09:51:43 EST


Hi,

On 8/3/22 08:37, Luke D. Jones wrote:
> Add quirk for ASUS ROG X13 Flow 2-in-1 to enable tablet mode with
> lid flip (all screen rotations).
>
> Signed-off-by: Luke D. Jones <luke@xxxxxxxxxx>
> ---
> drivers/platform/x86/asus-nb-wmi.c | 16 ++++++++++++++++
> drivers/platform/x86/asus-wmi.c | 16 +++++++++++++++-
> drivers/platform/x86/asus-wmi.h | 1 +
> include/linux/platform_data/x86/asus-wmi.h | 1 +
> 4 files changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
> index 478dd300b9c9..1ce8924d0474 100644
> --- a/drivers/platform/x86/asus-nb-wmi.c
> +++ b/drivers/platform/x86/asus-nb-wmi.c
> @@ -123,6 +123,12 @@ static struct quirk_entry quirk_asus_use_lid_flip_devid = {
> .use_lid_flip_devid = true,
> };
>
> +static struct quirk_entry quirk_asus_gv301 = {
> + .wmi_backlight_set_devstate = true,
> + .use_lid_flip_devid = true,
> + .enodev_as_tablet_mode = true,
> +};
> +
> static int dmi_matched(const struct dmi_system_id *dmi)
> {
> pr_info("Identified laptop model '%s'\n", dmi->ident);
> @@ -471,6 +477,15 @@ static const struct dmi_system_id asus_quirks[] = {
> },
> .driver_data = &quirk_asus_use_lid_flip_devid,
> },
> + {
> + .callback = dmi_matched,
> + .ident = "ASUS ROG FLOW X13",
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
> + DMI_MATCH(DMI_PRODUCT_NAME, "GV301Q"),
> + },
> + .driver_data = &quirk_asus_gv301,
> + },
> {},
> };
>
> @@ -581,6 +596,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
> { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
> { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */
> { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */
> + { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on rog flow laptops */

asus_wmi_handle_event_code() will never get to the part where it parses
the keymap since it has:

if (asus->driver->quirks->use_lid_flip_devid &&
(code == NOTIFY_LID_FLIP || code == NOTIFY_LID_FLIP_GV301)) {
lid_flip_tablet_mode_get_state(asus);
return;
}

after this patch. The old 0xFA mapping is there from before we had LID switch
reporting on devices using ASUS_WMI_DEVID_LID_FLIP. I don't believe adding
an extra entry for this is necessary; nor is it a good idea since then
userspace might become to rely on these events which we don't want.



> { KE_END, 0},
> };
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index 62ce198a3463..0458e9107ca7 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -68,6 +68,7 @@ module_param(fnlock_default, bool, 0444);
> #define NOTIFY_KBD_FBM 0x99
> #define NOTIFY_KBD_TTP 0xae
> #define NOTIFY_LID_FLIP 0xfa
> +#define NOTIFY_LID_FLIP_GV301 0xbd
>
> #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0)
>
> @@ -516,6 +517,12 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
>
> if (asus->driver->quirks->use_lid_flip_devid) {
> result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP);
> + if (result < 0)
> + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GV301_LID_FLIP);
> +
> + if (result == -ENODEV && asus->driver->quirks->enodev_as_tablet_mode)
> + result = 1;
> +

Looking at the handling of this here.

> if (result < 0)
> asus->driver->quirks->use_lid_flip_devid = 0;
> if (result >= 0) {
> @@ -553,6 +560,12 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus)
> {
> int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP);
>
> + if (result < 0)
> + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GV301_LID_FLIP);
> +
> + if (result == -ENODEV && asus->driver->quirks->enodev_as_tablet_mode)
> + result = 1;
> +

And here.

> if (result >= 0) {
> input_report_switch(asus->inputdev, SW_TABLET_MODE, result);
> input_sync(asus->inputdev);
> @@ -3094,7 +3107,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus)
> return;
> }
>
> - if (asus->driver->quirks->use_lid_flip_devid && code == NOTIFY_LID_FLIP) {
> + if (asus->driver->quirks->use_lid_flip_devid &&
> + (code == NOTIFY_LID_FLIP || code == NOTIFY_LID_FLIP_GV301)) {
> lid_flip_tablet_mode_get_state(asus);
> return;
> }

and here. This really just is an entirely different code flow from the
devices using ASUS_WMI_DEVID_LID_FLIP.

I think it would be better to instead of the enodev_as_tablet_mode quirk, to
do a preparation patch 1/2 adding a:

enum asus_wmi_tablet_switch_mode {
asus_wmi_no_tablet_switch,
asus_wmi_kbd_dock_devid,
asus_Wmi_lid_flip_devid,
asus_wmi_gv301_lid_flip_devid, /* to be added in patch 2/2 */
};

and then in the quirks struct replace:

bool use_kbd_dock_devid;
bool use_lid_flip_devid;

with:

enum asus_wmi_tablet_switch_mode tablet_switch_mode;

Adjust the quirks to set this to the right value and then where
the current code has the following pattern:

if (asus->driver->quirks->use_kbd_dock_devid) {
<kbd_dock_devid handling>;
}

if (asus->driver->quirks->use_lid_flip_devid) {
<lid_flip_devid handling>;
}

replace this with:

switch (asus->driver->quirks->tablet_switch_mode) {
case asus_wmi_no_tablet_switch:
break;
case asus_wmi_kbd_dock_devid:
<kbd_dock_devid handling>;
break;
case asus_Wmi_lid_flip_devid:
<lid_flip_devid handling>;
break;
}

And then in patch 2/2 add asus_wmi_gv301_lid_flip_devid to the enum
and extend the switch-cases with the necessary handling for the new
tablet-mode-switch type.

Regards,

Hans



> diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
> index b302415bf1d9..ac9023aae838 100644
> --- a/drivers/platform/x86/asus-wmi.h
> +++ b/drivers/platform/x86/asus-wmi.h
> @@ -35,6 +35,7 @@ struct quirk_entry {
> bool wmi_force_als_set;
> bool use_kbd_dock_devid;
> bool use_lid_flip_devid;
> + bool enodev_as_tablet_mode;
> int wapf;
> /*
> * For machines with AMD graphic chips, it will send out WMI event
> diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
> index a571b47ff362..79bd06628a8b 100644
> --- a/include/linux/platform_data/x86/asus-wmi.h
> +++ b/include/linux/platform_data/x86/asus-wmi.h
> @@ -64,6 +64,7 @@
> #define ASUS_WMI_DEVID_PANEL_OD 0x00050019
> #define ASUS_WMI_DEVID_CAMERA 0x00060013
> #define ASUS_WMI_DEVID_LID_FLIP 0x00060062
> +#define ASUS_WMI_DEVID_GV301_LID_FLIP 0x00060077
>
> /* Storage */
> #define ASUS_WMI_DEVID_CARDREADER 0x00080013