X86 platform drivers
 help / color / mirror / Atom feed
* [PATCH v3 0/3] platform/x86: asus-wmi: fix FA401 series keyboard sleep strobe
@ 2026-09-02 17:47 Idotoho Reimon Simanjuntak
  2026-09-02 17:47 ` [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands Idotoho Reimon Simanjuntak
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Idotoho Reimon Simanjuntak @ 2026-09-02 17:47 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: linux-kernel, Hans de Goede, Ilpo Järvinen, Denis Benato,
	Luke D . Jones, Corentin Chary, Idotoho Reimon Simanjuntak

This series fixes the keyboard sleep strobe effect on ASUS TUF Gaming
FA401 (A14) series laptops and refactors the TUF RGB state/mode
interface.

The FA401 does not report the TUF RGB state WMI device (0x00100057) via
standard DSTS probing, yet the EC supports the state flags required for
the sleep strobe animation. In addition, Modern Standby (S0ix/s2idle)
entry requires re-asserting the keyboard backlight and power state at
LPS0 prepare time because display servers and DRM drivers blank the
backlight to 0 prior to sleep.

Changes in v3:
- Split the series into 3 patches: preparatory bitmask cleanup, FA401
  DMI quirk, and S0ix sleep re-assertion (per Ilpo Järvinen).
- Use FIELD_PREP() and named GENMASK() definitions consistently
  (per Ilpo Järvinen).
- Address Denis Benato's feedback regarding userspace policy:
  * Check the TUF_RGB_STATE_SLEEP flag so the kernel honors any user
    decision to disable sleep LEDs.
  * Dynamically track the user's active brightness level
    (kbd_led_last_level) so the sleep strobe preserves dim/bright
    preferences rather than forcing max brightness.
- Hook into ACPI LPS0 s2idle dev ops (.prepare): ensures brightness and
  state are re-asserted after the display server and DRM drivers blank
  the screen, immediately prior to S0ix entry.
Link: https://lore.kernel.org/platform-driver-x86/20260902032353.16106-1-idotohors@gmail.com/ # v2

Idotoho Reimon Simanjuntak (3):
  platform/x86: asus-wmi: use named masks for TUF RGB commands
  platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk
  platform/x86: asus-wmi: re-assert FA401 keyboard state before S0ix

 drivers/platform/x86/asus-nb-wmi.c |  13 ++++
 drivers/platform/x86/asus-wmi.c    | 120 +++++++++++++++++++++++++----
 drivers/platform/x86/asus-wmi.h    |   1 +
 3 files changed, 118 insertions(+), 16 deletions(-)

-- 
2.55.0


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

* [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands
  2026-09-02 17:47 [PATCH v3 0/3] platform/x86: asus-wmi: fix FA401 series keyboard sleep strobe Idotoho Reimon Simanjuntak
@ 2026-09-02 17:47 ` Idotoho Reimon Simanjuntak
  2026-09-02 18:44   ` Denis Benato
  2026-09-02 17:47 ` [PATCH v3 2/3] platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk Idotoho Reimon Simanjuntak
  2026-09-02 17:47 ` [PATCH v3 3/3] platform/x86: asus-wmi: re-assert FA401 keyboard state before S0ix Idotoho Reimon Simanjuntak
  2 siblings, 1 reply; 6+ messages in thread
From: Idotoho Reimon Simanjuntak @ 2026-09-02 17:47 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: linux-kernel, Hans de Goede, Ilpo Järvinen, Denis Benato,
	Luke D . Jones, Corentin Chary, Idotoho Reimon Simanjuntak

Replace open-coded bit shifts and magic numbers in kbd_rgb_mode_store()
and kbd_rgb_state_store() with FIELD_PREP() and named GENMASK() masks.

Define ASUS_WMI_TUF_RGB_STATE_CMD_ID (0xbd) as a named constant instead
of an inline literal, making the required arg0 command ID self-documenting.

In kbd_rgb_state_store(), remove the unused intermediate "flags" variable
entirely. The old BIT(1)/BIT(3)/BIT(5)/BIT(7) construction is replaced by
FIELD_PREP with per-flag named masks (TUF_RGB_STATE_BOOT, _AWAKE, _SLEEP,
_KEYBOARD), building arg0 directly. This preserves the exact sysfs input
format ("cmd boot awake sleep keyboard") and the resulting WMI argument
bit layout — no behavioral change.

In kbd_rgb_mode_store(), replace the positional shift expressions for
arg1 and arg2 with FIELD_PREP using TUF_RGB_MODE_{CMD,MODE,RED,GREEN}
and TUF_RGB_MODE_{BLUE,SPEED} masks respectively.

This is a preparatory cleanup to improve readability before adding
model-specific quirks that depend on these definitions.

Signed-off-by: Idotoho Reimon Simanjuntak <idotohors@gmail.com>
---
 drivers/platform/x86/asus-wmi.c | 48 ++++++++++++++++++++++++++-------
 1 file changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index a65090429..efc730c2c 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -15,6 +15,7 @@
 
 #include <linux/acpi.h>
 #include <linux/backlight.h>
+#include <linux/bitfield.h>
 #include <linux/bits.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
@@ -1047,6 +1048,27 @@ static DEVICE_ATTR_RW(gpu_mux_mode);
 #endif /* IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS) */
 
 /* TUF Laptop Keyboard RGB Modes **********************************************/
+
+/* Command IDs passed in arg0 byte 0 for TUF RGB WMI methods */
+#define ASUS_WMI_TUF_RGB_STATE_CMD_ID	0xbd
+
+/* Bit mask for the save-to-BIOS command flag in kbd_rgb_state_store (arg0 bit 10) */
+#define TUF_RGB_STATE_SAVE	GENMASK(10, 10)
+
+/* Bit masks for kbd_rgb_state_store flags field (arg0 bits [23:16]) */
+#define TUF_RGB_STATE_BOOT	GENMASK(17, 17)
+#define TUF_RGB_STATE_AWAKE	GENMASK(19, 19)
+#define TUF_RGB_STATE_SLEEP	GENMASK(21, 21)
+#define TUF_RGB_STATE_KEYBOARD	GENMASK(23, 23)
+
+/* Bit masks for kbd_rgb_mode_store fields */
+#define TUF_RGB_MODE_CMD	GENMASK(7, 0)
+#define TUF_RGB_MODE_MODE	GENMASK(15, 8)
+#define TUF_RGB_MODE_RED	GENMASK(23, 16)
+#define TUF_RGB_MODE_GREEN	GENMASK(31, 24)
+#define TUF_RGB_MODE_BLUE	GENMASK(7, 0)
+#define TUF_RGB_MODE_SPEED	GENMASK(15, 8)
+
 static ssize_t kbd_rgb_mode_store(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count)
@@ -1093,7 +1115,12 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
 	}
 
 	err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, asus->kbd_rgb_dev,
-			cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL);
+			FIELD_PREP(TUF_RGB_MODE_CMD, cmd) |
+			FIELD_PREP(TUF_RGB_MODE_MODE, mode) |
+			FIELD_PREP(TUF_RGB_MODE_RED, r) |
+			FIELD_PREP(TUF_RGB_MODE_GREEN, g),
+			FIELD_PREP(TUF_RGB_MODE_BLUE, b) |
+			FIELD_PREP(TUF_RGB_MODE_SPEED, speed), NULL);
 	if (err)
 		return err;
 
@@ -1119,28 +1146,29 @@ static ssize_t kbd_rgb_state_store(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count)
 {
-	u32 flags, cmd, boot, awake, sleep, keyboard;
+	u32 cmd, boot, awake, sleep, keyboard;
+	u32 arg0;
 	int err;
 
 	if (sscanf(buf, "%d %d %d %d %d", &cmd, &boot, &awake, &sleep, &keyboard) != 5)
 		return -EINVAL;
 
+	arg0 = ASUS_WMI_TUF_RGB_STATE_CMD_ID;
+
 	if (cmd)
-		cmd = BIT(2);
+		arg0 |= FIELD_PREP(TUF_RGB_STATE_SAVE, 1);
 
-	flags = 0;
 	if (boot)
-		flags |= BIT(1);
+		arg0 |= FIELD_PREP(TUF_RGB_STATE_BOOT, 1);
 	if (awake)
-		flags |= BIT(3);
+		arg0 |= FIELD_PREP(TUF_RGB_STATE_AWAKE, 1);
 	if (sleep)
-		flags |= BIT(5);
+		arg0 |= FIELD_PREP(TUF_RGB_STATE_SLEEP, 1);
 	if (keyboard)
-		flags |= BIT(7);
+		arg0 |= FIELD_PREP(TUF_RGB_STATE_KEYBOARD, 1);
 
-	/* 0xbd is the required default arg0 for the method. Nothing happens otherwise */
 	err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS,
-			ASUS_WMI_DEVID_TUF_RGB_STATE, 0xbd | cmd << 8 | (flags << 16), 0, NULL);
+			ASUS_WMI_DEVID_TUF_RGB_STATE, arg0, 0, NULL);
 	if (err)
 		return err;
 
-- 
2.55.0


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

* [PATCH v3 2/3] platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk
  2026-09-02 17:47 [PATCH v3 0/3] platform/x86: asus-wmi: fix FA401 series keyboard sleep strobe Idotoho Reimon Simanjuntak
  2026-09-02 17:47 ` [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands Idotoho Reimon Simanjuntak
@ 2026-09-02 17:47 ` Idotoho Reimon Simanjuntak
  2026-09-02 18:40   ` Denis Benato
  2026-09-02 17:47 ` [PATCH v3 3/3] platform/x86: asus-wmi: re-assert FA401 keyboard state before S0ix Idotoho Reimon Simanjuntak
  2 siblings, 1 reply; 6+ messages in thread
From: Idotoho Reimon Simanjuntak @ 2026-09-02 17:47 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: linux-kernel, Hans de Goede, Ilpo Järvinen, Denis Benato,
	Luke D . Jones, Corentin Chary, Idotoho Reimon Simanjuntak

The FA401 (TUF Gaming A14) series does not expose the TUF RGB state
WMI device (0x00100057) through the standard DSTS probe, yet the EC
does support the keyboard backlight power-state flags needed for sleep
strobe functionality.

Add a DMI-based quirk in asus-nb-wmi.c that matches on DMI_SYS_VENDOR
"ASUSTeK COMPUTER INC." and DMI_BOARD_NAME "FA401", setting
kbd_rgb_state_available = true in struct quirk_entry.

In asus_wmi_add(), change the kbd_rgb_state_available assignment to
also consider driver->quirks->kbd_rgb_state_available, so models with
this quirk get the RGB state sysfs attributes even when DSTS probing
fails.

No PM/sleep/backlight changes are included in this commit; those will
be addressed separately once the RGB state interface is available.

Signed-off-by: Idotoho Reimon Simanjuntak <idotohors@gmail.com>
---
 drivers/platform/x86/asus-nb-wmi.c | 13 +++++++++++++
 drivers/platform/x86/asus-wmi.c    |  4 +++-
 drivers/platform/x86/asus-wmi.h    |  1 +
 3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index aeb461b16..47ceb6e46 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -155,6 +155,10 @@ static struct quirk_entry quirk_asus_z13 = {
 	.tablet_switch_mode = asus_wmi_kbd_dock_devid,
 };
 
+static struct quirk_entry quirk_asus_fa401 = {
+	.kbd_rgb_state_available = true,
+};
+
 static int dmi_matched(const struct dmi_system_id *dmi)
 {
 	pr_info("Identified laptop model '%s'\n", dmi->ident);
@@ -562,6 +566,15 @@ static const struct dmi_system_id asus_quirks[] = {
 		},
 		.driver_data = &quirk_asus_z13,
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. FA401",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "FA401"),
+		},
+		.driver_data = &quirk_asus_fa401,
+	},
 	{},
 };
 
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index efc730c2c..e7b2402c9 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -5181,7 +5181,9 @@ static int asus_wmi_add(struct platform_device *pdev)
 
 	asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);
 	asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);
-	asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);
+	asus->kbd_rgb_state_available =
+		asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE) ||
+		asus->driver->quirks->kbd_rgb_state_available;
 
 	if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE))
 		asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
index 5cd4392b9..9bc0b6145 100644
--- a/drivers/platform/x86/asus-wmi.h
+++ b/drivers/platform/x86/asus-wmi.h
@@ -52,6 +52,7 @@ struct quirk_entry {
 	 */
 	int no_display_toggle;
 	u32 xusb2pr;
+	bool kbd_rgb_state_available;
 };
 
 struct asus_wmi_driver {
-- 
2.55.0


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

* [PATCH v3 3/3] platform/x86: asus-wmi: re-assert FA401 keyboard state before S0ix
  2026-09-02 17:47 [PATCH v3 0/3] platform/x86: asus-wmi: fix FA401 series keyboard sleep strobe Idotoho Reimon Simanjuntak
  2026-09-02 17:47 ` [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands Idotoho Reimon Simanjuntak
  2026-09-02 17:47 ` [PATCH v3 2/3] platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk Idotoho Reimon Simanjuntak
@ 2026-09-02 17:47 ` Idotoho Reimon Simanjuntak
  2 siblings, 0 replies; 6+ messages in thread
From: Idotoho Reimon Simanjuntak @ 2026-09-02 17:47 UTC (permalink / raw)
  To: platform-driver-x86
  Cc: linux-kernel, Hans de Goede, Ilpo Järvinen, Denis Benato,
	Luke D . Jones, Corentin Chary, Idotoho Reimon Simanjuntak

On ASUS TUF Gaming FA401 laptops, the display server or graphics driver
blanks the keyboard backlight (brightness=0) during suspend. When the EC
enters S0ix with brightness=0, it disables the sleep-strobe effect.

Track the last user-configured non-zero keyboard backlight level in
asus->kbd_led_last_level, and re-assert it with the light-on bit (0x80)
along with the configured TUF RGB power state in both .prepare and the
LPS0 s2idle .prepare hook. Hooking LPS0 ensures the re-assertion happens
after all devices (including DRM and display managers) have suspended,
immediately prior to low-power S0 idle entry.

Only re-assert if the TUF sleep flag is active in kbd_rgb_state_flags,
respecting any user decision to disable sleep LEDs. Initialize default
flags at probe so the strobe functions out of the box.

Signed-off-by: Idotoho Reimon Simanjuntak <idotohors@gmail.com>
---
 drivers/platform/x86/asus-wmi.c | 68 ++++++++++++++++++++++++++++++---
 1 file changed, 63 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index e7b2402c9..03d2af604 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -257,6 +257,7 @@ struct asus_wmi {
 	int tpd_led_wk;
 	struct led_classdev kbd_led;
 	int kbd_led_wk;
+	int kbd_led_last_level;
 	bool kbd_led_notify;
 	bool kbd_led_avail;
 	bool kbd_led_registered;
@@ -310,6 +311,7 @@ struct asus_wmi {
 
 	u32 kbd_rgb_dev;
 	bool kbd_rgb_state_available;
+	u32 kbd_rgb_state_flags;
 	bool oobe_state_available;
 
 	u8 throttle_thermal_policy_mode;
@@ -344,6 +346,7 @@ struct asus_wmi {
 
 /* Global to allow setting externally without requiring driver data */
 static enum asus_ally_mcu_hack use_ally_mcu_hack = ASUS_WMI_ALLY_MCU_HACK_INIT;
+static struct asus_wmi *asus_hotk;
 
 #if IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS)
 static void asus_wmi_show_deprecated(void)
@@ -1146,6 +1149,8 @@ static ssize_t kbd_rgb_state_store(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count)
 {
+	struct led_classdev *led = dev_get_drvdata(dev);
+	struct asus_wmi *asus = container_of(led, struct asus_wmi, kbd_led);
 	u32 cmd, boot, awake, sleep, keyboard;
 	u32 arg0;
 	int err;
@@ -1172,6 +1177,8 @@ static ssize_t kbd_rgb_state_store(struct device *dev,
 	if (err)
 		return err;
 
+	asus->kbd_rgb_state_flags = arg0;
+
 	return count;
 }
 static DEVICE_ATTR_WO(kbd_rgb_state);
@@ -1944,8 +1951,11 @@ static void do_kbd_led_set(struct led_classdev *led_cdev, int value)
 
 	asus = container_of(led_cdev, struct asus_wmi, kbd_led);
 
-	scoped_guard(spinlock_irqsave, &asus_ref.lock)
+	scoped_guard(spinlock_irqsave, &asus_ref.lock) {
 		asus->kbd_led_wk = clamp_val(value, 0, ASUS_EV_MAX_BRIGHTNESS);
+		if (asus->kbd_led_wk > 0)
+			asus->kbd_led_last_level = asus->kbd_led_wk;
+	}
 
 	if (asus->kbd_led_avail)
 		kbd_led_update(asus);
@@ -2155,6 +2165,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus)
 
 	if (asus->kbd_led_avail) {
 		asus->kbd_led_wk = led_val;
+		asus->kbd_led_last_level = led_val > 0 ? led_val : ASUS_EV_MAX_BRIGHTNESS;
 		if (num_rgb_groups != 0)
 			asus->kbd_led.groups = kbd_rgb_mode_groups;
 	} else {
@@ -5146,6 +5157,7 @@ static int asus_wmi_add(struct platform_device *pdev)
 	asus->platform_device = pdev;
 	wdrv->platform_device = pdev;
 	platform_set_drvdata(asus->platform_device, asus);
+	asus_hotk = asus;
 
 	if (wdrv->detect_quirks)
 		wdrv->detect_quirks(asus->driver);
@@ -5184,6 +5196,14 @@ static int asus_wmi_add(struct platform_device *pdev)
 	asus->kbd_rgb_state_available =
 		asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE) ||
 		asus->driver->quirks->kbd_rgb_state_available;
+	if (asus->kbd_rgb_state_available) {
+		asus->kbd_rgb_state_flags =
+			ASUS_WMI_TUF_RGB_STATE_CMD_ID |
+			FIELD_PREP(TUF_RGB_STATE_BOOT, 1) |
+			FIELD_PREP(TUF_RGB_STATE_AWAKE, 1) |
+			FIELD_PREP(TUF_RGB_STATE_SLEEP, 1) |
+			FIELD_PREP(TUF_RGB_STATE_KEYBOARD, 1);
+	}
 
 	if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE))
 		asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
@@ -5324,6 +5344,7 @@ static void asus_wmi_remove(struct platform_device *device)
 	struct asus_wmi *asus;
 
 	asus = platform_get_drvdata(device);
+	asus_hotk = NULL;
 	if (asus->driver->i8042_filter)
 		i8042_remove_filter(asus->driver->i8042_filter);
 	wmi_remove_notify_handler(asus->driver->event_guid);
@@ -5424,17 +5445,54 @@ static int asus_hotk_restore(struct device *device)
 	return 0;
 }
 
+static void asus_tuf_reassert_sleep_rgb_state(struct asus_wmi *asus)
+{
+	if (asus && asus->driver->quirks->kbd_rgb_state_available &&
+	    asus->kbd_rgb_state_available &&
+	    (asus->kbd_rgb_state_flags & TUF_RGB_STATE_SLEEP)) {
+		int level;
+		u32 arg0;
+
+		/*
+		 * Re-assert keyboard backlight using the last user-configured
+		 * brightness level (falling back to max brightness) with the
+		 * light-on bit (0x80) set.
+		 */
+		level = asus->kbd_led_last_level ?
+			asus->kbd_led_last_level : ASUS_EV_MAX_BRIGHTNESS;
+		asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT,
+				      0x80 | (level & 0x7f), NULL);
+
+		/* Re-assert the last user-configured TUF RGB power state */
+		arg0 = asus->kbd_rgb_state_flags |
+		       FIELD_PREP(TUF_RGB_STATE_SAVE, 1);
+		asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS,
+					  ASUS_WMI_DEVID_TUF_RGB_STATE,
+					  arg0, 0, NULL);
+	}
+}
+
 static int asus_hotk_prepare(struct device *device)
 {
+	struct asus_wmi *asus = dev_get_drvdata(device);
+
 	if (use_ally_mcu_hack == ASUS_WMI_ALLY_MCU_HACK_ENABLED) {
 		acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE,
 					   ASUS_USB0_PWR_EC0_CSEE_OFF);
 		msleep(ASUS_USB0_PWR_EC0_CSEE_WAIT);
 	}
+
+	asus_tuf_reassert_sleep_rgb_state(asus);
+
 	return 0;
 }
 
 #if defined(CONFIG_SUSPEND)
+static void asus_s2idle_prepare(void)
+{
+	asus_tuf_reassert_sleep_rgb_state(asus_hotk);
+}
+
 static void asus_ally_s2idle_restore(void)
 {
 	if (use_ally_mcu_hack == ASUS_WMI_ALLY_MCU_HACK_ENABLED) {
@@ -5444,20 +5502,20 @@ static void asus_ally_s2idle_restore(void)
 	}
 }
 
-/* Use only for Ally devices due to the wake_on_ac */
-static struct acpi_s2idle_dev_ops asus_ally_s2idle_dev_ops = {
+static struct acpi_s2idle_dev_ops asus_s2idle_dev_ops = {
+	.prepare = asus_s2idle_prepare,
 	.restore = asus_ally_s2idle_restore,
 };
 
 static void asus_s2idle_check_register(void)
 {
-	if (acpi_register_lps0_dev(&asus_ally_s2idle_dev_ops))
+	if (acpi_register_lps0_dev(&asus_s2idle_dev_ops))
 		pr_warn("failed to register LPS0 sleep handler in asus-wmi\n");
 }
 
 static void asus_s2idle_check_unregister(void)
 {
-	acpi_unregister_lps0_dev(&asus_ally_s2idle_dev_ops);
+	acpi_unregister_lps0_dev(&asus_s2idle_dev_ops);
 }
 #else
 static void asus_s2idle_check_register(void) {}
-- 
2.55.0


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

* Re: [PATCH v3 2/3] platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk
  2026-09-02 17:47 ` [PATCH v3 2/3] platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk Idotoho Reimon Simanjuntak
@ 2026-09-02 18:40   ` Denis Benato
  0 siblings, 0 replies; 6+ messages in thread
From: Denis Benato @ 2026-09-02 18:40 UTC (permalink / raw)
  To: Idotoho Reimon Simanjuntak, platform-driver-x86
  Cc: linux-kernel, Hans de Goede, Ilpo Järvinen, Luke D . Jones,
	Corentin Chary


On 9/2/26 19:47, Idotoho Reimon Simanjuntak wrote:
> The FA401 (TUF Gaming A14) series does not expose the TUF RGB state
> WMI device (0x00100057) through the standard DSTS probe, yet the EC
> does support the keyboard backlight power-state flags needed for sleep
> strobe functionality.
>
> Add a DMI-based quirk in asus-nb-wmi.c that matches on DMI_SYS_VENDOR
> "ASUSTeK COMPUTER INC." and DMI_BOARD_NAME "FA401", setting
> kbd_rgb_state_available = true in struct quirk_entry.
>
> In asus_wmi_add(), change the kbd_rgb_state_available assignment to
> also consider driver->quirks->kbd_rgb_state_available, so models with
> this quirk get the RGB state sysfs attributes even when DSTS probing
> fails.
>
> No PM/sleep/backlight changes are included in this commit; those will
> be addressed separately once the RGB state interface is available.
I would say get rid of this: doesn't add any value and in general doesn't
conform too well with the rule as "write commit messages as if you were
telling git what to do".

With that phrase removed

Reviewed-by: Denis Benato <denis.benato@linux.dev>
> Signed-off-by: Idotoho Reimon Simanjuntak <idotohors@gmail.com>
> ---
>  drivers/platform/x86/asus-nb-wmi.c | 13 +++++++++++++
>  drivers/platform/x86/asus-wmi.c    |  4 +++-
>  drivers/platform/x86/asus-wmi.h    |  1 +
>  3 files changed, 17 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
> index aeb461b16..47ceb6e46 100644
> --- a/drivers/platform/x86/asus-nb-wmi.c
> +++ b/drivers/platform/x86/asus-nb-wmi.c
> @@ -155,6 +155,10 @@ static struct quirk_entry quirk_asus_z13 = {
>  	.tablet_switch_mode = asus_wmi_kbd_dock_devid,
>  };
>  
> +static struct quirk_entry quirk_asus_fa401 = {
> +	.kbd_rgb_state_available = true,
> +};
> +
>  static int dmi_matched(const struct dmi_system_id *dmi)
>  {
>  	pr_info("Identified laptop model '%s'\n", dmi->ident);
> @@ -562,6 +566,15 @@ static const struct dmi_system_id asus_quirks[] = {
>  		},
>  		.driver_data = &quirk_asus_z13,
>  	},
> +	{
> +		.callback = dmi_matched,
> +		.ident = "ASUSTeK COMPUTER INC. FA401",
> +		.matches = {
> +			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
> +			DMI_MATCH(DMI_BOARD_NAME, "FA401"),
> +		},
> +		.driver_data = &quirk_asus_fa401,
> +	},
>  	{},
>  };
>  
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index efc730c2c..e7b2402c9 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -5181,7 +5181,9 @@ static int asus_wmi_add(struct platform_device *pdev)
>  
>  	asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU);
>  	asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU);
> -	asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE);
> +	asus->kbd_rgb_state_available =
> +		asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE) ||
> +		asus->driver->quirks->kbd_rgb_state_available;
>  
>  	if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE))
>  		asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE;
> diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
> index 5cd4392b9..9bc0b6145 100644
> --- a/drivers/platform/x86/asus-wmi.h
> +++ b/drivers/platform/x86/asus-wmi.h
> @@ -52,6 +52,7 @@ struct quirk_entry {
>  	 */
>  	int no_display_toggle;
>  	u32 xusb2pr;
> +	bool kbd_rgb_state_available;
>  };
>  
>  struct asus_wmi_driver {

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

* Re: [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands
  2026-09-02 17:47 ` [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands Idotoho Reimon Simanjuntak
@ 2026-09-02 18:44   ` Denis Benato
  0 siblings, 0 replies; 6+ messages in thread
From: Denis Benato @ 2026-09-02 18:44 UTC (permalink / raw)
  To: Idotoho Reimon Simanjuntak, platform-driver-x86
  Cc: linux-kernel, Hans de Goede, Ilpo Järvinen, Luke D . Jones,
	Corentin Chary


On 9/2/26 19:47, Idotoho Reimon Simanjuntak wrote:
> Replace open-coded bit shifts and magic numbers in kbd_rgb_mode_store()
> and kbd_rgb_state_store() with FIELD_PREP() and named GENMASK() masks.
>
> Define ASUS_WMI_TUF_RGB_STATE_CMD_ID (0xbd) as a named constant instead
> of an inline literal, making the required arg0 command ID self-documenting.
>
> In kbd_rgb_state_store(), remove the unused intermediate "flags" variable
> entirely. The old BIT(1)/BIT(3)/BIT(5)/BIT(7) construction is replaced by
> FIELD_PREP with per-flag named masks (TUF_RGB_STATE_BOOT, _AWAKE, _SLEEP,
> _KEYBOARD), building arg0 directly. This preserves the exact sysfs input
> format ("cmd boot awake sleep keyboard") and the resulting WMI argument
> bit layout — no behavioral change.
>
> In kbd_rgb_mode_store(), replace the positional shift expressions for
> arg1 and arg2 with FIELD_PREP using TUF_RGB_MODE_{CMD,MODE,RED,GREEN}
> and TUF_RGB_MODE_{BLUE,SPEED} masks respectively.
>
> This is a preparatory cleanup to improve readability before adding
> model-specific quirks that depend on these definitions.
I can see that there is some code that I wrote and Ilpo already
reviewed: when you use the work of someone you have to include
his Signed-off-by (that has to be present in the original patch).

I already know that this works because I tried it in my TUF
when I wrote it:

Reviewed-by: Denis Benato <denis.benato@linux.dev>
> Signed-off-by: Idotoho Reimon Simanjuntak <idotohors@gmail.com>
> ---
>  drivers/platform/x86/asus-wmi.c | 48 ++++++++++++++++++++++++++-------
>  1 file changed, 38 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
> index a65090429..efc730c2c 100644
> --- a/drivers/platform/x86/asus-wmi.c
> +++ b/drivers/platform/x86/asus-wmi.c
> @@ -15,6 +15,7 @@
>  
>  #include <linux/acpi.h>
>  #include <linux/backlight.h>
> +#include <linux/bitfield.h>
>  #include <linux/bits.h>
>  #include <linux/debugfs.h>
>  #include <linux/delay.h>
> @@ -1047,6 +1048,27 @@ static DEVICE_ATTR_RW(gpu_mux_mode);
>  #endif /* IS_ENABLED(CONFIG_ASUS_WMI_DEPRECATED_ATTRS) */
>  
>  /* TUF Laptop Keyboard RGB Modes **********************************************/
> +
> +/* Command IDs passed in arg0 byte 0 for TUF RGB WMI methods */
> +#define ASUS_WMI_TUF_RGB_STATE_CMD_ID	0xbd
> +
> +/* Bit mask for the save-to-BIOS command flag in kbd_rgb_state_store (arg0 bit 10) */
> +#define TUF_RGB_STATE_SAVE	GENMASK(10, 10)
> +
> +/* Bit masks for kbd_rgb_state_store flags field (arg0 bits [23:16]) */
> +#define TUF_RGB_STATE_BOOT	GENMASK(17, 17)
> +#define TUF_RGB_STATE_AWAKE	GENMASK(19, 19)
> +#define TUF_RGB_STATE_SLEEP	GENMASK(21, 21)
> +#define TUF_RGB_STATE_KEYBOARD	GENMASK(23, 23)
> +
> +/* Bit masks for kbd_rgb_mode_store fields */
> +#define TUF_RGB_MODE_CMD	GENMASK(7, 0)
> +#define TUF_RGB_MODE_MODE	GENMASK(15, 8)
> +#define TUF_RGB_MODE_RED	GENMASK(23, 16)
> +#define TUF_RGB_MODE_GREEN	GENMASK(31, 24)
> +#define TUF_RGB_MODE_BLUE	GENMASK(7, 0)
> +#define TUF_RGB_MODE_SPEED	GENMASK(15, 8)
> +
>  static ssize_t kbd_rgb_mode_store(struct device *dev,
>  				 struct device_attribute *attr,
>  				 const char *buf, size_t count)
> @@ -1093,7 +1115,12 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
>  	}
>  
>  	err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, asus->kbd_rgb_dev,
> -			cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL);
> +			FIELD_PREP(TUF_RGB_MODE_CMD, cmd) |
> +			FIELD_PREP(TUF_RGB_MODE_MODE, mode) |
> +			FIELD_PREP(TUF_RGB_MODE_RED, r) |
> +			FIELD_PREP(TUF_RGB_MODE_GREEN, g),
> +			FIELD_PREP(TUF_RGB_MODE_BLUE, b) |
> +			FIELD_PREP(TUF_RGB_MODE_SPEED, speed), NULL);
>  	if (err)
>  		return err;
>  
> @@ -1119,28 +1146,29 @@ static ssize_t kbd_rgb_state_store(struct device *dev,
>  				 struct device_attribute *attr,
>  				 const char *buf, size_t count)
>  {
> -	u32 flags, cmd, boot, awake, sleep, keyboard;
> +	u32 cmd, boot, awake, sleep, keyboard;
> +	u32 arg0;
>  	int err;
>  
>  	if (sscanf(buf, "%d %d %d %d %d", &cmd, &boot, &awake, &sleep, &keyboard) != 5)
>  		return -EINVAL;
>  
> +	arg0 = ASUS_WMI_TUF_RGB_STATE_CMD_ID;
> +
>  	if (cmd)
> -		cmd = BIT(2);
> +		arg0 |= FIELD_PREP(TUF_RGB_STATE_SAVE, 1);
>  
> -	flags = 0;
>  	if (boot)
> -		flags |= BIT(1);
> +		arg0 |= FIELD_PREP(TUF_RGB_STATE_BOOT, 1);
>  	if (awake)
> -		flags |= BIT(3);
> +		arg0 |= FIELD_PREP(TUF_RGB_STATE_AWAKE, 1);
>  	if (sleep)
> -		flags |= BIT(5);
> +		arg0 |= FIELD_PREP(TUF_RGB_STATE_SLEEP, 1);
>  	if (keyboard)
> -		flags |= BIT(7);
> +		arg0 |= FIELD_PREP(TUF_RGB_STATE_KEYBOARD, 1);
>  
> -	/* 0xbd is the required default arg0 for the method. Nothing happens otherwise */
>  	err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS,
> -			ASUS_WMI_DEVID_TUF_RGB_STATE, 0xbd | cmd << 8 | (flags << 16), 0, NULL);
> +			ASUS_WMI_DEVID_TUF_RGB_STATE, arg0, 0, NULL);
>  	if (err)
>  		return err;
>  

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

end of thread, other threads:[~2026-09-02 18:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-02 17:47 [PATCH v3 0/3] platform/x86: asus-wmi: fix FA401 series keyboard sleep strobe Idotoho Reimon Simanjuntak
2026-09-02 17:47 ` [PATCH v3 1/3] platform/x86: asus-wmi: use named masks for TUF RGB commands Idotoho Reimon Simanjuntak
2026-09-02 18:44   ` Denis Benato
2026-09-02 17:47 ` [PATCH v3 2/3] platform/x86: asus-wmi: enable TUF RGB state for FA401 via DMI quirk Idotoho Reimon Simanjuntak
2026-09-02 18:40   ` Denis Benato
2026-09-02 17:47 ` [PATCH v3 3/3] platform/x86: asus-wmi: re-assert FA401 keyboard state before S0ix Idotoho Reimon Simanjuntak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox