From: Lucas Gillard <mirsella1@gmail.com>
To: platform-driver-x86@vger.kernel.org
Cc: jlee@suse.com, hansg@kernel.org, ilpo.jarvinen@linux.intel.com,
W_Armin@gmx.de, Lucas Gillard <mirsella1@gmail.com>
Subject: [PATCH] platform/x86: acer-wmi: support PH317-51 hwmon and kbd backlight
Date: Fri, 18 Sep 2026 17:55:04 +0200 [thread overview]
Message-ID: <6aad63a9.f9180b46.32931.492b@mx.google.com> (raw)
The Predator Helios 300 PH317-51 (2017) has the Predator gaming WMI
interface, but an early revision of it. Sensor queries and fan control
answer; the platform-profile and OC methods (22/23) do not exist. So it
gets a quirk that turns on HWMON without predator_v4.
The keyboard backlight has no WMI method behind it on this machine. I
probed the LED methods (2/4) every way I could and they neither report
nor change its state. The EC owns it instead, in RAM at 0x30/0x31, the
same bytes Fn+F9 flips. The read hook reports the live EC value, so the
Fn key and sysfs never disagree.
The code is mine, written with help from an AI coding assistant to
understand the codebase and how this kind of change is usually done;
this is my first kernel contribution. I verified every behavior
claimed here myself, on the machine.
Tested on a PH317-51: both temperatures, both fans, and the light going
on and off from sysfs.
Signed-off-by: Lucas Gillard <mirsella1@gmail.com>
Assisted-by: LLM
---
drivers/platform/x86/acer-wmi.c | 87 +++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 61ae622..f14b6e4 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -310,6 +310,7 @@ 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)
/*
* Interface type flags
@@ -359,6 +360,7 @@ struct acer_data {
int mailled;
int threeg;
int brightness;
+ int kbd_backlight;
};
struct acer_debug {
@@ -405,6 +407,8 @@ struct quirk_entry {
u8 gpu_fans;
u8 predator_v4;
u8 pwm;
+ u8 hwmon;
+ u8 kbd_backlight;
};
static struct quirk_entry *quirks;
@@ -425,6 +429,12 @@ static void __init set_quirks(void)
interface->capability |= ACER_CAP_PLATFORM_PROFILE |
ACER_CAP_HWMON;
+ if (quirks->hwmon)
+ interface->capability |= ACER_CAP_HWMON;
+
+ if (quirks->kbd_backlight)
+ interface->capability |= ACER_CAP_KBD_BACKLIGHT;
+
if (quirks->pwm)
interface->capability |= ACER_CAP_PWM;
}
@@ -466,6 +476,12 @@ static struct quirk_entry quirk_acer_predator_ph315_53 = {
.gpu_fans = 1,
};
+/* Firmware lacks the profile/OC methods, so no predator_v4. */
+static struct quirk_entry quirk_acer_predator_ph317_51 = {
+ .hwmon = 1,
+ .kbd_backlight = 1,
+};
+
static struct quirk_entry quirk_acer_predator_ph16_72 = {
.turbo = 1,
.cpu_fans = 1,
@@ -671,6 +687,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",
@@ -1947,6 +1972,45 @@ static void acer_led_exit(void)
led_classdev_unregister(&mail_led);
}
+/*
+ * No WMI method drives the backlight on this model; the EC keeps the
+ * state mirrored in both 0x30 and 0x31, so write both.
+ */
+static void kbd_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ value = !!value;
+ ec_write(0x30, value);
+ ec_write(0x31, value);
+}
+
+static enum led_brightness kbd_led_get(struct led_classdev *led_cdev)
+{
+ u8 result;
+
+ if (ec_read(0x30, &result))
+ return LED_OFF;
+ return (result & 0x1) ? LED_ON : LED_OFF;
+}
+
+static struct led_classdev kbd_led = {
+ .name = "acer-wmi::kbd_backlight",
+ .brightness_set = kbd_led_set,
+ .brightness_get = kbd_led_get,
+ .max_brightness = 1,
+};
+
+static int acer_kbd_led_init(struct device *dev)
+{
+ return led_classdev_register(dev, &kbd_led);
+}
+
+static void acer_kbd_led_exit(void)
+{
+ kbd_led_set(&kbd_led, LED_OFF);
+ led_classdev_unregister(&kbd_led);
+}
+
/*
* Backlight device
*/
@@ -2799,8 +2863,15 @@ static int acer_platform_probe(struct platform_device *device)
goto error_hwmon;
}
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT)) {
+ err = acer_kbd_led_init(&device->dev);
+ if (err)
+ goto error_kbd_backlight;
+ }
+
return 0;
+error_kbd_backlight:
error_hwmon:
error_platform_profile:
acer_rfkill_exit();
@@ -2816,6 +2887,8 @@ static int acer_platform_probe(struct platform_device *device)
static void acer_platform_remove(struct platform_device *device)
{
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT))
+ acer_kbd_led_exit();
if (has_cap(ACER_CAP_MAILLED))
acer_led_exit();
if (has_cap(ACER_CAP_BRIGHTNESS))
@@ -2844,6 +2917,14 @@ static int acer_suspend(struct device *dev)
data->brightness = value;
}
+ if (has_cap(ACER_CAP_KBD_BACKLIGHT)) {
+ u8 state;
+
+ if (!ec_read(0x30, &state))
+ data->kbd_backlight = state & 0x1;
+ kbd_led_set(&kbd_led, LED_OFF);
+ }
+
return 0;
}
@@ -2860,6 +2941,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))
+ kbd_led_set(&kbd_led, data->kbd_backlight);
+
if (acer_wmi_accel_dev)
acer_gsensor_init();
@@ -2881,6 +2965,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))
+ kbd_led_set(&kbd_led, LED_OFF);
}
static struct platform_driver acer_platform_driver = {
--
2.55.0
next reply other threads:[~2026-09-18 16:15 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 15:55 Lucas Gillard [this message]
2026-10-05 17:01 ` [PATCH] platform/x86: acer-wmi: support PH317-51 hwmon and kbd backlight Ilpo Järvinen
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=6aad63a9.f9180b46.32931.492b@mx.google.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=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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox