ThinkPad X1 Tablets emit HKEY 0x4012 and 0x4013 events when a keyboard cover is attached/detached or folded to the back of the device. They are used to switch from normal to tablet mode in userspace; e.g., to offer touch keyboard choices when focus goes to a text box and no keyboard is attached, or to enable autorotation of the display according to the built-in orientation sensor. This patch handles the two events by issuing corresponding SW_TABLET_MODE notifications to the ACPI userspace. Tested as working on a ThinkPad X1 Tablet Gen 2, 20JCS00C00, and as non-interfering with a ThinkPad X1 Carbon 7th, 20QESABM02 (normal clamshell, so it does not have a keyboard cover). Signed-off-by: Alexander Kobel <a-kobel@xxxxxxxxxx> --- drivers/platform/x86/thinkpad_acpi.c | 91 +++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index c404706379d9..8c1ff555f10b 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -174,6 +174,11 @@ enum tpacpi_hkey_event_t { or port replicator */ TP_HKEY_EV_HOTPLUG_UNDOCK = 0x4011, /* undocked from hotplug dock or port replicator */ + /* Thinkpad X1 Tablet series (and probably other GTOP type 4) emit 0x4012 and 0x4013 + * when keyboard cover is attached, detached or folded onto the back + */ + TP_HKEY_EV_KBD_COVER_ATTACH = 0x4012, /* keyboard cover attached */ + TP_HKEY_EV_KBD_COVER_DETACH = 0x4013, /* keyboard cover detached or folded back */ /* User-interface events */ TP_HKEY_EV_LID_CLOSE = 0x5001, /* laptop lid closed */ @@ -308,6 +313,8 @@ static struct { TP_HOTKEY_TABLET_NONE = 0, TP_HOTKEY_TABLET_USES_MHKG, TP_HOTKEY_TABLET_USES_GMMS, + TP_HOTKEY_TABLET_USES_GTOP_ANY_TYPE, + TP_HOTKEY_TABLET_USES_GTOP_X1_TABLET_TYPE, } hotkey_tablet; u32 kbdlight:1; u32 light:1; @@ -2166,11 +2173,32 @@ static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode) return !!(mode & TP_ACPI_MULTI_MODE_TABLET_LIKE); } +static int hotkey_gtop_any_type_get_tablet_mode(int s) +{ + return !(s & 0x1); +} + +static int hotkey_gtop_x1_tablet_type_get_tablet_mode(int s) +{ + return (!(s & 0x1) /* keyboard NOT attached */ + || ((s >> 16) & 0x1) /* or folded onto the back */); +} + static int hotkey_get_tablet_mode(int *status) { int s; switch (tp_features.hotkey_tablet) { + case TP_HOTKEY_TABLET_USES_GTOP_ANY_TYPE: + if (!acpi_evalf(hkey_handle, &s, "GTOP", "dd", 0x0200)) + return -EIO; + *status = hotkey_gtop_any_type_get_tablet_mode(s); + break; + case TP_HOTKEY_TABLET_USES_GTOP_X1_TABLET_TYPE: + if (!acpi_evalf(hkey_handle, &s, "GTOP", "dd", 0x0200)) + return -EIO; + *status = hotkey_gtop_x1_tablet_type_get_tablet_mode(s); + break; case TP_HOTKEY_TABLET_USES_MHKG: if (!acpi_evalf(hkey_handle, &s, "MHKG", "d")) return -EIO; @@ -3213,7 +3241,62 @@ static int hotkey_init_tablet_mode(void) int in_tablet_mode = 0, res; char *type = NULL; - if (acpi_evalf(hkey_handle, &res, "GMMS", "qdd", 0)) { + if (acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x0000) + && res >= 0x0103 + && acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x0100)) { + /* + * GTOP ("Get Tablet OPtion") state ASL method definition: + * - Input: 0x0000: Query version + * Output: 0x0103 (version 1.03) + * - Input: 0x0100: Query interface type + * Output: DWORD But 31-0 Interface type + * 0: Reserved + * 1: Any type + * 2: ThinkPad Helix series + * 3: ThinkPad 10 series + * 4: ThinkPad X1 Tablet series + * - Input: 0x0200: Get attach option + * Output: Option attach state + * (0: detached, 1: attached) + * version >= 1.03 and interface type 1: + * Bit 0: Any option attach state + * Bit 31-1: Reserved(0) + * version >= 1.03 and interface type 4: + * Bit 0: Thin-KBD attach state + * Bit 1: Pro-Cartridge attach state + * Bit 3-2: Pico-Cartridge attach state + * 00: detached + * 01: attached + * 10: attached with battery error + * 11: Reserved + * Bit 4: 3D Cartridge attach state + * Bit 5: Reserve 1 attach state + * Bit 6: Reserve 2 attach state + * Bit 15-7: Reserved(0) + * Bit 16: Folio keyboard location + * (valid if folio attached) + * 0: keyboard is NOT folded onto the back + * 1: keyboard is folded onto the back of the system + * Bit 31-17: Reserved(0) + */ + switch (res) { + case 1: + tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GTOP_ANY_TYPE; + if (acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x200)) + in_tablet_mode = hotkey_gtop_any_type_get_tablet_mode(res); + type = "GTOP"; + break; + case 4: + tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GTOP_X1_TABLET_TYPE; + if (acpi_evalf(hkey_handle, &res, "GTOP", "qdd", 0x200)) + in_tablet_mode = hotkey_gtop_x1_tablet_type_get_tablet_mode(res); + type = "GTOP"; + break; + default: + pr_err("unsupported GTOP type, please report this to %s\n", TPACPI_MAIL); + break; + } + } else if (acpi_evalf(hkey_handle, &res, "GMMS", "qdd", 0)) { int has_tablet_mode; in_tablet_mode = hotkey_gmms_get_tablet_mode(res, @@ -3989,6 +4072,12 @@ static bool hotkey_notify_dockevent(const u32 hkey, case TP_HKEY_EV_HOTPLUG_UNDOCK: /* undocked from port replicator */ pr_info("undocked from hotplug port replicator\n"); return true; + case TP_HKEY_EV_KBD_COVER_ATTACH: + case TP_HKEY_EV_KBD_COVER_DETACH: + tpacpi_input_send_tabletsw(); + hotkey_tablet_mode_notify_change(); + *send_acpi_ev = false; + return true; default: return false; -- 2.30.1
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature