linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support
@ 2019-04-18  6:46 Chris Chiu
  2019-04-19  8:52 ` Daniel Drake
  2019-04-24  0:54 ` Chris Chiu
  0 siblings, 2 replies; 4+ messages in thread
From: Chris Chiu @ 2019-04-18  6:46 UTC (permalink / raw)
  To: andriy.shevchenko, corentin.chary, dvhart
  Cc: acpi4asus-user, platform-driver-x86, linux-kernel, linux, Chris Chiu

Some of latest ASUS laptops support new fn-lock mode switching.
This commit detect whether if the fn-lock option is enabled in
BIOS setting, and toggle the fn-lock mode via a new WMI DEVID
0x00100023 when the corresponding notify code captured.

The ASUS fn-lock mode switch is activated by pressing Fn+Esc.
When on, keys F1 to F12 behave as applicable, with meanings
defined by the application being used at the time. When off,
F1 to F12 directly triggers hardware features, well known audio
volume up/down, brightness up/down...etc, which were triggered
by holding down Fn key and F-keys.

Because there's no way to retrieve the fn-lock mode via existing
WMI methods per ASUS spec, driver need to initialize and keep the
fn-lock mode by itself.

Signed-off-by: Chris Chiu <chiu@endlessm.com>
---
 drivers/platform/x86/asus-wmi.c            | 36 ++++++++++++++++++++++++++++++
 include/linux/platform_data/x86/asus-wmi.h |  1 +
 2 files changed, 37 insertions(+)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 37b5de541270..5f52b66e40cb 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -69,6 +69,7 @@ MODULE_LICENSE("GPL");
 #define NOTIFY_KBD_BRTUP		0xc4
 #define NOTIFY_KBD_BRTDWN		0xc5
 #define NOTIFY_KBD_BRTTOGGLE		0xc7
+#define NOTIFY_FNLOCK_TOGGLE		0x4e
 
 #define ASUS_FAN_DESC			"cpu_fan"
 #define ASUS_FAN_MFUN			0x13
@@ -177,6 +178,8 @@ struct asus_wmi {
 	struct workqueue_struct *hotplug_workqueue;
 	struct work_struct hotplug_work;
 
+	bool fnlock_locked;
+
 	struct asus_wmi_debug debug;
 
 	struct asus_wmi_driver *driver;
@@ -1619,6 +1622,24 @@ static int is_display_toggle(int code)
 	return 0;
 }
 
+static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)
+{
+#define ASUS_WMI_FNLOCK_BIOS_DISABLED	BIT(0)
+	u32 result;
+
+	asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FNLOCK, &result);
+
+	return (result & ASUS_WMI_DSTS_PRESENCE_BIT) &&
+		!(result & ASUS_WMI_FNLOCK_BIOS_DISABLED);
+}
+
+static void asus_wmi_fnlock_update(struct asus_wmi *asus)
+{
+	int mode = asus->fnlock_locked;
+
+	asus_wmi_set_devstate(ASUS_WMI_DEVID_FNLOCK, mode, NULL);
+}
+
 static void asus_wmi_notify(u32 value, void *context)
 {
 	struct asus_wmi *asus = context;
@@ -1680,6 +1701,12 @@ static void asus_wmi_notify(u32 value, void *context)
 		goto exit;
 	}
 
+	if (code == NOTIFY_FNLOCK_TOGGLE) {
+		asus->fnlock_locked = !asus->fnlock_locked;
+		asus_wmi_fnlock_update(asus);
+		goto exit;
+	}
+
 	if (is_display_toggle(code) &&
 	    asus->driver->quirks->no_display_toggle)
 		goto exit;
@@ -2134,6 +2161,11 @@ static int asus_wmi_add(struct platform_device *pdev)
 	} else
 		err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
 
+	if (asus_wmi_has_fnlock_key(asus)) {
+		asus->fnlock_locked = true;
+		asus_wmi_fnlock_update(asus);
+	}
+
 	status = wmi_install_notify_handler(asus->driver->event_guid,
 					    asus_wmi_notify, asus);
 	if (ACPI_FAILURE(status)) {
@@ -2213,6 +2245,8 @@ static int asus_hotk_resume(struct device *device)
 	if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
 		kbd_led_update(asus);
 
+	if (asus_wmi_has_fnlock_key(asus))
+		asus_wmi_fnlock_update(asus);
 	return 0;
 }
 
@@ -2249,6 +2283,8 @@ static int asus_hotk_restore(struct device *device)
 	if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
 		kbd_led_update(asus);
 
+	if (asus_wmi_has_fnlock_key(asus))
+		asus_wmi_fnlock_update(asus);
 	return 0;
 }
 
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
index 53dfc2541960..bfba245636a7 100644
--- a/include/linux/platform_data/x86/asus-wmi.h
+++ b/include/linux/platform_data/x86/asus-wmi.h
@@ -67,6 +67,7 @@
 /* Input */
 #define ASUS_WMI_DEVID_TOUCHPAD		0x00100011
 #define ASUS_WMI_DEVID_TOUCHPAD_LED	0x00100012
+#define ASUS_WMI_DEVID_FNLOCK		0x00100023
 
 /* Fan, Thermal */
 #define ASUS_WMI_DEVID_THERMAL_CTRL	0x00110011
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support
  2019-04-18  6:46 [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support Chris Chiu
@ 2019-04-19  8:52 ` Daniel Drake
  2019-04-24  0:54 ` Chris Chiu
  1 sibling, 0 replies; 4+ messages in thread
From: Daniel Drake @ 2019-04-19  8:52 UTC (permalink / raw)
  To: Chris Chiu
  Cc: Andy Shevchenko, Corentin Chary, Darren Hart, acpi4asus-user,
	Platform Driver, Linux Kernel, Linux Upstreaming Team

On Thu, Apr 18, 2019 at 2:47 PM Chris Chiu <chiu@endlessm.com> wrote:
>
> Some of latest ASUS laptops support new fn-lock mode switching.
> This commit detect whether if the fn-lock option is enabled in
> BIOS setting, and toggle the fn-lock mode via a new WMI DEVID
> 0x00100023 when the corresponding notify code captured.
>
> The ASUS fn-lock mode switch is activated by pressing Fn+Esc.
> When on, keys F1 to F12 behave as applicable, with meanings
> defined by the application being used at the time. When off,
> F1 to F12 directly triggers hardware features, well known audio
> volume up/down, brightness up/down...etc, which were triggered
> by holding down Fn key and F-keys.
>
> Because there's no way to retrieve the fn-lock mode via existing
> WMI methods per ASUS spec, driver need to initialize and keep the
> fn-lock mode by itself.
>
> Signed-off-by: Chris Chiu <chiu@endlessm.com>

Reviewed-by: Daniel Drake <drake@endlessm.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support
  2019-04-18  6:46 [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support Chris Chiu
  2019-04-19  8:52 ` Daniel Drake
@ 2019-04-24  0:54 ` Chris Chiu
  2019-05-06  9:26   ` Andy Shevchenko
  1 sibling, 1 reply; 4+ messages in thread
From: Chris Chiu @ 2019-04-24  0:54 UTC (permalink / raw)
  To: Andy Shevchenko, Corentin Chary, Darren Hart
  Cc: acpi4asus-user, Platform Driver, Linux Kernel, Linux Upstreaming Team

On Thu, Apr 18, 2019 at 2:46 PM Chris Chiu <chiu@endlessm.com> wrote:
>
> Some of latest ASUS laptops support new fn-lock mode switching.
> This commit detect whether if the fn-lock option is enabled in
> BIOS setting, and toggle the fn-lock mode via a new WMI DEVID
> 0x00100023 when the corresponding notify code captured.
>
> The ASUS fn-lock mode switch is activated by pressing Fn+Esc.
> When on, keys F1 to F12 behave as applicable, with meanings
> defined by the application being used at the time. When off,
> F1 to F12 directly triggers hardware features, well known audio
> volume up/down, brightness up/down...etc, which were triggered
> by holding down Fn key and F-keys.
>
> Because there's no way to retrieve the fn-lock mode via existing
> WMI methods per ASUS spec, driver need to initialize and keep the
> fn-lock mode by itself.
>
> Signed-off-by: Chris Chiu <chiu@endlessm.com>
> ---
>  drivers/platform/x86/asus-wmi.c            | 36 ++++++++++++++++++++++++++++++
>  include/linux/platform_data/x86/asus-wmi.h |  1 +
>  2 files changed, 37 insertions(+)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index 37b5de541270..5f52b66e40cb 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -69,6 +69,7 @@ MODULE_LICENSE("GPL");
>  #define NOTIFY_KBD_BRTUP               0xc4
>  #define NOTIFY_KBD_BRTDWN              0xc5
>  #define NOTIFY_KBD_BRTTOGGLE           0xc7
> +#define NOTIFY_FNLOCK_TOGGLE           0x4e
>
>  #define ASUS_FAN_DESC                  "cpu_fan"
>  #define ASUS_FAN_MFUN                  0x13
> @@ -177,6 +178,8 @@ struct asus_wmi {
>         struct workqueue_struct *hotplug_workqueue;
>         struct work_struct hotplug_work;
>
> +       bool fnlock_locked;
> +
>         struct asus_wmi_debug debug;
>
>         struct asus_wmi_driver *driver;
> @@ -1619,6 +1622,24 @@ static int is_display_toggle(int code)
>         return 0;
>  }
>
> +static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)
> +{
> +#define ASUS_WMI_FNLOCK_BIOS_DISABLED  BIT(0)
> +       u32 result;
> +
> +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FNLOCK, &result);
> +
> +       return (result & ASUS_WMI_DSTS_PRESENCE_BIT) &&
> +               !(result & ASUS_WMI_FNLOCK_BIOS_DISABLED);
> +}
> +
> +static void asus_wmi_fnlock_update(struct asus_wmi *asus)
> +{
> +       int mode = asus->fnlock_locked;
> +
> +       asus_wmi_set_devstate(ASUS_WMI_DEVID_FNLOCK, mode, NULL);
> +}
> +
>  static void asus_wmi_notify(u32 value, void *context)
>  {
>         struct asus_wmi *asus = context;
> @@ -1680,6 +1701,12 @@ static void asus_wmi_notify(u32 value, void *context)
>                 goto exit;
>         }
>
> +       if (code == NOTIFY_FNLOCK_TOGGLE) {
> +               asus->fnlock_locked = !asus->fnlock_locked;
> +               asus_wmi_fnlock_update(asus);
> +               goto exit;
> +       }
> +
>         if (is_display_toggle(code) &&
>             asus->driver->quirks->no_display_toggle)
>                 goto exit;
> @@ -2134,6 +2161,11 @@ static int asus_wmi_add(struct platform_device *pdev)
>         } else
>                 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
>
> +       if (asus_wmi_has_fnlock_key(asus)) {
> +               asus->fnlock_locked = true;
> +               asus_wmi_fnlock_update(asus);
> +       }
> +
>         status = wmi_install_notify_handler(asus->driver->event_guid,
>                                             asus_wmi_notify, asus);
>         if (ACPI_FAILURE(status)) {
> @@ -2213,6 +2245,8 @@ static int asus_hotk_resume(struct device *device)
>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>                 kbd_led_update(asus);
>
> +       if (asus_wmi_has_fnlock_key(asus))
> +               asus_wmi_fnlock_update(asus);
>         return 0;
>  }
>
> @@ -2249,6 +2283,8 @@ static int asus_hotk_restore(struct device *device)
>         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
>                 kbd_led_update(asus);
>
> +       if (asus_wmi_has_fnlock_key(asus))
> +               asus_wmi_fnlock_update(asus);
>         return 0;
>  }
>
> diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
> index 53dfc2541960..bfba245636a7 100644
> --- a/include/linux/platform_data/x86/asus-wmi.h
> +++ b/include/linux/platform_data/x86/asus-wmi.h
> @@ -67,6 +67,7 @@
>  /* Input */
>  #define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
>  #define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
> +#define ASUS_WMI_DEVID_FNLOCK          0x00100023
>
>  /* Fan, Thermal */
>  #define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
> --
> 2.11.0
>

Gentle ping. Any comments or suggestions for this are appreciated.

Chris

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support
  2019-04-24  0:54 ` Chris Chiu
@ 2019-05-06  9:26   ` Andy Shevchenko
  0 siblings, 0 replies; 4+ messages in thread
From: Andy Shevchenko @ 2019-05-06  9:26 UTC (permalink / raw)
  To: Chris Chiu
  Cc: Andy Shevchenko, Corentin Chary, Darren Hart, acpi4asus-user,
	Platform Driver, Linux Kernel, Linux Upstreaming Team

On Wed, Apr 24, 2019 at 3:54 AM Chris Chiu <chiu@endlessm.com> wrote:
>
> On Thu, Apr 18, 2019 at 2:46 PM Chris Chiu <chiu@endlessm.com> wrote:
> >
> > Some of latest ASUS laptops support new fn-lock mode switching.
> > This commit detect whether if the fn-lock option is enabled in
> > BIOS setting, and toggle the fn-lock mode via a new WMI DEVID
> > 0x00100023 when the corresponding notify code captured.
> >
> > The ASUS fn-lock mode switch is activated by pressing Fn+Esc.
> > When on, keys F1 to F12 behave as applicable, with meanings
> > defined by the application being used at the time. When off,
> > F1 to F12 directly triggers hardware features, well known audio
> > volume up/down, brightness up/down...etc, which were triggered
> > by holding down Fn key and F-keys.
> >
> > Because there's no way to retrieve the fn-lock mode via existing
> > WMI methods per ASUS spec, driver need to initialize and keep the
> > fn-lock mode by itself.
> >

Pushed to my review and testing queue, thanks!


> > Signed-off-by: Chris Chiu <chiu@endlessm.com>
> > ---
> >  drivers/platform/x86/asus-wmi.c            | 36 ++++++++++++++++++++++++++++++
> >  include/linux/platform_data/x86/asus-wmi.h |  1 +
> >  2 files changed, 37 insertions(+)
> >
> > diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> > index 37b5de541270..5f52b66e40cb 100644
> > --- a/drivers/platform/x86/asus-wmi.c
> > +++ b/drivers/platform/x86/asus-wmi.c
> > @@ -69,6 +69,7 @@ MODULE_LICENSE("GPL");
> >  #define NOTIFY_KBD_BRTUP               0xc4
> >  #define NOTIFY_KBD_BRTDWN              0xc5
> >  #define NOTIFY_KBD_BRTTOGGLE           0xc7
> > +#define NOTIFY_FNLOCK_TOGGLE           0x4e
> >
> >  #define ASUS_FAN_DESC                  "cpu_fan"
> >  #define ASUS_FAN_MFUN                  0x13
> > @@ -177,6 +178,8 @@ struct asus_wmi {
> >         struct workqueue_struct *hotplug_workqueue;
> >         struct work_struct hotplug_work;
> >
> > +       bool fnlock_locked;
> > +
> >         struct asus_wmi_debug debug;
> >
> >         struct asus_wmi_driver *driver;
> > @@ -1619,6 +1622,24 @@ static int is_display_toggle(int code)
> >         return 0;
> >  }
> >
> > +static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)
> > +{
> > +#define ASUS_WMI_FNLOCK_BIOS_DISABLED  BIT(0)
> > +       u32 result;
> > +
> > +       asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FNLOCK, &result);
> > +
> > +       return (result & ASUS_WMI_DSTS_PRESENCE_BIT) &&
> > +               !(result & ASUS_WMI_FNLOCK_BIOS_DISABLED);
> > +}
> > +
> > +static void asus_wmi_fnlock_update(struct asus_wmi *asus)
> > +{
> > +       int mode = asus->fnlock_locked;
> > +
> > +       asus_wmi_set_devstate(ASUS_WMI_DEVID_FNLOCK, mode, NULL);
> > +}
> > +
> >  static void asus_wmi_notify(u32 value, void *context)
> >  {
> >         struct asus_wmi *asus = context;
> > @@ -1680,6 +1701,12 @@ static void asus_wmi_notify(u32 value, void *context)
> >                 goto exit;
> >         }
> >
> > +       if (code == NOTIFY_FNLOCK_TOGGLE) {
> > +               asus->fnlock_locked = !asus->fnlock_locked;
> > +               asus_wmi_fnlock_update(asus);
> > +               goto exit;
> > +       }
> > +
> >         if (is_display_toggle(code) &&
> >             asus->driver->quirks->no_display_toggle)
> >                 goto exit;
> > @@ -2134,6 +2161,11 @@ static int asus_wmi_add(struct platform_device *pdev)
> >         } else
> >                 err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
> >
> > +       if (asus_wmi_has_fnlock_key(asus)) {
> > +               asus->fnlock_locked = true;
> > +               asus_wmi_fnlock_update(asus);
> > +       }
> > +
> >         status = wmi_install_notify_handler(asus->driver->event_guid,
> >                                             asus_wmi_notify, asus);
> >         if (ACPI_FAILURE(status)) {
> > @@ -2213,6 +2245,8 @@ static int asus_hotk_resume(struct device *device)
> >         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
> >                 kbd_led_update(asus);
> >
> > +       if (asus_wmi_has_fnlock_key(asus))
> > +               asus_wmi_fnlock_update(asus);
> >         return 0;
> >  }
> >
> > @@ -2249,6 +2283,8 @@ static int asus_hotk_restore(struct device *device)
> >         if (!IS_ERR_OR_NULL(asus->kbd_led.dev))
> >                 kbd_led_update(asus);
> >
> > +       if (asus_wmi_has_fnlock_key(asus))
> > +               asus_wmi_fnlock_update(asus);
> >         return 0;
> >  }
> >
> > diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
> > index 53dfc2541960..bfba245636a7 100644
> > --- a/include/linux/platform_data/x86/asus-wmi.h
> > +++ b/include/linux/platform_data/x86/asus-wmi.h
> > @@ -67,6 +67,7 @@
> >  /* Input */
> >  #define ASUS_WMI_DEVID_TOUCHPAD                0x00100011
> >  #define ASUS_WMI_DEVID_TOUCHPAD_LED    0x00100012
> > +#define ASUS_WMI_DEVID_FNLOCK          0x00100023
> >
> >  /* Fan, Thermal */
> >  #define ASUS_WMI_DEVID_THERMAL_CTRL    0x00110011
> > --
> > 2.11.0
> >
>
> Gentle ping. Any comments or suggestions for this are appreciated.
>
> Chris



-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-05-06  9:26 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-18  6:46 [PATCH] platform/x86: asus-wmi: Add fn-lock mode switch support Chris Chiu
2019-04-19  8:52 ` Daniel Drake
2019-04-24  0:54 ` Chris Chiu
2019-05-06  9:26   ` Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).