Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-10-01 Thread Andy Shevchenko
On Sun, Oct 1, 2017 at 12:31 PM, Andy Shevchenko
 wrote:
> On Mon, Sep 18, 2017 at 7:00 PM, Lyude Paul  wrote:
>> Reviewed-by: Lyude Paul 
>>
>> On Fri, 2017-09-15 at 15:20 +0200, Benjamin Berg wrote:
>>> Many thinkpad laptops and convertibles provide the GMMS method to
>>> resolve how far the laptop has been opened and whether it has been
>>> converted into tablet mode. This allows reporting a more precise tablet
>>> mode state to userspace.
>>>
>>> The current implementation only reports a summarized tablet mode state
>>> which is triggered as soon as the input devices become unusable as they
>>> are folded away from the display.
>>>
>>> This will work on all models where the CMMD method was used previously and
>>> it may also work in other cases.
>>>
>>> Thanks to Peter Zhang of Lenovo for providing information on how to use the
>>> GMMS method to query the tablet mode.
>
> I dunno why this one didn't appear in our patchwork database.
> I'll go to apply manually soon.
> Sorry for the delay.

Okay, now pushed to my testing queue.

-- 
With Best Regards,
Andy Shevchenko


Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-10-01 Thread Andy Shevchenko
On Sun, Oct 1, 2017 at 12:31 PM, Andy Shevchenko
 wrote:
> On Mon, Sep 18, 2017 at 7:00 PM, Lyude Paul  wrote:
>> Reviewed-by: Lyude Paul 
>>
>> On Fri, 2017-09-15 at 15:20 +0200, Benjamin Berg wrote:
>>> Many thinkpad laptops and convertibles provide the GMMS method to
>>> resolve how far the laptop has been opened and whether it has been
>>> converted into tablet mode. This allows reporting a more precise tablet
>>> mode state to userspace.
>>>
>>> The current implementation only reports a summarized tablet mode state
>>> which is triggered as soon as the input devices become unusable as they
>>> are folded away from the display.
>>>
>>> This will work on all models where the CMMD method was used previously and
>>> it may also work in other cases.
>>>
>>> Thanks to Peter Zhang of Lenovo for providing information on how to use the
>>> GMMS method to query the tablet mode.
>
> I dunno why this one didn't appear in our patchwork database.
> I'll go to apply manually soon.
> Sorry for the delay.

Okay, now pushed to my testing queue.

-- 
With Best Regards,
Andy Shevchenko


Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-10-01 Thread Andy Shevchenko
On Mon, Sep 18, 2017 at 7:00 PM, Lyude Paul  wrote:
> Reviewed-by: Lyude Paul 
>
> On Fri, 2017-09-15 at 15:20 +0200, Benjamin Berg wrote:
>> Many thinkpad laptops and convertibles provide the GMMS method to
>> resolve how far the laptop has been opened and whether it has been
>> converted into tablet mode. This allows reporting a more precise tablet
>> mode state to userspace.
>>
>> The current implementation only reports a summarized tablet mode state
>> which is triggered as soon as the input devices become unusable as they
>> are folded away from the display.
>>
>> This will work on all models where the CMMD method was used previously and
>> it may also work in other cases.
>>
>> Thanks to Peter Zhang of Lenovo for providing information on how to use the
>> GMMS method to query the tablet mode.

I dunno why this one didn't appear in our patchwork database.
I'll go to apply manually soon.
Sorry for the delay.

-- 
With Best Regards,
Andy Shevchenko


Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-10-01 Thread Andy Shevchenko
On Mon, Sep 18, 2017 at 7:00 PM, Lyude Paul  wrote:
> Reviewed-by: Lyude Paul 
>
> On Fri, 2017-09-15 at 15:20 +0200, Benjamin Berg wrote:
>> Many thinkpad laptops and convertibles provide the GMMS method to
>> resolve how far the laptop has been opened and whether it has been
>> converted into tablet mode. This allows reporting a more precise tablet
>> mode state to userspace.
>>
>> The current implementation only reports a summarized tablet mode state
>> which is triggered as soon as the input devices become unusable as they
>> are folded away from the display.
>>
>> This will work on all models where the CMMD method was used previously and
>> it may also work in other cases.
>>
>> Thanks to Peter Zhang of Lenovo for providing information on how to use the
>> GMMS method to query the tablet mode.

I dunno why this one didn't appear in our patchwork database.
I'll go to apply manually soon.
Sorry for the delay.

-- 
With Best Regards,
Andy Shevchenko


Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-09-18 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Fri, 2017-09-15 at 15:20 +0200, Benjamin Berg wrote:
> Many thinkpad laptops and convertibles provide the GMMS method to
> resolve how far the laptop has been opened and whether it has been
> converted into tablet mode. This allows reporting a more precise tablet
> mode state to userspace.
> 
> The current implementation only reports a summarized tablet mode state
> which is triggered as soon as the input devices become unusable as they
> are folded away from the display.
> 
> This will work on all models where the CMMD method was used previously and
> it may also work in other cases.
> 
> Thanks to Peter Zhang of Lenovo for providing information on how to use the
> GMMS method to query the tablet mode.
> 
> Signed-off-by: Benjamin Berg 
> Cc: Peter FP1 Zhang 
> Cc: Lyude Paul 
> ---
>  drivers/platform/x86/thinkpad_acpi.c | 132 +++-
> ---
>  1 file changed, 119 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/platform/x86/thinkpad_acpi.c
> b/drivers/platform/x86/thinkpad_acpi.c
> index 2242d6035d9e..91fab1a13a6d 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -310,8 +310,7 @@ static struct {
>   enum {
>   TP_HOTKEY_TABLET_NONE = 0,
>   TP_HOTKEY_TABLET_USES_MHKG,
> - /* X1 Yoga 2016, seen on BIOS N1FET44W */
> - TP_HOTKEY_TABLET_USES_CMMD,
> + TP_HOTKEY_TABLET_USES_GMMS,
>   } hotkey_tablet;
>   u32 kbdlight:1;
>   u32 light:1;
> @@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn);
>  
>  /* HKEY.MHKG() return bits */
>  #define TP_HOTKEY_TABLET_MASK (1 << 3)
> -/* ThinkPad X1 Yoga (2016) */
> -#define TP_EC_CMMD_TABLET_MODE 0x6
> +enum {
> + TP_ACPI_MULTI_MODE_INVALID  = 0,
> + TP_ACPI_MULTI_MODE_UNKNOWN  = 1 << 0,
> + TP_ACPI_MULTI_MODE_LAPTOP   = 1 << 1,
> + TP_ACPI_MULTI_MODE_TABLET   = 1 << 2,
> + TP_ACPI_MULTI_MODE_FLAT = 1 << 3,
> + TP_ACPI_MULTI_MODE_STAND= 1 << 4,
> + TP_ACPI_MULTI_MODE_TENT = 1 << 5,
> + TP_ACPI_MULTI_MODE_STAND_TENT   = 1 << 6,
> +};
> +
> +enum {
> + /* The following modes are considered tablet mode for the purpose
> of
> +  * reporting the status to userspace. i.e. in all these modes it
> makes
> +  * sense to disable the laptop input devices such as touchpad and
> +  * keyboard.
> +  */
> + TP_ACPI_MULTI_MODE_TABLET_LIKE  = TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT |
> +   TP_ACPI_MULTI_MODE_STAND_TENT,
> +};
>  
>  static int hotkey_get_wlsw(void)
>  {
> @@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void)
>   return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
>  }
>  
> +static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
> +{
> + int type = (s >> 16) & 0x;
> + int value = s & 0x;
> + int mode = TP_ACPI_MULTI_MODE_INVALID;
> + int valid_modes = 0;
> +
> + if (has_tablet_mode)
> + *has_tablet_mode = 0;
> +
> + switch (type) {
> + case 1:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND_TENT;
> + break;
> + case 2:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 3:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT;
> + break;
> + case 4:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 5:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + default:
> + pr_err("Unknown multi mode status type %d with value
> 0x%04X, please report this to %s\n",
> +type, value, TPACPI_MAIL);
> + return 0;
> + }
> +
> + if (has_tablet_mode && (valid_modes &
> TP_ACPI_MULTI_MODE_TABLET_LIKE))
> + *has_tablet_mode = 1;
> +
> + switch (value) {
> + case 1:
> + 

Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-09-18 Thread Lyude Paul
Reviewed-by: Lyude Paul 

On Fri, 2017-09-15 at 15:20 +0200, Benjamin Berg wrote:
> Many thinkpad laptops and convertibles provide the GMMS method to
> resolve how far the laptop has been opened and whether it has been
> converted into tablet mode. This allows reporting a more precise tablet
> mode state to userspace.
> 
> The current implementation only reports a summarized tablet mode state
> which is triggered as soon as the input devices become unusable as they
> are folded away from the display.
> 
> This will work on all models where the CMMD method was used previously and
> it may also work in other cases.
> 
> Thanks to Peter Zhang of Lenovo for providing information on how to use the
> GMMS method to query the tablet mode.
> 
> Signed-off-by: Benjamin Berg 
> Cc: Peter FP1 Zhang 
> Cc: Lyude Paul 
> ---
>  drivers/platform/x86/thinkpad_acpi.c | 132 +++-
> ---
>  1 file changed, 119 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/platform/x86/thinkpad_acpi.c
> b/drivers/platform/x86/thinkpad_acpi.c
> index 2242d6035d9e..91fab1a13a6d 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -310,8 +310,7 @@ static struct {
>   enum {
>   TP_HOTKEY_TABLET_NONE = 0,
>   TP_HOTKEY_TABLET_USES_MHKG,
> - /* X1 Yoga 2016, seen on BIOS N1FET44W */
> - TP_HOTKEY_TABLET_USES_CMMD,
> + TP_HOTKEY_TABLET_USES_GMMS,
>   } hotkey_tablet;
>   u32 kbdlight:1;
>   u32 light:1;
> @@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn);
>  
>  /* HKEY.MHKG() return bits */
>  #define TP_HOTKEY_TABLET_MASK (1 << 3)
> -/* ThinkPad X1 Yoga (2016) */
> -#define TP_EC_CMMD_TABLET_MODE 0x6
> +enum {
> + TP_ACPI_MULTI_MODE_INVALID  = 0,
> + TP_ACPI_MULTI_MODE_UNKNOWN  = 1 << 0,
> + TP_ACPI_MULTI_MODE_LAPTOP   = 1 << 1,
> + TP_ACPI_MULTI_MODE_TABLET   = 1 << 2,
> + TP_ACPI_MULTI_MODE_FLAT = 1 << 3,
> + TP_ACPI_MULTI_MODE_STAND= 1 << 4,
> + TP_ACPI_MULTI_MODE_TENT = 1 << 5,
> + TP_ACPI_MULTI_MODE_STAND_TENT   = 1 << 6,
> +};
> +
> +enum {
> + /* The following modes are considered tablet mode for the purpose
> of
> +  * reporting the status to userspace. i.e. in all these modes it
> makes
> +  * sense to disable the laptop input devices such as touchpad and
> +  * keyboard.
> +  */
> + TP_ACPI_MULTI_MODE_TABLET_LIKE  = TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT |
> +   TP_ACPI_MULTI_MODE_STAND_TENT,
> +};
>  
>  static int hotkey_get_wlsw(void)
>  {
> @@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void)
>   return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
>  }
>  
> +static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
> +{
> + int type = (s >> 16) & 0x;
> + int value = s & 0x;
> + int mode = TP_ACPI_MULTI_MODE_INVALID;
> + int valid_modes = 0;
> +
> + if (has_tablet_mode)
> + *has_tablet_mode = 0;
> +
> + switch (type) {
> + case 1:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND_TENT;
> + break;
> + case 2:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 3:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT;
> + break;
> + case 4:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 5:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + default:
> + pr_err("Unknown multi mode status type %d with value
> 0x%04X, please report this to %s\n",
> +type, value, TPACPI_MAIL);
> + return 0;
> + }
> +
> + if (has_tablet_mode && (valid_modes &
> TP_ACPI_MULTI_MODE_TABLET_LIKE))
> + *has_tablet_mode = 1;
> +
> + switch (value) {
> + case 1:
> + mode = TP_ACPI_MULTI_MODE_LAPTOP;
> + break;
> + 

Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-09-16 Thread Henrique de Moraes Holschuh
On Fri, 15 Sep 2017, Benjamin Berg wrote:
> Many thinkpad laptops and convertibles provide the GMMS method to
> resolve how far the laptop has been opened and whether it has been
> converted into tablet mode. This allows reporting a more precise tablet
> mode state to userspace.
> 
> The current implementation only reports a summarized tablet mode state
> which is triggered as soon as the input devices become unusable as they
> are folded away from the display.
> 
> This will work on all models where the CMMD method was used previously and
> it may also work in other cases.
> 
> Thanks to Peter Zhang of Lenovo for providing information on how to use the
> GMMS method to query the tablet mode.
> 
> Signed-off-by: Benjamin Berg 
> Cc: Peter FP1 Zhang 
> Cc: Lyude Paul 

Looks good.

Acked-by: Henrique de Moraes Holschuh 

---
  PS: please send me the documentation for CMMD/GMMS off-list.

> ---
>  drivers/platform/x86/thinkpad_acpi.c | 132 
> +++
>  1 file changed, 119 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/platform/x86/thinkpad_acpi.c 
> b/drivers/platform/x86/thinkpad_acpi.c
> index 2242d6035d9e..91fab1a13a6d 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -310,8 +310,7 @@ static struct {
>   enum {
>   TP_HOTKEY_TABLET_NONE = 0,
>   TP_HOTKEY_TABLET_USES_MHKG,
> - /* X1 Yoga 2016, seen on BIOS N1FET44W */
> - TP_HOTKEY_TABLET_USES_CMMD,
> + TP_HOTKEY_TABLET_USES_GMMS,
>   } hotkey_tablet;
>   u32 kbdlight:1;
>   u32 light:1;
> @@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn);
>  
>  /* HKEY.MHKG() return bits */
>  #define TP_HOTKEY_TABLET_MASK (1 << 3)
> -/* ThinkPad X1 Yoga (2016) */
> -#define TP_EC_CMMD_TABLET_MODE 0x6
> +enum {
> + TP_ACPI_MULTI_MODE_INVALID  = 0,
> + TP_ACPI_MULTI_MODE_UNKNOWN  = 1 << 0,
> + TP_ACPI_MULTI_MODE_LAPTOP   = 1 << 1,
> + TP_ACPI_MULTI_MODE_TABLET   = 1 << 2,
> + TP_ACPI_MULTI_MODE_FLAT = 1 << 3,
> + TP_ACPI_MULTI_MODE_STAND= 1 << 4,
> + TP_ACPI_MULTI_MODE_TENT = 1 << 5,
> + TP_ACPI_MULTI_MODE_STAND_TENT   = 1 << 6,
> +};
> +
> +enum {
> + /* The following modes are considered tablet mode for the purpose of
> +  * reporting the status to userspace. i.e. in all these modes it makes
> +  * sense to disable the laptop input devices such as touchpad and
> +  * keyboard.
> +  */
> + TP_ACPI_MULTI_MODE_TABLET_LIKE  = TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT |
> +   TP_ACPI_MULTI_MODE_STAND_TENT,
> +};
>  
>  static int hotkey_get_wlsw(void)
>  {
> @@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void)
>   return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
>  }
>  
> +static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
> +{
> + int type = (s >> 16) & 0x;
> + int value = s & 0x;
> + int mode = TP_ACPI_MULTI_MODE_INVALID;
> + int valid_modes = 0;
> +
> + if (has_tablet_mode)
> + *has_tablet_mode = 0;
> +
> + switch (type) {
> + case 1:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND_TENT;
> + break;
> + case 2:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 3:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT;
> + break;
> + case 4:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 5:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + default:
> + pr_err("Unknown multi mode status type %d with value 0x%04X, 
> please report this to %s\n",
> +type, value, TPACPI_MAIL);
> + return 0;
> + }
> +
> + if (has_tablet_mode && (valid_modes & TP_ACPI_MULTI_MODE_TABLET_LIKE))
> +   

Re: [PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-09-16 Thread Henrique de Moraes Holschuh
On Fri, 15 Sep 2017, Benjamin Berg wrote:
> Many thinkpad laptops and convertibles provide the GMMS method to
> resolve how far the laptop has been opened and whether it has been
> converted into tablet mode. This allows reporting a more precise tablet
> mode state to userspace.
> 
> The current implementation only reports a summarized tablet mode state
> which is triggered as soon as the input devices become unusable as they
> are folded away from the display.
> 
> This will work on all models where the CMMD method was used previously and
> it may also work in other cases.
> 
> Thanks to Peter Zhang of Lenovo for providing information on how to use the
> GMMS method to query the tablet mode.
> 
> Signed-off-by: Benjamin Berg 
> Cc: Peter FP1 Zhang 
> Cc: Lyude Paul 

Looks good.

Acked-by: Henrique de Moraes Holschuh 

---
  PS: please send me the documentation for CMMD/GMMS off-list.

> ---
>  drivers/platform/x86/thinkpad_acpi.c | 132 
> +++
>  1 file changed, 119 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/platform/x86/thinkpad_acpi.c 
> b/drivers/platform/x86/thinkpad_acpi.c
> index 2242d6035d9e..91fab1a13a6d 100644
> --- a/drivers/platform/x86/thinkpad_acpi.c
> +++ b/drivers/platform/x86/thinkpad_acpi.c
> @@ -310,8 +310,7 @@ static struct {
>   enum {
>   TP_HOTKEY_TABLET_NONE = 0,
>   TP_HOTKEY_TABLET_USES_MHKG,
> - /* X1 Yoga 2016, seen on BIOS N1FET44W */
> - TP_HOTKEY_TABLET_USES_CMMD,
> + TP_HOTKEY_TABLET_USES_GMMS,
>   } hotkey_tablet;
>   u32 kbdlight:1;
>   u32 light:1;
> @@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn);
>  
>  /* HKEY.MHKG() return bits */
>  #define TP_HOTKEY_TABLET_MASK (1 << 3)
> -/* ThinkPad X1 Yoga (2016) */
> -#define TP_EC_CMMD_TABLET_MODE 0x6
> +enum {
> + TP_ACPI_MULTI_MODE_INVALID  = 0,
> + TP_ACPI_MULTI_MODE_UNKNOWN  = 1 << 0,
> + TP_ACPI_MULTI_MODE_LAPTOP   = 1 << 1,
> + TP_ACPI_MULTI_MODE_TABLET   = 1 << 2,
> + TP_ACPI_MULTI_MODE_FLAT = 1 << 3,
> + TP_ACPI_MULTI_MODE_STAND= 1 << 4,
> + TP_ACPI_MULTI_MODE_TENT = 1 << 5,
> + TP_ACPI_MULTI_MODE_STAND_TENT   = 1 << 6,
> +};
> +
> +enum {
> + /* The following modes are considered tablet mode for the purpose of
> +  * reporting the status to userspace. i.e. in all these modes it makes
> +  * sense to disable the laptop input devices such as touchpad and
> +  * keyboard.
> +  */
> + TP_ACPI_MULTI_MODE_TABLET_LIKE  = TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT |
> +   TP_ACPI_MULTI_MODE_STAND_TENT,
> +};
>  
>  static int hotkey_get_wlsw(void)
>  {
> @@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void)
>   return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
>  }
>  
> +static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
> +{
> + int type = (s >> 16) & 0x;
> + int value = s & 0x;
> + int mode = TP_ACPI_MULTI_MODE_INVALID;
> + int valid_modes = 0;
> +
> + if (has_tablet_mode)
> + *has_tablet_mode = 0;
> +
> + switch (type) {
> + case 1:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND_TENT;
> + break;
> + case 2:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 3:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT;
> + break;
> + case 4:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + case 5:
> + valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
> +   TP_ACPI_MULTI_MODE_FLAT |
> +   TP_ACPI_MULTI_MODE_TABLET |
> +   TP_ACPI_MULTI_MODE_STAND |
> +   TP_ACPI_MULTI_MODE_TENT;
> + break;
> + default:
> + pr_err("Unknown multi mode status type %d with value 0x%04X, 
> please report this to %s\n",
> +type, value, TPACPI_MAIL);
> + return 0;
> + }
> +
> + if (has_tablet_mode && (valid_modes & TP_ACPI_MULTI_MODE_TABLET_LIKE))
> + *has_tablet_mode = 1;
> +
> + switch (value) {
> + case 1:
> +  

[PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-09-15 Thread Benjamin Berg
Many thinkpad laptops and convertibles provide the GMMS method to
resolve how far the laptop has been opened and whether it has been
converted into tablet mode. This allows reporting a more precise tablet
mode state to userspace.

The current implementation only reports a summarized tablet mode state
which is triggered as soon as the input devices become unusable as they
are folded away from the display.

This will work on all models where the CMMD method was used previously and
it may also work in other cases.

Thanks to Peter Zhang of Lenovo for providing information on how to use the
GMMS method to query the tablet mode.

Signed-off-by: Benjamin Berg 
Cc: Peter FP1 Zhang 
Cc: Lyude Paul 
---
 drivers/platform/x86/thinkpad_acpi.c | 132 +++
 1 file changed, 119 insertions(+), 13 deletions(-)

diff --git a/drivers/platform/x86/thinkpad_acpi.c 
b/drivers/platform/x86/thinkpad_acpi.c
index 2242d6035d9e..91fab1a13a6d 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -310,8 +310,7 @@ static struct {
enum {
TP_HOTKEY_TABLET_NONE = 0,
TP_HOTKEY_TABLET_USES_MHKG,
-   /* X1 Yoga 2016, seen on BIOS N1FET44W */
-   TP_HOTKEY_TABLET_USES_CMMD,
+   TP_HOTKEY_TABLET_USES_GMMS,
} hotkey_tablet;
u32 kbdlight:1;
u32 light:1;
@@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn);
 
 /* HKEY.MHKG() return bits */
 #define TP_HOTKEY_TABLET_MASK (1 << 3)
-/* ThinkPad X1 Yoga (2016) */
-#define TP_EC_CMMD_TABLET_MODE 0x6
+enum {
+   TP_ACPI_MULTI_MODE_INVALID  = 0,
+   TP_ACPI_MULTI_MODE_UNKNOWN  = 1 << 0,
+   TP_ACPI_MULTI_MODE_LAPTOP   = 1 << 1,
+   TP_ACPI_MULTI_MODE_TABLET   = 1 << 2,
+   TP_ACPI_MULTI_MODE_FLAT = 1 << 3,
+   TP_ACPI_MULTI_MODE_STAND= 1 << 4,
+   TP_ACPI_MULTI_MODE_TENT = 1 << 5,
+   TP_ACPI_MULTI_MODE_STAND_TENT   = 1 << 6,
+};
+
+enum {
+   /* The following modes are considered tablet mode for the purpose of
+* reporting the status to userspace. i.e. in all these modes it makes
+* sense to disable the laptop input devices such as touchpad and
+* keyboard.
+*/
+   TP_ACPI_MULTI_MODE_TABLET_LIKE  = TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT |
+ TP_ACPI_MULTI_MODE_STAND_TENT,
+};
 
 static int hotkey_get_wlsw(void)
 {
@@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void)
return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
 }
 
+static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
+{
+   int type = (s >> 16) & 0x;
+   int value = s & 0x;
+   int mode = TP_ACPI_MULTI_MODE_INVALID;
+   int valid_modes = 0;
+
+   if (has_tablet_mode)
+   *has_tablet_mode = 0;
+
+   switch (type) {
+   case 1:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND_TENT;
+   break;
+   case 2:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_FLAT |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT;
+   break;
+   case 3:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_FLAT;
+   break;
+   case 4:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT;
+   break;
+   case 5:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_FLAT |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT;
+   break;
+   default:
+   pr_err("Unknown multi mode status type %d with value 0x%04X, 
please report this to %s\n",
+  type, value, TPACPI_MAIL);
+   return 0;
+   }
+
+   if (has_tablet_mode && (valid_modes & TP_ACPI_MULTI_MODE_TABLET_LIKE))
+   *has_tablet_mode = 1;
+
+   switch (value) {
+   case 1:
+   mode = TP_ACPI_MULTI_MODE_LAPTOP;
+   break;
+   case 2:
+   mode = TP_ACPI_MULTI_MODE_FLAT;
+   break;
+   case 3:
+   mode = 

[PATCH] thinkpad_acpi: Implement tablet mode resolving using GMMS method

2017-09-15 Thread Benjamin Berg
Many thinkpad laptops and convertibles provide the GMMS method to
resolve how far the laptop has been opened and whether it has been
converted into tablet mode. This allows reporting a more precise tablet
mode state to userspace.

The current implementation only reports a summarized tablet mode state
which is triggered as soon as the input devices become unusable as they
are folded away from the display.

This will work on all models where the CMMD method was used previously and
it may also work in other cases.

Thanks to Peter Zhang of Lenovo for providing information on how to use the
GMMS method to query the tablet mode.

Signed-off-by: Benjamin Berg 
Cc: Peter FP1 Zhang 
Cc: Lyude Paul 
---
 drivers/platform/x86/thinkpad_acpi.c | 132 +++
 1 file changed, 119 insertions(+), 13 deletions(-)

diff --git a/drivers/platform/x86/thinkpad_acpi.c 
b/drivers/platform/x86/thinkpad_acpi.c
index 2242d6035d9e..91fab1a13a6d 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -310,8 +310,7 @@ static struct {
enum {
TP_HOTKEY_TABLET_NONE = 0,
TP_HOTKEY_TABLET_USES_MHKG,
-   /* X1 Yoga 2016, seen on BIOS N1FET44W */
-   TP_HOTKEY_TABLET_USES_CMMD,
+   TP_HOTKEY_TABLET_USES_GMMS,
} hotkey_tablet;
u32 kbdlight:1;
u32 light:1;
@@ -2044,8 +2043,28 @@ static void hotkey_poll_setup(const bool may_warn);
 
 /* HKEY.MHKG() return bits */
 #define TP_HOTKEY_TABLET_MASK (1 << 3)
-/* ThinkPad X1 Yoga (2016) */
-#define TP_EC_CMMD_TABLET_MODE 0x6
+enum {
+   TP_ACPI_MULTI_MODE_INVALID  = 0,
+   TP_ACPI_MULTI_MODE_UNKNOWN  = 1 << 0,
+   TP_ACPI_MULTI_MODE_LAPTOP   = 1 << 1,
+   TP_ACPI_MULTI_MODE_TABLET   = 1 << 2,
+   TP_ACPI_MULTI_MODE_FLAT = 1 << 3,
+   TP_ACPI_MULTI_MODE_STAND= 1 << 4,
+   TP_ACPI_MULTI_MODE_TENT = 1 << 5,
+   TP_ACPI_MULTI_MODE_STAND_TENT   = 1 << 6,
+};
+
+enum {
+   /* The following modes are considered tablet mode for the purpose of
+* reporting the status to userspace. i.e. in all these modes it makes
+* sense to disable the laptop input devices such as touchpad and
+* keyboard.
+*/
+   TP_ACPI_MULTI_MODE_TABLET_LIKE  = TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT |
+ TP_ACPI_MULTI_MODE_STAND_TENT,
+};
 
 static int hotkey_get_wlsw(void)
 {
@@ -2066,6 +2085,90 @@ static int hotkey_get_wlsw(void)
return (status) ? TPACPI_RFK_RADIO_ON : TPACPI_RFK_RADIO_OFF;
 }
 
+static int hotkey_gmms_get_tablet_mode(int s, int *has_tablet_mode)
+{
+   int type = (s >> 16) & 0x;
+   int value = s & 0x;
+   int mode = TP_ACPI_MULTI_MODE_INVALID;
+   int valid_modes = 0;
+
+   if (has_tablet_mode)
+   *has_tablet_mode = 0;
+
+   switch (type) {
+   case 1:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND_TENT;
+   break;
+   case 2:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_FLAT |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT;
+   break;
+   case 3:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_FLAT;
+   break;
+   case 4:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT;
+   break;
+   case 5:
+   valid_modes = TP_ACPI_MULTI_MODE_LAPTOP |
+ TP_ACPI_MULTI_MODE_FLAT |
+ TP_ACPI_MULTI_MODE_TABLET |
+ TP_ACPI_MULTI_MODE_STAND |
+ TP_ACPI_MULTI_MODE_TENT;
+   break;
+   default:
+   pr_err("Unknown multi mode status type %d with value 0x%04X, 
please report this to %s\n",
+  type, value, TPACPI_MAIL);
+   return 0;
+   }
+
+   if (has_tablet_mode && (valid_modes & TP_ACPI_MULTI_MODE_TABLET_LIKE))
+   *has_tablet_mode = 1;
+
+   switch (value) {
+   case 1:
+   mode = TP_ACPI_MULTI_MODE_LAPTOP;
+   break;
+   case 2:
+   mode = TP_ACPI_MULTI_MODE_FLAT;
+   break;
+   case 3:
+   mode = TP_ACPI_MULTI_MODE_TABLET;
+   break;
+   case 4:
+