* [PATCH 0/2] hp-wmi: Omen 16-b1xxx (8A13) support + per-fan pwm @ 2026-05-13 19:39 foobisdweik 2026-05-13 19:39 ` [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) foobisdweik 2026-05-13 19:39 ` [PATCH 2/2] platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels foobisdweik 0 siblings, 2 replies; 6+ messages in thread From: foobisdweik @ 2026-05-13 19:39 UTC (permalink / raw) To: Hans de Goede, Ilpo Järvinen Cc: platform-driver-x86, linux-kernel, foobisdweik Hi all, Two patches against drivers/platform/x86/hp/hp-wmi.c. They are independent but both required to make fan control fully work on HP OMEN 16-b1xxx laptops. Patch 1 adds DMI board name 8A13 (OMEN by HP Laptop 16-b1xxx) to the existing Omen thermal-profile and Victus-S DMI tables. The firmware exposes the standard Omen PerformanceControl WMI feature and uses the same legacy EC layout and GM2D/GM2E methods as its sibling 8A44 (Omen 16-n0xxx). After this patch /sys/firmware/acpi/ platform_profile and the hp hwmon device come up correctly on 8A13. Patch 2 promotes the per-driver pwm setpoint to a two-element array so that hp-wmi exposes pwm1 (CPU fan) and pwm2 (GPU fan) independently on Victus-S-capable boards. The underlying WMI method (HPWMI_VICTUS_S_FAN_SPEED_SET_QUERY) already takes a two-byte buffer and the EC honors per-fan setpoints; the driver just hadn't been wired up that way. This is the standard hwmon shape for multi-fan systems and makes fan-control tools such as fancontrol and fan2go work out of the box. Tested on a stock HP OMEN 16-b1xxx (BIOS F.23, 12th-gen i7-12700H, RTX 3060) running 7.1-rc2 + these patches: platform_profile toggles cool/balanced/performance, fan1_input/fan2_input read independent tachs, and writing pwm1=60 + pwm2=200 simultaneously drives CPU fan to ~1600 RPM and GPU fan to ~5700 RPM (verified both via hwmon and direct read of EC offsets 0xB0..0xB3). Evidence from dmesg: [ 0.000000] DMI: HP OMEN by HP Laptop 16-b1xxx/8A13, BIOS F.23 08/15/2025 [ 7.643551] hp_wmi: Registered as platform profile handler Evidence from sensors (manual control mode): hp-isa-0000 Adapter: ISA adapter fan1: 2700 RPM fan2: 2800 RPM pwm1: 62% MANUAL CONTROL pwm2: 64% MANUAL CONTROL foobisdweik (2): platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels drivers/platform/x86/hp/hp-wmi.c | 53 +++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 15 deletions(-) -- 2.54.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) 2026-05-13 19:39 [PATCH 0/2] hp-wmi: Omen 16-b1xxx (8A13) support + per-fan pwm foobisdweik @ 2026-05-13 19:39 ` foobisdweik 2026-05-19 13:58 ` Ilpo Järvinen 2026-05-20 9:46 ` Krishna Chomal 2026-05-13 19:39 ` [PATCH 2/2] platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels foobisdweik 1 sibling, 2 replies; 6+ messages in thread From: foobisdweik @ 2026-05-13 19:39 UTC (permalink / raw) To: Hans de Goede, Ilpo Järvinen Cc: platform-driver-x86, linux-kernel, foobisdweik Add board name 8A13 (OMEN by HP Laptop 16-b1xxx, 12th-gen Intel/RTX 30 series) to the Omen thermal-profile, timed-thermal-profile, and Victus-S DMI lists. The 8A13 firmware exposes the standard Omen "PerformanceControl" WMI feature, uses the legacy EC thermal-profile offset (0x95), and implements the Victus-S-style GM2D/GM2E WMI methods at EC offsets 0xB0..0xB3 (RPM1..RPM4 tach) and 0x34..0x35 (SRP1/SRP2 setpoints). This makes it identical in interface to its same-era sibling 8A44 (Omen 16-n0xxx), so reuse omen_v1_legacy_thermal_params. After this change /sys/firmware/acpi/platform_profile reports cool/balanced/performance and the hp hwmon device exposes per-fan tachs plus the manual-mode pwm control on Omen 16-b1xxx. Signed-off-by: foobisdweik <dweikmferris@gmail.com> --- drivers/platform/x86/hp/hp-wmi.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 24c151289dd3..389506a6d2e3 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -157,7 +157,7 @@ static const char * const omen_thermal_profile_boards[] = { "886B", "886C", "88C8", "88CB", "88D1", "88D2", "88F4", "88F5", "88F6", "88F7", "88FD", "88FE", "88FF", "8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB", - "8A15", "8A42", + "8A13", "8A15", "8A42", "8BAD", "8C58", "8E41", @@ -177,7 +177,7 @@ static const char * const omen_thermal_profile_force_v0_boards[] = { * "balanced" when reaching zero. */ static const char * const omen_timed_thermal_profile_boards[] = { - "8A15", "8A42", + "8A13", "8A15", "8A42", "8BAD", }; @@ -189,6 +189,10 @@ static const char * const victus_thermal_profile_boards[] = { /* DMI Board names of Victus 16-r and Victus 16-s laptops */ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { + { + .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A13") }, + .driver_data = (void *)&omen_v1_legacy_thermal_params, + }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, .driver_data = (void *)&omen_v1_legacy_thermal_params, -- 2.54.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) 2026-05-13 19:39 ` [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) foobisdweik @ 2026-05-19 13:58 ` Ilpo Järvinen 2026-05-20 9:46 ` Krishna Chomal 1 sibling, 0 replies; 6+ messages in thread From: Ilpo Järvinen @ 2026-05-19 13:58 UTC (permalink / raw) To: foobisdweik; +Cc: Hans de Goede, platform-driver-x86, LKML On Wed, 13 May 2026, foobisdweik wrote: > Add board name 8A13 (OMEN by HP Laptop 16-b1xxx, 12th-gen Intel/RTX 30 > series) to the Omen thermal-profile, timed-thermal-profile, and Victus-S > DMI lists. > > The 8A13 firmware exposes the standard Omen "PerformanceControl" WMI > feature, uses the legacy EC thermal-profile offset (0x95), and > implements the Victus-S-style GM2D/GM2E WMI methods at EC offsets > 0xB0..0xB3 (RPM1..RPM4 tach) and 0x34..0x35 (SRP1/SRP2 setpoints). > This makes it identical in interface to its same-era sibling 8A44 > (Omen 16-n0xxx), so reuse omen_v1_legacy_thermal_params. > > After this change /sys/firmware/acpi/platform_profile reports > cool/balanced/performance and the hp hwmon device exposes per-fan > tachs plus the manual-mode pwm control on Omen 16-b1xxx. > > Signed-off-by: foobisdweik <dweikmferris@gmail.com> Hi, Thanks for the patch, but we're not allowed to take in patches with sign off lines using nicknames or pseudo names (please see Documentation/process/submitting-patches.rst). > --- > drivers/platform/x86/hp/hp-wmi.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c > index 24c151289dd3..389506a6d2e3 100644 > --- a/drivers/platform/x86/hp/hp-wmi.c > +++ b/drivers/platform/x86/hp/hp-wmi.c > @@ -157,7 +157,7 @@ static const char * const omen_thermal_profile_boards[] = { > "886B", "886C", "88C8", "88CB", "88D1", "88D2", "88F4", "88F5", "88F6", > "88F7", "88FD", "88FE", "88FF", > "8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB", > - "8A15", "8A42", > + "8A13", "8A15", "8A42", > "8BAD", > "8C58", > "8E41", > @@ -177,7 +177,7 @@ static const char * const omen_thermal_profile_force_v0_boards[] = { > * "balanced" when reaching zero. > */ > static const char * const omen_timed_thermal_profile_boards[] = { > - "8A15", "8A42", > + "8A13", "8A15", "8A42", > "8BAD", > }; > > @@ -189,6 +189,10 @@ static const char * const victus_thermal_profile_boards[] = { > > /* DMI Board names of Victus 16-r and Victus 16-s laptops */ > static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { > + { > + .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A13") }, > + .driver_data = (void *)&omen_v1_legacy_thermal_params, > + }, I'll soon be pushing out review-ilpo-fixes branch, which will add 8902 here. In order to avoid conflict with it, please base this change on top of it. > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, > .driver_data = (void *)&omen_v1_legacy_thermal_params, > -- i. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) 2026-05-13 19:39 ` [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) foobisdweik 2026-05-19 13:58 ` Ilpo Järvinen @ 2026-05-20 9:46 ` Krishna Chomal 1 sibling, 0 replies; 6+ messages in thread From: Krishna Chomal @ 2026-05-20 9:46 UTC (permalink / raw) To: foobisdweik Cc: Hans de Goede, Ilpo Järvinen, platform-driver-x86, linux-kernel On Wed, May 13, 2026 at 12:39:15PM -0700, foobisdweik wrote: >Add board name 8A13 (OMEN by HP Laptop 16-b1xxx, 12th-gen Intel/RTX 30 >series) to the Omen thermal-profile, timed-thermal-profile, and Victus-S >DMI lists. > The DMI lists are exclusively checked at every reference so adding to Victus-S seems sufficient, as addition to omen thermal-profile and timed-thermal-profile would not make a difference. >The 8A13 firmware exposes the standard Omen "PerformanceControl" WMI >feature, uses the legacy EC thermal-profile offset (0x95), and >implements the Victus-S-style GM2D/GM2E WMI methods at EC offsets >0xB0..0xB3 (RPM1..RPM4 tach) and 0x34..0x35 (SRP1/SRP2 setpoints). >This makes it identical in interface to its same-era sibling 8A44 >(Omen 16-n0xxx), so reuse omen_v1_legacy_thermal_params. > >After this change /sys/firmware/acpi/platform_profile reports >cool/balanced/performance and the hp hwmon device exposes per-fan >tachs plus the manual-mode pwm control on Omen 16-b1xxx. > >Signed-off-by: foobisdweik <dweikmferris@gmail.com> >--- > drivers/platform/x86/hp/hp-wmi.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > >diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c >index 24c151289dd3..389506a6d2e3 100644 >--- a/drivers/platform/x86/hp/hp-wmi.c >+++ b/drivers/platform/x86/hp/hp-wmi.c >@@ -157,7 +157,7 @@ static const char * const omen_thermal_profile_boards[] = { > "886B", "886C", "88C8", "88CB", "88D1", "88D2", "88F4", "88F5", "88F6", > "88F7", "88FD", "88FE", "88FF", > "8900", "8901", "8902", "8912", "8917", "8918", "8949", "894A", "89EB", >- "8A15", "8A42", >+ "8A13", "8A15", "8A42", > "8BAD", > "8C58", > "8E41", >@@ -177,7 +177,7 @@ static const char * const omen_thermal_profile_force_v0_boards[] = { > * "balanced" when reaching zero. > */ > static const char * const omen_timed_thermal_profile_boards[] = { >- "8A15", "8A42", >+ "8A13", "8A15", "8A42", > "8BAD", > }; > >@@ -189,6 +189,10 @@ static const char * const victus_thermal_profile_boards[] = { > > /* DMI Board names of Victus 16-r and Victus 16-s laptops */ > static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { >+ { >+ .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A13") }, >+ .driver_data = (void *)&omen_v1_legacy_thermal_params, >+ }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, > .driver_data = (void *)&omen_v1_legacy_thermal_params, >-- >2.54.0 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 2/2] platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels 2026-05-13 19:39 [PATCH 0/2] hp-wmi: Omen 16-b1xxx (8A13) support + per-fan pwm foobisdweik 2026-05-13 19:39 ` [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) foobisdweik @ 2026-05-13 19:39 ` foobisdweik 2026-05-20 10:21 ` Krishna Chomal 1 sibling, 1 reply; 6+ messages in thread From: foobisdweik @ 2026-05-13 19:39 UTC (permalink / raw) To: Hans de Goede, Ilpo Järvinen Cc: platform-driver-x86, linux-kernel, foobisdweik The Victus-S WMI fan-speed-set query (HPWMI_VICTUS_S_FAN_SPEED_SET_QUERY, GM2E in firmware) takes a two-byte buffer [cpu, gpu] and writes the values to EC SRP1/SRP2 setpoints independently. The driver however drove both fans from a single hwmon pwm1 attribute, with the GPU value derived as cpu + priv->gpu_delta from the fan table. This makes asymmetric fan curves (common ask: GPU fan louder than CPU under heavy gaming load) impossible from userspace fan-control tools that expect one pwm attribute per fan. Promote priv->pwm to a two-element array, add a second pwm hwmon channel, and extend hp_wmi_hwmon_write() / hp_wmi_apply_fan_settings() to drive the per-channel setpoints through GM2E. The U8_MAX sentinel in hp_wmi_fan_speed_set() selects the new per-fan path; existing callers using HP_FAN_SPEED_AUTOMATIC or a direct rpm value keep their behavior. The second pwm channel is only visible on Victus-S-capable boards, since other HP laptops still use the legacy single-fan WMI commands. Tested on OMEN by HP Laptop 16-b1xxx (8A13): writing pwm1=60, pwm2=200 in manual mode drives CPU fan to ~1600 RPM and GPU fan to ~5700 RPM simultaneously, verified via fan1_input/fan2_input tachs and direct read of EC offsets 0xB0..0xB3. Signed-off-by: foobisdweik <dweikmferris@gmail.com> --- drivers/platform/x86/hp/hp-wmi.c | 45 +++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 389506a6d2e3..40eb3715583a 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -486,7 +486,7 @@ struct hp_wmi_hwmon_priv { u8 max_rpm; int gpu_delta; u8 mode; - u8 pwm; + u8 pwm[2]; struct delayed_work keep_alive_dwork; }; @@ -822,12 +822,18 @@ static int hp_wmi_fan_speed_set(struct hp_wmi_hwmon_priv *priv, u8 speed) fan_speed[GPU_FAN] = speed; /* - * GPU fan speed is always a little higher than CPU fan speed, we fetch - * this delta value from the fan table during hwmon init. - * Exception: Speed is set to HP_FAN_SPEED_AUTOMATIC, to revert to - * automatic mode. + * Pass-through value U8_MAX: drive each fan from its own + * priv->pwm[] setpoint converted via pwm_to_rpm(). Used by the + * hwmon pwm1/pwm2 path that allows independent CPU/GPU fan control. + * + * Otherwise: GPU fan speed is always a little higher than CPU fan + * speed; we fetch this delta from the fan table during hwmon init. + * Exception: HP_FAN_SPEED_AUTOMATIC reverts to automatic mode. */ - if (speed != HP_FAN_SPEED_AUTOMATIC) { + if (speed == U8_MAX) { + fan_speed[CPU_FAN] = pwm_to_rpm(priv->pwm[CPU_FAN], priv); + fan_speed[GPU_FAN] = pwm_to_rpm(priv->pwm[GPU_FAN], priv); + } else if (speed != HP_FAN_SPEED_AUTOMATIC) { gpu_speed = speed + priv->gpu_delta; fan_speed[GPU_FAN] = clamp_val(gpu_speed, 0, U8_MAX); } @@ -2398,7 +2404,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) case PWM_MODE_MANUAL: if (!is_victus_s_thermal_profile()) return -EOPNOTSUPP; - ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv)); + ret = hp_wmi_fan_speed_set(priv, U8_MAX); if (ret < 0) return ret; mod_delayed_work(system_wq, &priv->keep_alive_dwork, @@ -2429,6 +2435,12 @@ static umode_t hp_wmi_hwmon_is_visible(const void *data, { switch (type) { case hwmon_pwm: + /* + * Second pwm channel only exists on Victus-S-style boards + * which expose an independent GPU fan setpoint. + */ + if (channel == 1 && !is_victus_s_thermal_profile()) + return 0; if (attr == hwmon_pwm_input && !is_victus_s_thermal_profile()) return 0; return 0644; @@ -2514,7 +2526,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, /* ensure PWM input is within valid fan speeds */ rpm = pwm_to_rpm(val, priv); rpm = clamp_val(rpm, priv->min_rpm, priv->max_rpm); - priv->pwm = rpm_to_pwm(rpm, priv); + priv->pwm[channel] = rpm_to_pwm(rpm, priv); return hp_wmi_apply_fan_settings(priv); } switch (val) { @@ -2525,13 +2537,18 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, if (!is_victus_s_thermal_profile()) return -EOPNOTSUPP; /* - * When switching to manual mode, set fan speed to - * current RPM values to ensure a smooth transition. + * When switching to manual mode, seed each per-fan + * setpoint from its current measured RPM so the + * transition is smooth. */ - rpm = hp_wmi_get_fan_speed_victus_s(channel); + rpm = hp_wmi_get_fan_speed_victus_s(CPU_FAN); + if (rpm < 0) + return rpm; + priv->pwm[CPU_FAN] = rpm_to_pwm(rpm / 100, priv); + rpm = hp_wmi_get_fan_speed_victus_s(GPU_FAN); if (rpm < 0) return rpm; - priv->pwm = rpm_to_pwm(rpm / 100, priv); + priv->pwm[GPU_FAN] = rpm_to_pwm(rpm / 100, priv); priv->mode = PWM_MODE_MANUAL; return hp_wmi_apply_fan_settings(priv); case PWM_MODE_AUTO: @@ -2547,7 +2564,9 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, static const struct hwmon_channel_info * const info[] = { HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), - HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE | HWMON_PWM_INPUT), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_ENABLE | HWMON_PWM_INPUT, + HWMON_PWM_ENABLE | HWMON_PWM_INPUT), NULL }; -- 2.54.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels 2026-05-13 19:39 ` [PATCH 2/2] platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels foobisdweik @ 2026-05-20 10:21 ` Krishna Chomal 0 siblings, 0 replies; 6+ messages in thread From: Krishna Chomal @ 2026-05-20 10:21 UTC (permalink / raw) To: foobisdweik Cc: Hans de Goede, Ilpo Järvinen, platform-driver-x86, linux-kernel On Wed, May 13, 2026 at 12:39:16PM -0700, foobisdweik wrote: >The Victus-S WMI fan-speed-set query (HPWMI_VICTUS_S_FAN_SPEED_SET_QUERY, >GM2E in firmware) takes a two-byte buffer [cpu, gpu] and writes the >values to EC SRP1/SRP2 setpoints independently. The driver however drove >both fans from a single hwmon pwm1 attribute, with the GPU value >derived as cpu + priv->gpu_delta from the fan table. This makes >asymmetric fan curves (common ask: GPU fan louder than CPU under >heavy gaming load) impossible from userspace fan-control tools that >expect one pwm attribute per fan. > >Promote priv->pwm to a two-element array, add a second pwm hwmon >channel, and extend hp_wmi_hwmon_write() / hp_wmi_apply_fan_settings() >to drive the per-channel setpoints through GM2E. > >The U8_MAX sentinel in hp_wmi_fan_speed_set() selects the new >per-fan path; existing callers using HP_FAN_SPEED_AUTOMATIC or a >direct rpm value keep their behavior. The second pwm channel is only >visible on Victus-S-capable boards, since other HP laptops still use >the legacy single-fan WMI commands. > >Tested on OMEN by HP Laptop 16-b1xxx (8A13): writing pwm1=60, pwm2=200 >in manual mode drives CPU fan to ~1600 RPM and GPU fan to ~5700 RPM >simultaneously, verified via fan1_input/fan2_input tachs and direct >read of EC offsets 0xB0..0xB3. > >Signed-off-by: foobisdweik <dweikmferris@gmail.com> >--- > drivers/platform/x86/hp/hp-wmi.c | 45 +++++++++++++++++++++++--------- > 1 file changed, 32 insertions(+), 13 deletions(-) > >diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c >index 389506a6d2e3..40eb3715583a 100644 >--- a/drivers/platform/x86/hp/hp-wmi.c >+++ b/drivers/platform/x86/hp/hp-wmi.c >@@ -486,7 +486,7 @@ struct hp_wmi_hwmon_priv { > u8 max_rpm; > int gpu_delta; > u8 mode; >- u8 pwm; >+ u8 pwm[2]; > struct delayed_work keep_alive_dwork; > }; > >@@ -822,12 +822,18 @@ static int hp_wmi_fan_speed_set(struct hp_wmi_hwmon_priv *priv, u8 speed) > fan_speed[GPU_FAN] = speed; > > /* >- * GPU fan speed is always a little higher than CPU fan speed, we fetch >- * this delta value from the fan table during hwmon init. >- * Exception: Speed is set to HP_FAN_SPEED_AUTOMATIC, to revert to >- * automatic mode. >+ * Pass-through value U8_MAX: drive each fan from its own >+ * priv->pwm[] setpoint converted via pwm_to_rpm(). Used by the >+ * hwmon pwm1/pwm2 path that allows independent CPU/GPU fan control. >+ * >+ * Otherwise: GPU fan speed is always a little higher than CPU fan >+ * speed; we fetch this delta from the fan table during hwmon init. >+ * Exception: HP_FAN_SPEED_AUTOMATIC reverts to automatic mode. > */ >- if (speed != HP_FAN_SPEED_AUTOMATIC) { >+ if (speed == U8_MAX) { >+ fan_speed[CPU_FAN] = pwm_to_rpm(priv->pwm[CPU_FAN], priv); >+ fan_speed[GPU_FAN] = pwm_to_rpm(priv->pwm[GPU_FAN], priv); >+ } else if (speed != HP_FAN_SPEED_AUTOMATIC) { > gpu_speed = speed + priv->gpu_delta; > fan_speed[GPU_FAN] = clamp_val(gpu_speed, 0, U8_MAX); > } Currently, there are 2 callers for hp_wmi_fan_speed_set: 1. hp_wmi_fan_speed_reset() -> calls via speed = HP_FAN_SPEED_AUTOMATIC, and 2. hp_wmi_apply_fan_settings() -> calls via speed = U8_MAX (as updated by you) So this else-if block is effectively never executed, which in turn means that gpu_delta is also now redundant. >@@ -2398,7 +2404,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > case PWM_MODE_MANUAL: > if (!is_victus_s_thermal_profile()) > return -EOPNOTSUPP; >- ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv)); >+ ret = hp_wmi_fan_speed_set(priv, U8_MAX); I think you could avoid passing the sentinel argument (speed) and directly update priv->pwm[] in the caller: hp_wmi_fan_speed_reset() > if (ret < 0) > return ret; > mod_delayed_work(system_wq, &priv->keep_alive_dwork, >@@ -2429,6 +2435,12 @@ static umode_t hp_wmi_hwmon_is_visible(const void *data, > { > switch (type) { > case hwmon_pwm: >+ /* >+ * Second pwm channel only exists on Victus-S-style boards >+ * which expose an independent GPU fan setpoint. >+ */ >+ if (channel == 1 && !is_victus_s_thermal_profile()) >+ return 0; Technically, the fan table has a dedicated field .num_fans (see struct victus_s_fan_table_header), so there is a possibility that some Victus-S-style device may not have second fan for pwm channel. But at least for the current entries, this is not the case, so I guess it would be safe to keep it this way. > if (attr == hwmon_pwm_input && !is_victus_s_thermal_profile()) > return 0; > return 0644; >@@ -2514,7 +2526,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > /* ensure PWM input is within valid fan speeds */ > rpm = pwm_to_rpm(val, priv); > rpm = clamp_val(rpm, priv->min_rpm, priv->max_rpm); >- priv->pwm = rpm_to_pwm(rpm, priv); >+ priv->pwm[channel] = rpm_to_pwm(rpm, priv); > return hp_wmi_apply_fan_settings(priv); > } > switch (val) { >@@ -2525,13 +2537,18 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > if (!is_victus_s_thermal_profile()) > return -EOPNOTSUPP; > /* >- * When switching to manual mode, set fan speed to >- * current RPM values to ensure a smooth transition. >+ * When switching to manual mode, seed each per-fan >+ * setpoint from its current measured RPM so the >+ * transition is smooth. > */ >- rpm = hp_wmi_get_fan_speed_victus_s(channel); >+ rpm = hp_wmi_get_fan_speed_victus_s(CPU_FAN); >+ if (rpm < 0) >+ return rpm; >+ priv->pwm[CPU_FAN] = rpm_to_pwm(rpm / 100, priv); >+ rpm = hp_wmi_get_fan_speed_victus_s(GPU_FAN); > if (rpm < 0) > return rpm; >- priv->pwm = rpm_to_pwm(rpm / 100, priv); >+ priv->pwm[GPU_FAN] = rpm_to_pwm(rpm / 100, priv); > priv->mode = PWM_MODE_MANUAL; > return hp_wmi_apply_fan_settings(priv); > case PWM_MODE_AUTO: >@@ -2547,7 +2564,9 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > > static const struct hwmon_channel_info * const info[] = { > HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), >- HWMON_CHANNEL_INFO(pwm, HWMON_PWM_ENABLE | HWMON_PWM_INPUT), >+ HWMON_CHANNEL_INFO(pwm, >+ HWMON_PWM_ENABLE | HWMON_PWM_INPUT, >+ HWMON_PWM_ENABLE | HWMON_PWM_INPUT), I think you can take this opportunity to explore adding fanX_{min,max,input} to hwmon as well. > NULL > }; > >-- >2.54.0 > ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-05-20 10:21 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-13 19:39 [PATCH 0/2] hp-wmi: Omen 16-b1xxx (8A13) support + per-fan pwm foobisdweik 2026-05-13 19:39 ` [PATCH 1/2] platform/x86: hp-wmi: Add support for Omen 16-b1xxx (8A13) foobisdweik 2026-05-19 13:58 ` Ilpo Järvinen 2026-05-20 9:46 ` Krishna Chomal 2026-05-13 19:39 ` [PATCH 2/2] platform/x86: hp-wmi: Expose independent CPU/GPU pwm channels foobisdweik 2026-05-20 10:21 ` Krishna Chomal
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.