From: Lucas Gillard <mirsella1@gmail.com>
To: platform-driver-x86@vger.kernel.org
Cc: ilpo.jarvinen@linux.intel.com, jlee@suse.com, hansg@kernel.org,
W_Armin@gmx.de, linux-kernel@vger.kernel.org
Subject: [PATCH v2] platform/x86: acer-wmi: support PH317-51 hwmon and kbd backlight
Date: Tue, 27 Oct 2026 12:21:04 +0100 [thread overview]
Message-ID: <20261027112104.1464336-1-mirsella1@gmail.com> (raw)
In-Reply-To: <ea6d7395-c70f-9346-fc3f-9465adb5fef1@linux.intel.com>
The Predator Helios 300 PH317-51 exposes early gaming WMI methods for
temperature and fan sensors, but lacks the platform-profile and
overclocking methods (22 and 23). Enable hwmon for this model without
enabling platform-profile support.
Its keyboard backlight is controlled by EC registers 0x30 and 0x31;
the WMI LED methods do not report or change it. Fn+F9 updates both EC
registers. Register an on/off keyboard LED with a blocking setter and
read its brightness directly from the EC, so sysfs reflects changes
made with Fn+F9.
Write both registers to match the firmware's on/off states. Use the LED
core to suspend and resume the backlight, reading its current state from
the EC before suspend.
Signed-off-by: Lucas Gillard <mirsella1@gmail.com>
Assisted-by: LLM
---
Hi Ilpo,
Thanks for the review. This revision is based on the platform-drivers-x86
for-next tree at 9d3475065167197742b0882aff21cf8e78393277.
Changes in v2:
- Use the existing hwmon quirk after the predator_v4 split.
- Name both EC registers and the state mask, and use them throughout.
- Convert brightness to an explicit u8 on/off value without modifying
the enum argument; remove the redundant mask parentheses.
- Use brightness_set_blocking and return EC write errors.
- Use managed LED registration and remove the explicit off-write on
unregister. LED core handles teardown.
- Use LED-core helpers for suspend, resume and shutdown, draining pending
LED work before suspend/shutdown. Read the live EC state before suspend
to preserve Fn+F9 changes.
I'm currently away from the machine and haven't retested v2 on hardware. I'm sending this update for review.
I used an LLM for code changes, review and local validation.
v1: https://lore.kernel.org/r/6aad63a9.f9180b46.32931.492b@mx.google.com
Review: https://lore.kernel.org/r/ea6d7395-c70f-9346-fc3f-9465adb5fef1@linux.intel.com
Thanks,
Lucas
drivers/platform/x86/acer-wmi.c | 85 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 3a018fdf513891a8a012aeaa7185a3de521ecf47..b893e04712966fb1d792e4eb27955f3dbc8fad1d 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -310,6 +310,11 @@ struct hotkey_function_type_aa {
#define ACER_CAP_PLATFORM_PROFILE BIT(10)
#define ACER_CAP_HWMON BIT(11)
#define ACER_CAP_PWM BIT(12)
+#define ACER_CAP_KBD_BACKLIGHT BIT(13)
+
+#define ACER_KBD_BACKLIGHT_EC_STATE 0x30
+#define ACER_KBD_BACKLIGHT_EC_MIRROR 0x31
+#define ACER_KBD_BACKLIGHT_MASK BIT(0)
/*
* Interface type flags
@@ -406,6 +411,7 @@ struct quirk_entry {
bool hwmon;
bool platform_profile;
bool pwm;
+ bool kbd_backlight;
};
static struct quirk_entry *quirks;
@@ -430,6 +436,9 @@ static void __init set_quirks(void)
if (quirks->pwm)
interface->capability |= ACER_CAP_PWM;
+
+ if (quirks->kbd_backlight)
+ interface->capability |= ACER_CAP_KBD_BACKLIGHT;
}
static int __init dmi_matched(const struct dmi_system_id *dmi)
@@ -474,6 +483,12 @@ static struct quirk_entry quirk_acer_predator_ph315_53 = {
.gpu_fans = 1,
};
+/* Firmware supports sensors but lacks the platform-profile/OC methods. */
+static struct quirk_entry quirk_acer_predator_ph317_51 = {
+ .hwmon = true,
+ .kbd_backlight = true,
+};
+
static struct quirk_entry quirk_acer_nitro_anv15_51 = {
.cpu_fans = 1,
.gpu_fans = 1,
@@ -717,6 +732,15 @@ static const struct dmi_system_id acer_quirks[] __initconst = {
},
.driver_data = &quirk_acer_predator_ph315_53,
},
+ {
+ .callback = dmi_matched,
+ .ident = "Acer Predator PH317-51",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH317-51"),
+ },
+ .driver_data = &quirk_acer_predator_ph317_51,
+ },
{
.callback = dmi_matched,
.ident = "Acer Predator PHN16-71",
@@ -1968,7 +1992,7 @@ static void __init acer_commandline_init(void)
}
/*
- * LED device (Mail LED only, no other LEDs known yet)
+ * Mail LED device
*/
static void mail_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
@@ -1992,6 +2016,40 @@ static void acer_led_exit(void)
led_classdev_unregister(&mail_led);
}
+/*
+ * No WMI method drives this keyboard backlight. Fn+F9 changes both EC
+ * registers, so write both to reproduce the firmware's on/off states.
+ */
+static int kbd_led_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ u8 value = brightness == LED_OFF ? 0 : ACER_KBD_BACKLIGHT_MASK;
+ int ret;
+
+ ret = ec_write(ACER_KBD_BACKLIGHT_EC_STATE, value);
+ if (ret)
+ return ret;
+
+ return ec_write(ACER_KBD_BACKLIGHT_EC_MIRROR, value);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+ u8 value;
+
+ if (ec_read(ACER_KBD_BACKLIGHT_EC_STATE, &value))
+ return LED_OFF;
+
+ return value & ACER_KBD_BACKLIGHT_MASK ? LED_ON : LED_OFF;
+}
+
+static struct led_classdev kbd_led = {
+ .name = "acer-wmi::kbd_backlight",
+ .brightness_set_blocking = kbd_led_set,
+ .brightness_get = kbd_led_get,
+ .max_brightness = LED_ON,
+};
+
/*
* Backlight device
*/
@@ -2847,8 +2905,15 @@ static int acer_platform_probe(struct platform_device *device)
goto error_hwmon;
}
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT)) {
+ err = devm_led_classdev_register(&device->dev, &kbd_led);
+ if (err)
+ goto error_kbd_backlight;
+ }
+
return 0;
+error_kbd_backlight:
error_hwmon:
error_platform_profile:
acer_rfkill_exit();
@@ -2877,6 +2942,7 @@ static int acer_suspend(struct device *dev)
{
u32 value;
struct acer_data *data = &interface->data;
+ int ret;
if (!data)
return -ENOMEM;
@@ -2892,6 +2958,17 @@ static int acer_suspend(struct device *dev)
data->brightness = value;
}
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT)) {
+ u8 state;
+
+ ret = ec_read(ACER_KBD_BACKLIGHT_EC_STATE, &state);
+ if (ret)
+ return ret;
+
+ kbd_led.brightness = state & ACER_KBD_BACKLIGHT_MASK;
+ led_classdev_suspend(&kbd_led);
+ }
+
return 0;
}
@@ -2908,6 +2985,9 @@ static int acer_resume(struct device *dev)
if (has_cap(ACER_CAP_BRIGHTNESS))
set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT))
+ led_classdev_resume(&kbd_led);
+
if (acer_wmi_accel_dev)
acer_gsensor_init();
@@ -2929,6 +3009,9 @@ static void acer_platform_shutdown(struct platform_device *device)
if (has_cap(ACER_CAP_MAILLED))
set_u32(LED_OFF, ACER_CAP_MAILLED);
+
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT))
+ led_classdev_suspend(&kbd_led);
}
static struct platform_driver acer_platform_driver = {
base-commit: 9d3475065167197742b0882aff21cf8e78393277
prev parent reply other threads:[~2026-10-27 11:21 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 15:55 [PATCH] platform/x86: acer-wmi: support PH317-51 hwmon and kbd backlight Lucas Gillard
2026-10-05 17:01 ` Ilpo Järvinen
2026-10-27 11:21 ` Lucas Gillard [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261027112104.1464336-1-mirsella1@gmail.com \
--to=mirsella1@gmail.com \
--cc=W_Armin@gmx.de \
--cc=hansg@kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=jlee@suse.com \
--cc=linux-kernel@vger.kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.