* [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control
@ 2026-05-20 14:07 Radhey Kalra
2026-05-20 14:07 ` [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data Radhey Kalra
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Radhey Kalra @ 2026-05-20 14:07 UTC (permalink / raw)
To: platform-driver-x86
Cc: ilpo.jarvinen, hdegoede, krishna.chomal108, Radhey Kalra
Hi,
This is a smaller v5 split for the Victus 15-fb0xxx fan-control change.
Patch 1 prepares the hp-wmi board data and hwmon fan-control selection
so fan support can be described independently from Victus S thermal
profiles. Patch 2 adds fan-control support for Victus 15-fb0xxx board
8A3D.
Based on platform-drivers-x86/for-next commit:
165e81354eefd5551358112773f24027aac59d5a
Tested on a Victus by HP Gaming Laptop 15-fb0xxx, board 8A3D, BIOS
F.22. With the series applied, pwm1 and pwm1_enable are exposed and
the EC-layout warning is not emitted for 8A3D.
Radhey Kalra (2):
platform/x86: hp-wmi: Prepare Victus fan control board data
platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control
drivers/platform/x86/hp/hp-wmi.c | 212 ++++++++++++++++++++++---------
1 file changed, 153 insertions(+), 59 deletions(-)
---
Changes in v5:
- Reduce the series to two patches: one preparatory board-data/hwmon
patch and one focused 8A3D enablement patch.
- Drop the active_thermal_profile_params global and dereference the
thermal-profile data through active_board_params.
- Wrap the setup comment added in the preparatory patch to stay under
80 columns.
Changes in v4:
- Split v3 into two no-functional-changes-intended refactors, one
fan-table parsing fix, and one 8A3D support patch.
- Rebase on platform-drivers-x86/for-next commit 165e81354eefd555.
- Move revision notes to the cover letter.
Changes in v3:
- Rebase on platform-drivers-x86/for-next commit 165e81354eefd555.
- Keep the v2 board-data approach and 8A3D fan-control-only handling.
Changes in v2:
- Use real name in Signed-off-by.
- Replace the ad-hoc fan-control DMI table with board data in
.driver_data.
- Keep 8A3D fan-control-only instead of enabling Victus S thermal
profiles.
- Use the fixed fan-table parser path and derive gpu_delta from the
first non-zero GPU row.
--
2.54.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data 2026-05-20 14:07 [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra @ 2026-05-20 14:07 ` Radhey Kalra 2026-05-21 13:02 ` Ilpo Järvinen 2026-05-20 14:07 ` [PATCH v5 2/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra 2026-05-20 17:50 ` [PATCH v5 0/2] " Krishna Chomal 2 siblings, 1 reply; 9+ messages in thread From: Radhey Kalra @ 2026-05-20 14:07 UTC (permalink / raw) To: platform-driver-x86 Cc: ilpo.jarvinen, hdegoede, krishna.chomal108, Radhey Kalra Move the Victus S thermal-profile DMI data behind hp_wmi_board_params so board-specific feature data can describe thermal-profile and fan-control support together. Use the active board data for fan-control decisions instead of checking is_victus_s_thermal_profile() in the hwmon path. Also derive gpu_delta from the first non-zero GPU RPM row so fan tables whose first GPU RPM is zero still produce valid fan settings. No fan-control support changes intended for existing boards. Fan tables with an initial zero GPU RPM row now produce a valid GPU delta. Signed-off-by: Radhey Kalra <radheykalra901@gmail.com> --- drivers/platform/x86/hp/hp-wmi.c | 204 ++++++++++++++++++++++--------- 1 file changed, 145 insertions(+), 59 deletions(-) diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index d1cc6e7..dcfffe6 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -133,11 +133,52 @@ static const struct thermal_profile_params omen_v1_no_ec_thermal_params = { .ec_tp_offset = HP_NO_THERMAL_PROFILE_OFFSET, }; -/* - * A generic pointer for the currently-active board's thermal profile - * parameters. - */ -static struct thermal_profile_params *active_thermal_profile_params; +struct hp_wmi_fan_profile_params { + int (*get_fan_speed)(int fan); + bool fan_table; +}; + +struct hp_wmi_board_params { + const struct thermal_profile_params *thermal_profile; + const struct hp_wmi_fan_profile_params *fan_profile; +}; + +static int hp_wmi_get_fan_speed_victus_s(int fan); + +static const struct hp_wmi_fan_profile_params victus_s_fan_profile_params = { + .get_fan_speed = hp_wmi_get_fan_speed_victus_s, + .fan_table = true, +}; + +static const struct hp_wmi_board_params victus_s_board_params = { + .thermal_profile = &victus_s_thermal_params, + .fan_profile = &victus_s_fan_profile_params, +}; + +static const struct hp_wmi_board_params omen_v1_board_params = { + .thermal_profile = &omen_v1_thermal_params, + .fan_profile = &victus_s_fan_profile_params, +}; + +static const struct hp_wmi_board_params omen_v1_legacy_board_params = { + .thermal_profile = &omen_v1_legacy_thermal_params, + .fan_profile = &victus_s_fan_profile_params, +}; + +static const struct hp_wmi_board_params omen_v1_no_ec_board_params = { + .thermal_profile = &omen_v1_no_ec_thermal_params, + .fan_profile = &victus_s_fan_profile_params, +}; + +static const struct hp_wmi_board_params *active_board_params; + +static const struct thermal_profile_params *hp_wmi_thermal_profile(void) +{ + if (!active_board_params) + return NULL; + + return active_board_params->thermal_profile; +} /* DMI board names of devices that should use the omen specific path for * thermal profiles. @@ -187,67 +228,67 @@ static const char * const victus_thermal_profile_boards[] = { "8A25", }; -/* DMI Board names of Victus 16-r and Victus 16-s laptops */ -static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { +/* DMI board-specific feature data for Omen and Victus laptops. */ +static const struct dmi_system_id hp_wmi_feature_boards[] __initconst = { { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, - .driver_data = (void *)&omen_v1_legacy_thermal_params, + .driver_data = (void *)&omen_v1_legacy_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A4D") }, - .driver_data = (void *)&omen_v1_legacy_thermal_params, + .driver_data = (void *)&omen_v1_legacy_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") }, - .driver_data = (void *)&omen_v1_thermal_params, + .driver_data = (void *)&omen_v1_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") }, - .driver_data = (void *)&victus_s_thermal_params, + .driver_data = (void *)&victus_s_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCA") }, - .driver_data = (void *)&omen_v1_thermal_params, + .driver_data = (void *)&omen_v1_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") }, - .driver_data = (void *)&omen_v1_thermal_params, + .driver_data = (void *)&omen_v1_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") }, - .driver_data = (void *)&victus_s_thermal_params, + .driver_data = (void *)&victus_s_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") }, - .driver_data = (void *)&victus_s_thermal_params, + .driver_data = (void *)&victus_s_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C76") }, - .driver_data = (void *)&omen_v1_thermal_params, + .driver_data = (void *)&omen_v1_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C77") }, - .driver_data = (void *)&omen_v1_thermal_params, + .driver_data = (void *)&omen_v1_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") }, - .driver_data = (void *)&omen_v1_thermal_params, + .driver_data = (void *)&omen_v1_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C99") }, - .driver_data = (void *)&victus_s_thermal_params, + .driver_data = (void *)&victus_s_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C9C") }, - .driver_data = (void *)&victus_s_thermal_params, + .driver_data = (void *)&victus_s_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") }, - .driver_data = (void *)&victus_s_thermal_params, + .driver_data = (void *)&victus_s_board_params, }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D87") }, - .driver_data = (void *)&omen_v1_no_ec_thermal_params, + .driver_data = (void *)&omen_v1_no_ec_board_params, }, {}, }; @@ -1769,6 +1810,38 @@ static bool is_victus_s_thermal_profile(void) return is_victus_s_board; } +static const struct hp_wmi_fan_profile_params *hp_wmi_fan_profile(void) +{ + if (!active_board_params) + return NULL; + + return active_board_params->fan_profile; +} + +static bool hp_wmi_fan_control_supported(void) +{ + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); + + return params && params->get_fan_speed; +} + +static bool hp_wmi_fan_table_supported(void) +{ + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); + + return params && params->fan_table; +} + +static int hp_wmi_get_active_fan_speed(int fan) +{ + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); + + if (!params || !params->get_fan_speed) + return -EOPNOTSUPP; + + return params->get_fan_speed(fan); +} + static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable, bool *ppab_enable, u8 *dstate, @@ -1854,7 +1927,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil u8 current_dstate, current_gpu_slowdown_temp, tp; const struct thermal_profile_params *params; - params = active_thermal_profile_params; + params = hp_wmi_thermal_profile(); + if (!params) + return -ENODEV; + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { *profile = active_platform_profile; @@ -1866,10 +1942,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil return ret; /* - * We cannot use active_thermal_profile_params here, because boards - * like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, but logically - * it should have tp == 0x30 || tp == 0x31, as corrected by the Omen - * Gaming Hub on windows. Hence accept both of these values. + * Boards like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, + * but logically it should have tp == 0x30 || tp == 0x31, as + * corrected by the Omen Gaming Hub on windows. Hence accept both + * of these values. */ if (tp == victus_s_thermal_params.performance || tp == omen_v1_thermal_params.performance) { @@ -1904,12 +1980,12 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil static int platform_profile_victus_s_set_ec(enum platform_profile_option profile) { - struct thermal_profile_params *params; + const struct thermal_profile_params *params; bool gpu_ctgp_enable, gpu_ppab_enable; u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */ int err, tp; - params = active_thermal_profile_params; + params = hp_wmi_thermal_profile(); if (!params) return -ENODEV; @@ -2175,6 +2251,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { static int thermal_profile_setup(struct platform_device *device) { const struct platform_profile_ops *ops; + const struct thermal_profile_params *params; int err, tp; if (is_omen_thermal_profile()) { @@ -2206,13 +2283,17 @@ static int thermal_profile_setup(struct platform_device *device) ops = &platform_profile_victus_ops; } else if (is_victus_s_thermal_profile()) { + params = hp_wmi_thermal_profile(); + if (!params) + return -ENODEV; + /* * For an unknown EC layout board, platform_profile_victus_s_get_ec(), * behaves like a wrapper around active_platform_profile, to avoid using * uninitialized data, we default to PLATFORM_PROFILE_BALANCED. */ - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || - active_thermal_profile_params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || + params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { active_platform_profile = PLATFORM_PROFILE_BALANCED; } else { err = platform_profile_victus_s_get_ec(&active_platform_profile); @@ -2380,7 +2461,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) switch (priv->mode) { case PWM_MODE_MAX: - if (is_victus_s_thermal_profile()) { + if (hp_wmi_fan_control_supported()) { ret = hp_wmi_get_fan_count_userdefine_trigger(); if (ret < 0) return ret; @@ -2392,7 +2473,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); return 0; case PWM_MODE_MANUAL: - if (!is_victus_s_thermal_profile()) + if (!hp_wmi_fan_control_supported()) return -EOPNOTSUPP; ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv)); if (ret < 0) @@ -2401,7 +2482,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); return 0; case PWM_MODE_AUTO: - if (is_victus_s_thermal_profile()) { + if (hp_wmi_fan_control_supported()) { ret = hp_wmi_get_fan_count_userdefine_trigger(); if (ret < 0) return ret; @@ -2425,12 +2506,12 @@ static umode_t hp_wmi_hwmon_is_visible(const void *data, { switch (type) { case hwmon_pwm: - if (attr == hwmon_pwm_input && !is_victus_s_thermal_profile()) + if (attr == hwmon_pwm_input && !hp_wmi_fan_control_supported()) return 0; return 0644; case hwmon_fan: - if (is_victus_s_thermal_profile()) { - if (hp_wmi_get_fan_speed_victus_s(channel) >= 0) + if (hp_wmi_fan_control_supported()) { + if (hp_wmi_get_active_fan_speed(channel) >= 0) return 0444; } else { if (hp_wmi_get_fan_speed(channel) >= 0) @@ -2454,8 +2535,8 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, priv = dev_get_drvdata(dev); switch (type) { case hwmon_fan: - if (is_victus_s_thermal_profile()) - ret = hp_wmi_get_fan_speed_victus_s(channel); + if (hp_wmi_fan_control_supported()) + ret = hp_wmi_get_active_fan_speed(channel); else ret = hp_wmi_get_fan_speed(channel); if (ret < 0) @@ -2464,10 +2545,10 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, return 0; case hwmon_pwm: if (attr == hwmon_pwm_input) { - if (!is_victus_s_thermal_profile()) + if (!hp_wmi_fan_control_supported()) return -EOPNOTSUPP; - rpm = hp_wmi_get_fan_speed_victus_s(channel); + rpm = hp_wmi_get_active_fan_speed(channel); if (rpm < 0) return rpm; *val = rpm_to_pwm(rpm / 100, priv); @@ -2501,7 +2582,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, switch (type) { case hwmon_pwm: if (attr == hwmon_pwm_input) { - if (!is_victus_s_thermal_profile()) + if (!hp_wmi_fan_control_supported()) return -EOPNOTSUPP; /* PWM input is invalid when not in manual mode */ if (priv->mode != PWM_MODE_MANUAL) @@ -2518,13 +2599,13 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, priv->mode = PWM_MODE_MAX; return hp_wmi_apply_fan_settings(priv); case PWM_MODE_MANUAL: - if (!is_victus_s_thermal_profile()) + if (!hp_wmi_fan_control_supported()) return -EOPNOTSUPP; /* * When switching to manual mode, set fan speed to * current RPM values to ensure a smooth transition. */ - rpm = hp_wmi_get_fan_speed_victus_s(channel); + rpm = hp_wmi_get_active_fan_speed(channel); if (rpm < 0) return rpm; priv->pwm = rpm_to_pwm(rpm / 100, priv); @@ -2585,13 +2666,14 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) u8 min_rpm, max_rpm; u8 cpu_rpm, gpu_rpm, noise_db; int gpu_delta, i, num_entries, ret; + bool gpu_delta_found = false; size_t header_size, entry_size; /* Default behaviour on hwmon init is automatic mode */ priv->mode = PWM_MODE_AUTO; - /* Bypass all non-Victus S devices */ - if (!is_victus_s_thermal_profile()) + /* Bypass devices without fan control support. */ + if (!hp_wmi_fan_table_supported()) return 0; ret = hp_wmi_perform_query(HPWMI_VICTUS_S_GET_FAN_TABLE_QUERY, @@ -2625,12 +2707,15 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) min_rpm = cpu_rpm; if (cpu_rpm > max_rpm) max_rpm = cpu_rpm; + if (!gpu_delta_found && gpu_rpm > 0) { + gpu_delta = gpu_rpm - cpu_rpm; + gpu_delta_found = true; + } } - if (min_rpm == U8_MAX || max_rpm == 0) + if (min_rpm == U8_MAX || max_rpm == 0 || !gpu_delta_found) return -EINVAL; - gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm; priv->min_rpm = min_rpm; priv->max_rpm = max_rpm; priv->gpu_delta = gpu_delta; @@ -2673,24 +2758,25 @@ static int hp_wmi_hwmon_init(void) return 0; } -static void __init setup_active_thermal_profile_params(void) +static void __init setup_active_board_params(void) { const struct dmi_system_id *id; + const struct thermal_profile_params *params; - /* - * Currently only victus_s devices use the - * active_thermal_profile_params - */ - id = dmi_first_match(victus_s_thermal_profile_boards); + id = dmi_first_match(hp_wmi_feature_boards); if (id) { + active_board_params = id->driver_data; + params = hp_wmi_thermal_profile(); + if (!params) + return; + /* * Marking this boolean is required to ensure that * is_victus_s_thermal_profile() behaves like a valid * wrapper. */ is_victus_s_board = true; - active_thermal_profile_params = id->driver_data; - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { pr_warn("Unknown EC layout for board %s. Thermal profile readback will be disabled. Please report this to platform-driver-x86@vger.kernel.org\n", dmi_get_system_info(DMI_BOARD_NAME)); } @@ -2725,10 +2811,10 @@ static int __init hp_wmi_init(void) } /* - * Setup active board's thermal profile parameters before - * starting platform driver probe. + * Setup active board feature data before starting platform + * driver probe. */ - setup_active_thermal_profile_params(); + setup_active_board_params(); err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); if (err) goto err_unregister_device; -- 2.54.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data 2026-05-20 14:07 ` [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data Radhey Kalra @ 2026-05-21 13:02 ` Ilpo Järvinen 2026-05-21 13:06 ` Radhey Kalra 0 siblings, 1 reply; 9+ messages in thread From: Ilpo Järvinen @ 2026-05-21 13:02 UTC (permalink / raw) To: Radhey Kalra; +Cc: platform-driver-x86, hdegoede, krishna.chomal108 On Wed, 20 May 2026, Radhey Kalra wrote: > Move the Victus S thermal-profile DMI data behind hp_wmi_board_params so > board-specific feature data can describe thermal-profile and fan-control > support together. > > Use the active board data for fan-control decisions instead of checking > is_victus_s_thermal_profile() in the hwmon path. > Also derive gpu_delta > from the first non-zero GPU RPM row so fan tables whose first GPU RPM is > zero still produce valid fan settings. Unfortunately, moving gpu_delta things from own patch to the refactor patch is a step backwards. Why would it logically belong to this patch?? -- i. > No fan-control support changes intended for existing boards. Fan tables > with an initial zero GPU RPM row now produce a valid GPU delta. > > Signed-off-by: Radhey Kalra <radheykalra901@gmail.com> > --- > drivers/platform/x86/hp/hp-wmi.c | 204 ++++++++++++++++++++++--------- > 1 file changed, 145 insertions(+), 59 deletions(-) > > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c > index d1cc6e7..dcfffe6 100644 > --- a/drivers/platform/x86/hp/hp-wmi.c > +++ b/drivers/platform/x86/hp/hp-wmi.c > @@ -133,11 +133,52 @@ static const struct thermal_profile_params omen_v1_no_ec_thermal_params = { > .ec_tp_offset = HP_NO_THERMAL_PROFILE_OFFSET, > }; > > -/* > - * A generic pointer for the currently-active board's thermal profile > - * parameters. > - */ > -static struct thermal_profile_params *active_thermal_profile_params; > +struct hp_wmi_fan_profile_params { > + int (*get_fan_speed)(int fan); > + bool fan_table; > +}; > + > +struct hp_wmi_board_params { > + const struct thermal_profile_params *thermal_profile; > + const struct hp_wmi_fan_profile_params *fan_profile; > +}; > + > +static int hp_wmi_get_fan_speed_victus_s(int fan); > + > +static const struct hp_wmi_fan_profile_params victus_s_fan_profile_params = { > + .get_fan_speed = hp_wmi_get_fan_speed_victus_s, > + .fan_table = true, > +}; > + > +static const struct hp_wmi_board_params victus_s_board_params = { > + .thermal_profile = &victus_s_thermal_params, > + .fan_profile = &victus_s_fan_profile_params, > +}; > + > +static const struct hp_wmi_board_params omen_v1_board_params = { > + .thermal_profile = &omen_v1_thermal_params, > + .fan_profile = &victus_s_fan_profile_params, > +}; > + > +static const struct hp_wmi_board_params omen_v1_legacy_board_params = { > + .thermal_profile = &omen_v1_legacy_thermal_params, > + .fan_profile = &victus_s_fan_profile_params, > +}; > + > +static const struct hp_wmi_board_params omen_v1_no_ec_board_params = { > + .thermal_profile = &omen_v1_no_ec_thermal_params, > + .fan_profile = &victus_s_fan_profile_params, > +}; > + > +static const struct hp_wmi_board_params *active_board_params; > + > +static const struct thermal_profile_params *hp_wmi_thermal_profile(void) > +{ > + if (!active_board_params) > + return NULL; > + > + return active_board_params->thermal_profile; > +} > > /* DMI board names of devices that should use the omen specific path for > * thermal profiles. > @@ -187,67 +228,67 @@ static const char * const victus_thermal_profile_boards[] = { > "8A25", > }; > > -/* DMI Board names of Victus 16-r and Victus 16-s laptops */ > -static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { > +/* DMI board-specific feature data for Omen and Victus laptops. */ > +static const struct dmi_system_id hp_wmi_feature_boards[] __initconst = { > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, > - .driver_data = (void *)&omen_v1_legacy_thermal_params, > + .driver_data = (void *)&omen_v1_legacy_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A4D") }, > - .driver_data = (void *)&omen_v1_legacy_thermal_params, > + .driver_data = (void *)&omen_v1_legacy_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") }, > - .driver_data = (void *)&omen_v1_thermal_params, > + .driver_data = (void *)&omen_v1_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") }, > - .driver_data = (void *)&victus_s_thermal_params, > + .driver_data = (void *)&victus_s_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCA") }, > - .driver_data = (void *)&omen_v1_thermal_params, > + .driver_data = (void *)&omen_v1_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") }, > - .driver_data = (void *)&omen_v1_thermal_params, > + .driver_data = (void *)&omen_v1_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") }, > - .driver_data = (void *)&victus_s_thermal_params, > + .driver_data = (void *)&victus_s_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") }, > - .driver_data = (void *)&victus_s_thermal_params, > + .driver_data = (void *)&victus_s_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C76") }, > - .driver_data = (void *)&omen_v1_thermal_params, > + .driver_data = (void *)&omen_v1_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C77") }, > - .driver_data = (void *)&omen_v1_thermal_params, > + .driver_data = (void *)&omen_v1_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") }, > - .driver_data = (void *)&omen_v1_thermal_params, > + .driver_data = (void *)&omen_v1_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C99") }, > - .driver_data = (void *)&victus_s_thermal_params, > + .driver_data = (void *)&victus_s_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C9C") }, > - .driver_data = (void *)&victus_s_thermal_params, > + .driver_data = (void *)&victus_s_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") }, > - .driver_data = (void *)&victus_s_thermal_params, > + .driver_data = (void *)&victus_s_board_params, > }, > { > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D87") }, > - .driver_data = (void *)&omen_v1_no_ec_thermal_params, > + .driver_data = (void *)&omen_v1_no_ec_board_params, > }, > {}, > }; > @@ -1769,6 +1810,38 @@ static bool is_victus_s_thermal_profile(void) > return is_victus_s_board; > } > > +static const struct hp_wmi_fan_profile_params *hp_wmi_fan_profile(void) > +{ > + if (!active_board_params) > + return NULL; > + > + return active_board_params->fan_profile; > +} > + > +static bool hp_wmi_fan_control_supported(void) > +{ > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > + > + return params && params->get_fan_speed; > +} > + > +static bool hp_wmi_fan_table_supported(void) > +{ > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > + > + return params && params->fan_table; > +} > + > +static int hp_wmi_get_active_fan_speed(int fan) > +{ > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > + > + if (!params || !params->get_fan_speed) > + return -EOPNOTSUPP; > + > + return params->get_fan_speed(fan); > +} > + > static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable, > bool *ppab_enable, > u8 *dstate, > @@ -1854,7 +1927,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > u8 current_dstate, current_gpu_slowdown_temp, tp; > const struct thermal_profile_params *params; > > - params = active_thermal_profile_params; > + params = hp_wmi_thermal_profile(); > + if (!params) > + return -ENODEV; > + > if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > *profile = active_platform_profile; > @@ -1866,10 +1942,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > return ret; > > /* > - * We cannot use active_thermal_profile_params here, because boards > - * like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, but logically > - * it should have tp == 0x30 || tp == 0x31, as corrected by the Omen > - * Gaming Hub on windows. Hence accept both of these values. > + * Boards like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, > + * but logically it should have tp == 0x30 || tp == 0x31, as > + * corrected by the Omen Gaming Hub on windows. Hence accept both > + * of these values. > */ > if (tp == victus_s_thermal_params.performance || > tp == omen_v1_thermal_params.performance) { > @@ -1904,12 +1980,12 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > static int platform_profile_victus_s_set_ec(enum platform_profile_option profile) > { > - struct thermal_profile_params *params; > + const struct thermal_profile_params *params; > bool gpu_ctgp_enable, gpu_ppab_enable; > u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */ > int err, tp; > > - params = active_thermal_profile_params; > + params = hp_wmi_thermal_profile(); > if (!params) > return -ENODEV; > > @@ -2175,6 +2251,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { > static int thermal_profile_setup(struct platform_device *device) > { > const struct platform_profile_ops *ops; > + const struct thermal_profile_params *params; > int err, tp; > > if (is_omen_thermal_profile()) { > @@ -2206,13 +2283,17 @@ static int thermal_profile_setup(struct platform_device *device) > > ops = &platform_profile_victus_ops; > } else if (is_victus_s_thermal_profile()) { > + params = hp_wmi_thermal_profile(); > + if (!params) > + return -ENODEV; > + > /* > * For an unknown EC layout board, platform_profile_victus_s_get_ec(), > * behaves like a wrapper around active_platform_profile, to avoid using > * uninitialized data, we default to PLATFORM_PROFILE_BALANCED. > */ > - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > - active_thermal_profile_params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > + params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > active_platform_profile = PLATFORM_PROFILE_BALANCED; > } else { > err = platform_profile_victus_s_get_ec(&active_platform_profile); > @@ -2380,7 +2461,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > switch (priv->mode) { > case PWM_MODE_MAX: > - if (is_victus_s_thermal_profile()) { > + if (hp_wmi_fan_control_supported()) { > ret = hp_wmi_get_fan_count_userdefine_trigger(); > if (ret < 0) > return ret; > @@ -2392,7 +2473,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); > return 0; > case PWM_MODE_MANUAL: > - if (!is_victus_s_thermal_profile()) > + if (!hp_wmi_fan_control_supported()) > return -EOPNOTSUPP; > ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv)); > if (ret < 0) > @@ -2401,7 +2482,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); > return 0; > case PWM_MODE_AUTO: > - if (is_victus_s_thermal_profile()) { > + if (hp_wmi_fan_control_supported()) { > ret = hp_wmi_get_fan_count_userdefine_trigger(); > if (ret < 0) > return ret; > @@ -2425,12 +2506,12 @@ static umode_t hp_wmi_hwmon_is_visible(const void *data, > { > switch (type) { > case hwmon_pwm: > - if (attr == hwmon_pwm_input && !is_victus_s_thermal_profile()) > + if (attr == hwmon_pwm_input && !hp_wmi_fan_control_supported()) > return 0; > return 0644; > case hwmon_fan: > - if (is_victus_s_thermal_profile()) { > - if (hp_wmi_get_fan_speed_victus_s(channel) >= 0) > + if (hp_wmi_fan_control_supported()) { > + if (hp_wmi_get_active_fan_speed(channel) >= 0) > return 0444; > } else { > if (hp_wmi_get_fan_speed(channel) >= 0) > @@ -2454,8 +2535,8 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, > priv = dev_get_drvdata(dev); > switch (type) { > case hwmon_fan: > - if (is_victus_s_thermal_profile()) > - ret = hp_wmi_get_fan_speed_victus_s(channel); > + if (hp_wmi_fan_control_supported()) > + ret = hp_wmi_get_active_fan_speed(channel); > else > ret = hp_wmi_get_fan_speed(channel); > if (ret < 0) > @@ -2464,10 +2545,10 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, > return 0; > case hwmon_pwm: > if (attr == hwmon_pwm_input) { > - if (!is_victus_s_thermal_profile()) > + if (!hp_wmi_fan_control_supported()) > return -EOPNOTSUPP; > > - rpm = hp_wmi_get_fan_speed_victus_s(channel); > + rpm = hp_wmi_get_active_fan_speed(channel); > if (rpm < 0) > return rpm; > *val = rpm_to_pwm(rpm / 100, priv); > @@ -2501,7 +2582,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > switch (type) { > case hwmon_pwm: > if (attr == hwmon_pwm_input) { > - if (!is_victus_s_thermal_profile()) > + if (!hp_wmi_fan_control_supported()) > return -EOPNOTSUPP; > /* PWM input is invalid when not in manual mode */ > if (priv->mode != PWM_MODE_MANUAL) > @@ -2518,13 +2599,13 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > priv->mode = PWM_MODE_MAX; > return hp_wmi_apply_fan_settings(priv); > case PWM_MODE_MANUAL: > - if (!is_victus_s_thermal_profile()) > + if (!hp_wmi_fan_control_supported()) > return -EOPNOTSUPP; > /* > * When switching to manual mode, set fan speed to > * current RPM values to ensure a smooth transition. > */ > - rpm = hp_wmi_get_fan_speed_victus_s(channel); > + rpm = hp_wmi_get_active_fan_speed(channel); > if (rpm < 0) > return rpm; > priv->pwm = rpm_to_pwm(rpm / 100, priv); > @@ -2585,13 +2666,14 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) > u8 min_rpm, max_rpm; > u8 cpu_rpm, gpu_rpm, noise_db; > int gpu_delta, i, num_entries, ret; > + bool gpu_delta_found = false; > size_t header_size, entry_size; > > /* Default behaviour on hwmon init is automatic mode */ > priv->mode = PWM_MODE_AUTO; > > - /* Bypass all non-Victus S devices */ > - if (!is_victus_s_thermal_profile()) > + /* Bypass devices without fan control support. */ > + if (!hp_wmi_fan_table_supported()) > return 0; > > ret = hp_wmi_perform_query(HPWMI_VICTUS_S_GET_FAN_TABLE_QUERY, > @@ -2625,12 +2707,15 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) > min_rpm = cpu_rpm; > if (cpu_rpm > max_rpm) > max_rpm = cpu_rpm; > + if (!gpu_delta_found && gpu_rpm > 0) { > + gpu_delta = gpu_rpm - cpu_rpm; > + gpu_delta_found = true; > + } > } > > - if (min_rpm == U8_MAX || max_rpm == 0) > + if (min_rpm == U8_MAX || max_rpm == 0 || !gpu_delta_found) > return -EINVAL; > > - gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm; > priv->min_rpm = min_rpm; > priv->max_rpm = max_rpm; > priv->gpu_delta = gpu_delta; > @@ -2673,24 +2758,25 @@ static int hp_wmi_hwmon_init(void) > return 0; > } > > -static void __init setup_active_thermal_profile_params(void) > +static void __init setup_active_board_params(void) > { > const struct dmi_system_id *id; > + const struct thermal_profile_params *params; > > - /* > - * Currently only victus_s devices use the > - * active_thermal_profile_params > - */ > - id = dmi_first_match(victus_s_thermal_profile_boards); > + id = dmi_first_match(hp_wmi_feature_boards); > if (id) { > + active_board_params = id->driver_data; > + params = hp_wmi_thermal_profile(); > + if (!params) > + return; > + > /* > * Marking this boolean is required to ensure that > * is_victus_s_thermal_profile() behaves like a valid > * wrapper. > */ > is_victus_s_board = true; > - active_thermal_profile_params = id->driver_data; > - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { > + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { > pr_warn("Unknown EC layout for board %s. Thermal profile readback will be disabled. Please report this to platform-driver-x86@vger.kernel.org\n", > dmi_get_system_info(DMI_BOARD_NAME)); > } > @@ -2725,10 +2811,10 @@ static int __init hp_wmi_init(void) > } > > /* > - * Setup active board's thermal profile parameters before > - * starting platform driver probe. > + * Setup active board feature data before starting platform > + * driver probe. > */ > - setup_active_thermal_profile_params(); > + setup_active_board_params(); > err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); > if (err) > goto err_unregister_device; > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data 2026-05-21 13:02 ` Ilpo Järvinen @ 2026-05-21 13:06 ` Radhey Kalra 2026-05-21 13:17 ` Ilpo Järvinen 0 siblings, 1 reply; 9+ messages in thread From: Radhey Kalra @ 2026-05-21 13:06 UTC (permalink / raw) To: Ilpo Järvinen; +Cc: platform-driver-x86, krishna.chomal108 Hi Ilpo, Agreed, that was a mistake. The gpu_delta parsing change does not logically belong in the board-data refactor. I folded it into the preparatory patch while trying to reduce the series size, but that made the patch less focused. I will split it back out so the series is: board-data / fan-control selection refactor fan-table gpu_delta parsing fix 8A3D board addition Thanks, Radhey On Thu, May 21, 2026 at 6:33 PM Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> wrote: > > On Wed, 20 May 2026, Radhey Kalra wrote: > > > Move the Victus S thermal-profile DMI data behind hp_wmi_board_params so > > board-specific feature data can describe thermal-profile and fan-control > > support together. > > > > Use the active board data for fan-control decisions instead of checking > > is_victus_s_thermal_profile() in the hwmon path. > > > Also derive gpu_delta > > from the first non-zero GPU RPM row so fan tables whose first GPU RPM is > > zero still produce valid fan settings. > > Unfortunately, moving gpu_delta things from own patch to the refactor > patch is a step backwards. > > Why would it logically belong to this patch?? > > -- > i. > > > No fan-control support changes intended for existing boards. Fan tables > > with an initial zero GPU RPM row now produce a valid GPU delta. > > > > Signed-off-by: Radhey Kalra <radheykalra901@gmail.com> > > --- > > drivers/platform/x86/hp/hp-wmi.c | 204 ++++++++++++++++++++++--------- > > 1 file changed, 145 insertions(+), 59 deletions(-) > > > > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c > > index d1cc6e7..dcfffe6 100644 > > --- a/drivers/platform/x86/hp/hp-wmi.c > > +++ b/drivers/platform/x86/hp/hp-wmi.c > > @@ -133,11 +133,52 @@ static const struct thermal_profile_params omen_v1_no_ec_thermal_params = { > > .ec_tp_offset = HP_NO_THERMAL_PROFILE_OFFSET, > > }; > > > > -/* > > - * A generic pointer for the currently-active board's thermal profile > > - * parameters. > > - */ > > -static struct thermal_profile_params *active_thermal_profile_params; > > +struct hp_wmi_fan_profile_params { > > + int (*get_fan_speed)(int fan); > > + bool fan_table; > > +}; > > + > > +struct hp_wmi_board_params { > > + const struct thermal_profile_params *thermal_profile; > > + const struct hp_wmi_fan_profile_params *fan_profile; > > +}; > > + > > +static int hp_wmi_get_fan_speed_victus_s(int fan); > > + > > +static const struct hp_wmi_fan_profile_params victus_s_fan_profile_params = { > > + .get_fan_speed = hp_wmi_get_fan_speed_victus_s, > > + .fan_table = true, > > +}; > > + > > +static const struct hp_wmi_board_params victus_s_board_params = { > > + .thermal_profile = &victus_s_thermal_params, > > + .fan_profile = &victus_s_fan_profile_params, > > +}; > > + > > +static const struct hp_wmi_board_params omen_v1_board_params = { > > + .thermal_profile = &omen_v1_thermal_params, > > + .fan_profile = &victus_s_fan_profile_params, > > +}; > > + > > +static const struct hp_wmi_board_params omen_v1_legacy_board_params = { > > + .thermal_profile = &omen_v1_legacy_thermal_params, > > + .fan_profile = &victus_s_fan_profile_params, > > +}; > > + > > +static const struct hp_wmi_board_params omen_v1_no_ec_board_params = { > > + .thermal_profile = &omen_v1_no_ec_thermal_params, > > + .fan_profile = &victus_s_fan_profile_params, > > +}; > > + > > +static const struct hp_wmi_board_params *active_board_params; > > + > > +static const struct thermal_profile_params *hp_wmi_thermal_profile(void) > > +{ > > + if (!active_board_params) > > + return NULL; > > + > > + return active_board_params->thermal_profile; > > +} > > > > /* DMI board names of devices that should use the omen specific path for > > * thermal profiles. > > @@ -187,67 +228,67 @@ static const char * const victus_thermal_profile_boards[] = { > > "8A25", > > }; > > > > -/* DMI Board names of Victus 16-r and Victus 16-s laptops */ > > -static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { > > +/* DMI board-specific feature data for Omen and Victus laptops. */ > > +static const struct dmi_system_id hp_wmi_feature_boards[] __initconst = { > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, > > - .driver_data = (void *)&omen_v1_legacy_thermal_params, > > + .driver_data = (void *)&omen_v1_legacy_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A4D") }, > > - .driver_data = (void *)&omen_v1_legacy_thermal_params, > > + .driver_data = (void *)&omen_v1_legacy_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") }, > > - .driver_data = (void *)&omen_v1_thermal_params, > > + .driver_data = (void *)&omen_v1_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") }, > > - .driver_data = (void *)&victus_s_thermal_params, > > + .driver_data = (void *)&victus_s_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCA") }, > > - .driver_data = (void *)&omen_v1_thermal_params, > > + .driver_data = (void *)&omen_v1_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") }, > > - .driver_data = (void *)&omen_v1_thermal_params, > > + .driver_data = (void *)&omen_v1_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") }, > > - .driver_data = (void *)&victus_s_thermal_params, > > + .driver_data = (void *)&victus_s_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") }, > > - .driver_data = (void *)&victus_s_thermal_params, > > + .driver_data = (void *)&victus_s_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C76") }, > > - .driver_data = (void *)&omen_v1_thermal_params, > > + .driver_data = (void *)&omen_v1_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C77") }, > > - .driver_data = (void *)&omen_v1_thermal_params, > > + .driver_data = (void *)&omen_v1_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") }, > > - .driver_data = (void *)&omen_v1_thermal_params, > > + .driver_data = (void *)&omen_v1_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C99") }, > > - .driver_data = (void *)&victus_s_thermal_params, > > + .driver_data = (void *)&victus_s_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C9C") }, > > - .driver_data = (void *)&victus_s_thermal_params, > > + .driver_data = (void *)&victus_s_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") }, > > - .driver_data = (void *)&victus_s_thermal_params, > > + .driver_data = (void *)&victus_s_board_params, > > }, > > { > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D87") }, > > - .driver_data = (void *)&omen_v1_no_ec_thermal_params, > > + .driver_data = (void *)&omen_v1_no_ec_board_params, > > }, > > {}, > > }; > > @@ -1769,6 +1810,38 @@ static bool is_victus_s_thermal_profile(void) > > return is_victus_s_board; > > } > > > > +static const struct hp_wmi_fan_profile_params *hp_wmi_fan_profile(void) > > +{ > > + if (!active_board_params) > > + return NULL; > > + > > + return active_board_params->fan_profile; > > +} > > + > > +static bool hp_wmi_fan_control_supported(void) > > +{ > > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > > + > > + return params && params->get_fan_speed; > > +} > > + > > +static bool hp_wmi_fan_table_supported(void) > > +{ > > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > > + > > + return params && params->fan_table; > > +} > > + > > +static int hp_wmi_get_active_fan_speed(int fan) > > +{ > > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > > + > > + if (!params || !params->get_fan_speed) > > + return -EOPNOTSUPP; > > + > > + return params->get_fan_speed(fan); > > +} > > + > > static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable, > > bool *ppab_enable, > > u8 *dstate, > > @@ -1854,7 +1927,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > u8 current_dstate, current_gpu_slowdown_temp, tp; > > const struct thermal_profile_params *params; > > > > - params = active_thermal_profile_params; > > + params = hp_wmi_thermal_profile(); > > + if (!params) > > + return -ENODEV; > > + > > if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > > params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > > *profile = active_platform_profile; > > @@ -1866,10 +1942,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > return ret; > > > > /* > > - * We cannot use active_thermal_profile_params here, because boards > > - * like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, but logically > > - * it should have tp == 0x30 || tp == 0x31, as corrected by the Omen > > - * Gaming Hub on windows. Hence accept both of these values. > > + * Boards like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, > > + * but logically it should have tp == 0x30 || tp == 0x31, as > > + * corrected by the Omen Gaming Hub on windows. Hence accept both > > + * of these values. > > */ > > if (tp == victus_s_thermal_params.performance || > > tp == omen_v1_thermal_params.performance) { > > @@ -1904,12 +1980,12 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > > > static int platform_profile_victus_s_set_ec(enum platform_profile_option profile) > > { > > - struct thermal_profile_params *params; > > + const struct thermal_profile_params *params; > > bool gpu_ctgp_enable, gpu_ppab_enable; > > u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */ > > int err, tp; > > > > - params = active_thermal_profile_params; > > + params = hp_wmi_thermal_profile(); > > if (!params) > > return -ENODEV; > > > > @@ -2175,6 +2251,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { > > static int thermal_profile_setup(struct platform_device *device) > > { > > const struct platform_profile_ops *ops; > > + const struct thermal_profile_params *params; > > int err, tp; > > > > if (is_omen_thermal_profile()) { > > @@ -2206,13 +2283,17 @@ static int thermal_profile_setup(struct platform_device *device) > > > > ops = &platform_profile_victus_ops; > > } else if (is_victus_s_thermal_profile()) { > > + params = hp_wmi_thermal_profile(); > > + if (!params) > > + return -ENODEV; > > + > > /* > > * For an unknown EC layout board, platform_profile_victus_s_get_ec(), > > * behaves like a wrapper around active_platform_profile, to avoid using > > * uninitialized data, we default to PLATFORM_PROFILE_BALANCED. > > */ > > - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > > - active_thermal_profile_params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > > + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > > + params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > > active_platform_profile = PLATFORM_PROFILE_BALANCED; > > } else { > > err = platform_profile_victus_s_get_ec(&active_platform_profile); > > @@ -2380,7 +2461,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > > > switch (priv->mode) { > > case PWM_MODE_MAX: > > - if (is_victus_s_thermal_profile()) { > > + if (hp_wmi_fan_control_supported()) { > > ret = hp_wmi_get_fan_count_userdefine_trigger(); > > if (ret < 0) > > return ret; > > @@ -2392,7 +2473,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); > > return 0; > > case PWM_MODE_MANUAL: > > - if (!is_victus_s_thermal_profile()) > > + if (!hp_wmi_fan_control_supported()) > > return -EOPNOTSUPP; > > ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv)); > > if (ret < 0) > > @@ -2401,7 +2482,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); > > return 0; > > case PWM_MODE_AUTO: > > - if (is_victus_s_thermal_profile()) { > > + if (hp_wmi_fan_control_supported()) { > > ret = hp_wmi_get_fan_count_userdefine_trigger(); > > if (ret < 0) > > return ret; > > @@ -2425,12 +2506,12 @@ static umode_t hp_wmi_hwmon_is_visible(const void *data, > > { > > switch (type) { > > case hwmon_pwm: > > - if (attr == hwmon_pwm_input && !is_victus_s_thermal_profile()) > > + if (attr == hwmon_pwm_input && !hp_wmi_fan_control_supported()) > > return 0; > > return 0644; > > case hwmon_fan: > > - if (is_victus_s_thermal_profile()) { > > - if (hp_wmi_get_fan_speed_victus_s(channel) >= 0) > > + if (hp_wmi_fan_control_supported()) { > > + if (hp_wmi_get_active_fan_speed(channel) >= 0) > > return 0444; > > } else { > > if (hp_wmi_get_fan_speed(channel) >= 0) > > @@ -2454,8 +2535,8 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, > > priv = dev_get_drvdata(dev); > > switch (type) { > > case hwmon_fan: > > - if (is_victus_s_thermal_profile()) > > - ret = hp_wmi_get_fan_speed_victus_s(channel); > > + if (hp_wmi_fan_control_supported()) > > + ret = hp_wmi_get_active_fan_speed(channel); > > else > > ret = hp_wmi_get_fan_speed(channel); > > if (ret < 0) > > @@ -2464,10 +2545,10 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, > > return 0; > > case hwmon_pwm: > > if (attr == hwmon_pwm_input) { > > - if (!is_victus_s_thermal_profile()) > > + if (!hp_wmi_fan_control_supported()) > > return -EOPNOTSUPP; > > > > - rpm = hp_wmi_get_fan_speed_victus_s(channel); > > + rpm = hp_wmi_get_active_fan_speed(channel); > > if (rpm < 0) > > return rpm; > > *val = rpm_to_pwm(rpm / 100, priv); > > @@ -2501,7 +2582,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > > switch (type) { > > case hwmon_pwm: > > if (attr == hwmon_pwm_input) { > > - if (!is_victus_s_thermal_profile()) > > + if (!hp_wmi_fan_control_supported()) > > return -EOPNOTSUPP; > > /* PWM input is invalid when not in manual mode */ > > if (priv->mode != PWM_MODE_MANUAL) > > @@ -2518,13 +2599,13 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > > priv->mode = PWM_MODE_MAX; > > return hp_wmi_apply_fan_settings(priv); > > case PWM_MODE_MANUAL: > > - if (!is_victus_s_thermal_profile()) > > + if (!hp_wmi_fan_control_supported()) > > return -EOPNOTSUPP; > > /* > > * When switching to manual mode, set fan speed to > > * current RPM values to ensure a smooth transition. > > */ > > - rpm = hp_wmi_get_fan_speed_victus_s(channel); > > + rpm = hp_wmi_get_active_fan_speed(channel); > > if (rpm < 0) > > return rpm; > > priv->pwm = rpm_to_pwm(rpm / 100, priv); > > @@ -2585,13 +2666,14 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) > > u8 min_rpm, max_rpm; > > u8 cpu_rpm, gpu_rpm, noise_db; > > int gpu_delta, i, num_entries, ret; > > + bool gpu_delta_found = false; > > size_t header_size, entry_size; > > > > /* Default behaviour on hwmon init is automatic mode */ > > priv->mode = PWM_MODE_AUTO; > > > > - /* Bypass all non-Victus S devices */ > > - if (!is_victus_s_thermal_profile()) > > + /* Bypass devices without fan control support. */ > > + if (!hp_wmi_fan_table_supported()) > > return 0; > > > > ret = hp_wmi_perform_query(HPWMI_VICTUS_S_GET_FAN_TABLE_QUERY, > > @@ -2625,12 +2707,15 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) > > min_rpm = cpu_rpm; > > if (cpu_rpm > max_rpm) > > max_rpm = cpu_rpm; > > + if (!gpu_delta_found && gpu_rpm > 0) { > > + gpu_delta = gpu_rpm - cpu_rpm; > > + gpu_delta_found = true; > > + } > > } > > > > - if (min_rpm == U8_MAX || max_rpm == 0) > > + if (min_rpm == U8_MAX || max_rpm == 0 || !gpu_delta_found) > > return -EINVAL; > > > > - gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm; > > priv->min_rpm = min_rpm; > > priv->max_rpm = max_rpm; > > priv->gpu_delta = gpu_delta; > > @@ -2673,24 +2758,25 @@ static int hp_wmi_hwmon_init(void) > > return 0; > > } > > > > -static void __init setup_active_thermal_profile_params(void) > > +static void __init setup_active_board_params(void) > > { > > const struct dmi_system_id *id; > > + const struct thermal_profile_params *params; > > > > - /* > > - * Currently only victus_s devices use the > > - * active_thermal_profile_params > > - */ > > - id = dmi_first_match(victus_s_thermal_profile_boards); > > + id = dmi_first_match(hp_wmi_feature_boards); > > if (id) { > > + active_board_params = id->driver_data; > > + params = hp_wmi_thermal_profile(); > > + if (!params) > > + return; > > + > > /* > > * Marking this boolean is required to ensure that > > * is_victus_s_thermal_profile() behaves like a valid > > * wrapper. > > */ > > is_victus_s_board = true; > > - active_thermal_profile_params = id->driver_data; > > - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { > > + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { > > pr_warn("Unknown EC layout for board %s. Thermal profile readback will be disabled. Please report this to platform-driver-x86@vger.kernel.org\n", > > dmi_get_system_info(DMI_BOARD_NAME)); > > } > > @@ -2725,10 +2811,10 @@ static int __init hp_wmi_init(void) > > } > > > > /* > > - * Setup active board's thermal profile parameters before > > - * starting platform driver probe. > > + * Setup active board feature data before starting platform > > + * driver probe. > > */ > > - setup_active_thermal_profile_params(); > > + setup_active_board_params(); > > err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); > > if (err) > > goto err_unregister_device; > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data 2026-05-21 13:06 ` Radhey Kalra @ 2026-05-21 13:17 ` Ilpo Järvinen 0 siblings, 0 replies; 9+ messages in thread From: Ilpo Järvinen @ 2026-05-21 13:17 UTC (permalink / raw) To: Radhey Kalra; +Cc: platform-driver-x86, krishna.chomal108 [-- Attachment #1: Type: text/plain, Size: 23003 bytes --] On Thu, 21 May 2026, Radhey Kalra wrote: > Hi Ilpo, > > Agreed, that was a mistake. The gpu_delta parsing change does not > logically belong in the board-data refactor. > > I folded it into the preparatory patch while trying to reduce the > series size, but that made the patch less focused. If we're talking about < 25 patches, you should not even think of the series length. Many focused patches is almost always better from reviewer's perspective than a large chunk which mixes things up (it's also used if somebody looks these commits from git history later, smaller changes are just easier to check for correctness). -- i. > I will split it > back out so the series is: > > board-data / fan-control selection refactor > fan-table gpu_delta parsing fix > 8A3D board addition > > Thanks, Radhey > > > On Thu, May 21, 2026 at 6:33 PM Ilpo Järvinen > <ilpo.jarvinen@linux.intel.com> wrote: > > > > On Wed, 20 May 2026, Radhey Kalra wrote: > > > > > Move the Victus S thermal-profile DMI data behind hp_wmi_board_params so > > > board-specific feature data can describe thermal-profile and fan-control > > > support together. > > > > > > Use the active board data for fan-control decisions instead of checking > > > is_victus_s_thermal_profile() in the hwmon path. > > > > > Also derive gpu_delta > > > from the first non-zero GPU RPM row so fan tables whose first GPU RPM is > > > zero still produce valid fan settings. > > > > Unfortunately, moving gpu_delta things from own patch to the refactor > > patch is a step backwards. > > > > Why would it logically belong to this patch?? > > > > -- > > i. > > > > > No fan-control support changes intended for existing boards. Fan tables > > > with an initial zero GPU RPM row now produce a valid GPU delta. > > > > > > Signed-off-by: Radhey Kalra <radheykalra901@gmail.com> > > > --- > > > drivers/platform/x86/hp/hp-wmi.c | 204 ++++++++++++++++++++++--------- > > > 1 file changed, 145 insertions(+), 59 deletions(-) > > > > > > diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c > > > index d1cc6e7..dcfffe6 100644 > > > --- a/drivers/platform/x86/hp/hp-wmi.c > > > +++ b/drivers/platform/x86/hp/hp-wmi.c > > > @@ -133,11 +133,52 @@ static const struct thermal_profile_params omen_v1_no_ec_thermal_params = { > > > .ec_tp_offset = HP_NO_THERMAL_PROFILE_OFFSET, > > > }; > > > > > > -/* > > > - * A generic pointer for the currently-active board's thermal profile > > > - * parameters. > > > - */ > > > -static struct thermal_profile_params *active_thermal_profile_params; > > > +struct hp_wmi_fan_profile_params { > > > + int (*get_fan_speed)(int fan); > > > + bool fan_table; > > > +}; > > > + > > > +struct hp_wmi_board_params { > > > + const struct thermal_profile_params *thermal_profile; > > > + const struct hp_wmi_fan_profile_params *fan_profile; > > > +}; > > > + > > > +static int hp_wmi_get_fan_speed_victus_s(int fan); > > > + > > > +static const struct hp_wmi_fan_profile_params victus_s_fan_profile_params = { > > > + .get_fan_speed = hp_wmi_get_fan_speed_victus_s, > > > + .fan_table = true, > > > +}; > > > + > > > +static const struct hp_wmi_board_params victus_s_board_params = { > > > + .thermal_profile = &victus_s_thermal_params, > > > + .fan_profile = &victus_s_fan_profile_params, > > > +}; > > > + > > > +static const struct hp_wmi_board_params omen_v1_board_params = { > > > + .thermal_profile = &omen_v1_thermal_params, > > > + .fan_profile = &victus_s_fan_profile_params, > > > +}; > > > + > > > +static const struct hp_wmi_board_params omen_v1_legacy_board_params = { > > > + .thermal_profile = &omen_v1_legacy_thermal_params, > > > + .fan_profile = &victus_s_fan_profile_params, > > > +}; > > > + > > > +static const struct hp_wmi_board_params omen_v1_no_ec_board_params = { > > > + .thermal_profile = &omen_v1_no_ec_thermal_params, > > > + .fan_profile = &victus_s_fan_profile_params, > > > +}; > > > + > > > +static const struct hp_wmi_board_params *active_board_params; > > > + > > > +static const struct thermal_profile_params *hp_wmi_thermal_profile(void) > > > +{ > > > + if (!active_board_params) > > > + return NULL; > > > + > > > + return active_board_params->thermal_profile; > > > +} > > > > > > /* DMI board names of devices that should use the omen specific path for > > > * thermal profiles. > > > @@ -187,67 +228,67 @@ static const char * const victus_thermal_profile_boards[] = { > > > "8A25", > > > }; > > > > > > -/* DMI Board names of Victus 16-r and Victus 16-s laptops */ > > > -static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst = { > > > +/* DMI board-specific feature data for Omen and Victus laptops. */ > > > +static const struct dmi_system_id hp_wmi_feature_boards[] __initconst = { > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, > > > - .driver_data = (void *)&omen_v1_legacy_thermal_params, > > > + .driver_data = (void *)&omen_v1_legacy_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A4D") }, > > > - .driver_data = (void *)&omen_v1_legacy_thermal_params, > > > + .driver_data = (void *)&omen_v1_legacy_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BAB") }, > > > - .driver_data = (void *)&omen_v1_thermal_params, > > > + .driver_data = (void *)&omen_v1_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BBE") }, > > > - .driver_data = (void *)&victus_s_thermal_params, > > > + .driver_data = (void *)&victus_s_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCA") }, > > > - .driver_data = (void *)&omen_v1_thermal_params, > > > + .driver_data = (void *)&omen_v1_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BCD") }, > > > - .driver_data = (void *)&omen_v1_thermal_params, > > > + .driver_data = (void *)&omen_v1_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD4") }, > > > - .driver_data = (void *)&victus_s_thermal_params, > > > + .driver_data = (void *)&victus_s_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8BD5") }, > > > - .driver_data = (void *)&victus_s_thermal_params, > > > + .driver_data = (void *)&victus_s_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C76") }, > > > - .driver_data = (void *)&omen_v1_thermal_params, > > > + .driver_data = (void *)&omen_v1_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C77") }, > > > - .driver_data = (void *)&omen_v1_thermal_params, > > > + .driver_data = (void *)&omen_v1_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C78") }, > > > - .driver_data = (void *)&omen_v1_thermal_params, > > > + .driver_data = (void *)&omen_v1_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C99") }, > > > - .driver_data = (void *)&victus_s_thermal_params, > > > + .driver_data = (void *)&victus_s_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8C9C") }, > > > - .driver_data = (void *)&victus_s_thermal_params, > > > + .driver_data = (void *)&victus_s_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D41") }, > > > - .driver_data = (void *)&victus_s_thermal_params, > > > + .driver_data = (void *)&victus_s_board_params, > > > }, > > > { > > > .matches = { DMI_MATCH(DMI_BOARD_NAME, "8D87") }, > > > - .driver_data = (void *)&omen_v1_no_ec_thermal_params, > > > + .driver_data = (void *)&omen_v1_no_ec_board_params, > > > }, > > > {}, > > > }; > > > @@ -1769,6 +1810,38 @@ static bool is_victus_s_thermal_profile(void) > > > return is_victus_s_board; > > > } > > > > > > +static const struct hp_wmi_fan_profile_params *hp_wmi_fan_profile(void) > > > +{ > > > + if (!active_board_params) > > > + return NULL; > > > + > > > + return active_board_params->fan_profile; > > > +} > > > + > > > +static bool hp_wmi_fan_control_supported(void) > > > +{ > > > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > > > + > > > + return params && params->get_fan_speed; > > > +} > > > + > > > +static bool hp_wmi_fan_table_supported(void) > > > +{ > > > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > > > + > > > + return params && params->fan_table; > > > +} > > > + > > > +static int hp_wmi_get_active_fan_speed(int fan) > > > +{ > > > + const struct hp_wmi_fan_profile_params *params = hp_wmi_fan_profile(); > > > + > > > + if (!params || !params->get_fan_speed) > > > + return -EOPNOTSUPP; > > > + > > > + return params->get_fan_speed(fan); > > > +} > > > + > > > static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable, > > > bool *ppab_enable, > > > u8 *dstate, > > > @@ -1854,7 +1927,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > > u8 current_dstate, current_gpu_slowdown_temp, tp; > > > const struct thermal_profile_params *params; > > > > > > - params = active_thermal_profile_params; > > > + params = hp_wmi_thermal_profile(); > > > + if (!params) > > > + return -ENODEV; > > > + > > > if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > > > params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > > > *profile = active_platform_profile; > > > @@ -1866,10 +1942,10 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > > return ret; > > > > > > /* > > > - * We cannot use active_thermal_profile_params here, because boards > > > - * like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, but logically > > > - * it should have tp == 0x30 || tp == 0x31, as corrected by the Omen > > > - * Gaming Hub on windows. Hence accept both of these values. > > > + * Boards like 8C78 have tp == 0x0 || tp == 0x1 after cold boot, > > > + * but logically it should have tp == 0x30 || tp == 0x31, as > > > + * corrected by the Omen Gaming Hub on windows. Hence accept both > > > + * of these values. > > > */ > > > if (tp == victus_s_thermal_params.performance || > > > tp == omen_v1_thermal_params.performance) { > > > @@ -1904,12 +1980,12 @@ static int platform_profile_victus_s_get_ec(enum platform_profile_option *profil > > > > > > static int platform_profile_victus_s_set_ec(enum platform_profile_option profile) > > > { > > > - struct thermal_profile_params *params; > > > + const struct thermal_profile_params *params; > > > bool gpu_ctgp_enable, gpu_ppab_enable; > > > u8 gpu_dstate; /* Test shows 1 = 100%, 2 = 50%, 3 = 25%, 4 = 12.5% */ > > > int err, tp; > > > > > > - params = active_thermal_profile_params; > > > + params = hp_wmi_thermal_profile(); > > > if (!params) > > > return -ENODEV; > > > > > > @@ -2175,6 +2251,7 @@ static const struct platform_profile_ops hp_wmi_platform_profile_ops = { > > > static int thermal_profile_setup(struct platform_device *device) > > > { > > > const struct platform_profile_ops *ops; > > > + const struct thermal_profile_params *params; > > > int err, tp; > > > > > > if (is_omen_thermal_profile()) { > > > @@ -2206,13 +2283,17 @@ static int thermal_profile_setup(struct platform_device *device) > > > > > > ops = &platform_profile_victus_ops; > > > } else if (is_victus_s_thermal_profile()) { > > > + params = hp_wmi_thermal_profile(); > > > + if (!params) > > > + return -ENODEV; > > > + > > > /* > > > * For an unknown EC layout board, platform_profile_victus_s_get_ec(), > > > * behaves like a wrapper around active_platform_profile, to avoid using > > > * uninitialized data, we default to PLATFORM_PROFILE_BALANCED. > > > */ > > > - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > > > - active_thermal_profile_params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > > > + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN || > > > + params->ec_tp_offset == HP_NO_THERMAL_PROFILE_OFFSET) { > > > active_platform_profile = PLATFORM_PROFILE_BALANCED; > > > } else { > > > err = platform_profile_victus_s_get_ec(&active_platform_profile); > > > @@ -2380,7 +2461,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > > > > > switch (priv->mode) { > > > case PWM_MODE_MAX: > > > - if (is_victus_s_thermal_profile()) { > > > + if (hp_wmi_fan_control_supported()) { > > > ret = hp_wmi_get_fan_count_userdefine_trigger(); > > > if (ret < 0) > > > return ret; > > > @@ -2392,7 +2473,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > > secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); > > > return 0; > > > case PWM_MODE_MANUAL: > > > - if (!is_victus_s_thermal_profile()) > > > + if (!hp_wmi_fan_control_supported()) > > > return -EOPNOTSUPP; > > > ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv)); > > > if (ret < 0) > > > @@ -2401,7 +2482,7 @@ static int hp_wmi_apply_fan_settings(struct hp_wmi_hwmon_priv *priv) > > > secs_to_jiffies(KEEP_ALIVE_DELAY_SECS)); > > > return 0; > > > case PWM_MODE_AUTO: > > > - if (is_victus_s_thermal_profile()) { > > > + if (hp_wmi_fan_control_supported()) { > > > ret = hp_wmi_get_fan_count_userdefine_trigger(); > > > if (ret < 0) > > > return ret; > > > @@ -2425,12 +2506,12 @@ static umode_t hp_wmi_hwmon_is_visible(const void *data, > > > { > > > switch (type) { > > > case hwmon_pwm: > > > - if (attr == hwmon_pwm_input && !is_victus_s_thermal_profile()) > > > + if (attr == hwmon_pwm_input && !hp_wmi_fan_control_supported()) > > > return 0; > > > return 0644; > > > case hwmon_fan: > > > - if (is_victus_s_thermal_profile()) { > > > - if (hp_wmi_get_fan_speed_victus_s(channel) >= 0) > > > + if (hp_wmi_fan_control_supported()) { > > > + if (hp_wmi_get_active_fan_speed(channel) >= 0) > > > return 0444; > > > } else { > > > if (hp_wmi_get_fan_speed(channel) >= 0) > > > @@ -2454,8 +2535,8 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, > > > priv = dev_get_drvdata(dev); > > > switch (type) { > > > case hwmon_fan: > > > - if (is_victus_s_thermal_profile()) > > > - ret = hp_wmi_get_fan_speed_victus_s(channel); > > > + if (hp_wmi_fan_control_supported()) > > > + ret = hp_wmi_get_active_fan_speed(channel); > > > else > > > ret = hp_wmi_get_fan_speed(channel); > > > if (ret < 0) > > > @@ -2464,10 +2545,10 @@ static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, > > > return 0; > > > case hwmon_pwm: > > > if (attr == hwmon_pwm_input) { > > > - if (!is_victus_s_thermal_profile()) > > > + if (!hp_wmi_fan_control_supported()) > > > return -EOPNOTSUPP; > > > > > > - rpm = hp_wmi_get_fan_speed_victus_s(channel); > > > + rpm = hp_wmi_get_active_fan_speed(channel); > > > if (rpm < 0) > > > return rpm; > > > *val = rpm_to_pwm(rpm / 100, priv); > > > @@ -2501,7 +2582,7 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > > > switch (type) { > > > case hwmon_pwm: > > > if (attr == hwmon_pwm_input) { > > > - if (!is_victus_s_thermal_profile()) > > > + if (!hp_wmi_fan_control_supported()) > > > return -EOPNOTSUPP; > > > /* PWM input is invalid when not in manual mode */ > > > if (priv->mode != PWM_MODE_MANUAL) > > > @@ -2518,13 +2599,13 @@ static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type, > > > priv->mode = PWM_MODE_MAX; > > > return hp_wmi_apply_fan_settings(priv); > > > case PWM_MODE_MANUAL: > > > - if (!is_victus_s_thermal_profile()) > > > + if (!hp_wmi_fan_control_supported()) > > > return -EOPNOTSUPP; > > > /* > > > * When switching to manual mode, set fan speed to > > > * current RPM values to ensure a smooth transition. > > > */ > > > - rpm = hp_wmi_get_fan_speed_victus_s(channel); > > > + rpm = hp_wmi_get_active_fan_speed(channel); > > > if (rpm < 0) > > > return rpm; > > > priv->pwm = rpm_to_pwm(rpm / 100, priv); > > > @@ -2585,13 +2666,14 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) > > > u8 min_rpm, max_rpm; > > > u8 cpu_rpm, gpu_rpm, noise_db; > > > int gpu_delta, i, num_entries, ret; > > > + bool gpu_delta_found = false; > > > size_t header_size, entry_size; > > > > > > /* Default behaviour on hwmon init is automatic mode */ > > > priv->mode = PWM_MODE_AUTO; > > > > > > - /* Bypass all non-Victus S devices */ > > > - if (!is_victus_s_thermal_profile()) > > > + /* Bypass devices without fan control support. */ > > > + if (!hp_wmi_fan_table_supported()) > > > return 0; > > > > > > ret = hp_wmi_perform_query(HPWMI_VICTUS_S_GET_FAN_TABLE_QUERY, > > > @@ -2625,12 +2707,15 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv) > > > min_rpm = cpu_rpm; > > > if (cpu_rpm > max_rpm) > > > max_rpm = cpu_rpm; > > > + if (!gpu_delta_found && gpu_rpm > 0) { > > > + gpu_delta = gpu_rpm - cpu_rpm; > > > + gpu_delta_found = true; > > > + } > > > } > > > > > > - if (min_rpm == U8_MAX || max_rpm == 0) > > > + if (min_rpm == U8_MAX || max_rpm == 0 || !gpu_delta_found) > > > return -EINVAL; > > > > > > - gpu_delta = fan_table->entries[0].gpu_rpm - fan_table->entries[0].cpu_rpm; > > > priv->min_rpm = min_rpm; > > > priv->max_rpm = max_rpm; > > > priv->gpu_delta = gpu_delta; > > > @@ -2673,24 +2758,25 @@ static int hp_wmi_hwmon_init(void) > > > return 0; > > > } > > > > > > -static void __init setup_active_thermal_profile_params(void) > > > +static void __init setup_active_board_params(void) > > > { > > > const struct dmi_system_id *id; > > > + const struct thermal_profile_params *params; > > > > > > - /* > > > - * Currently only victus_s devices use the > > > - * active_thermal_profile_params > > > - */ > > > - id = dmi_first_match(victus_s_thermal_profile_boards); > > > + id = dmi_first_match(hp_wmi_feature_boards); > > > if (id) { > > > + active_board_params = id->driver_data; > > > + params = hp_wmi_thermal_profile(); > > > + if (!params) > > > + return; > > > + > > > /* > > > * Marking this boolean is required to ensure that > > > * is_victus_s_thermal_profile() behaves like a valid > > > * wrapper. > > > */ > > > is_victus_s_board = true; > > > - active_thermal_profile_params = id->driver_data; > > > - if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { > > > + if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) { > > > pr_warn("Unknown EC layout for board %s. Thermal profile readback will be disabled. Please report this to platform-driver-x86@vger.kernel.org\n", > > > dmi_get_system_info(DMI_BOARD_NAME)); > > > } > > > @@ -2725,10 +2811,10 @@ static int __init hp_wmi_init(void) > > > } > > > > > > /* > > > - * Setup active board's thermal profile parameters before > > > - * starting platform driver probe. > > > + * Setup active board feature data before starting platform > > > + * driver probe. > > > */ > > > - setup_active_thermal_profile_params(); > > > + setup_active_board_params(); > > > err = platform_driver_probe(&hp_wmi_driver, hp_wmi_bios_setup); > > > if (err) > > > goto err_unregister_device; > > > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v5 2/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control 2026-05-20 14:07 [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra 2026-05-20 14:07 ` [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data Radhey Kalra @ 2026-05-20 14:07 ` Radhey Kalra 2026-05-20 17:50 ` [PATCH v5 0/2] " Krishna Chomal 2 siblings, 0 replies; 9+ messages in thread From: Radhey Kalra @ 2026-05-20 14:07 UTC (permalink / raw) To: platform-driver-x86 Cc: ilpo.jarvinen, hdegoede, krishna.chomal108, Radhey Kalra HP Victus 15-fb0xxx board 8A3D exposes the Victus fan table and accepts the existing Victus fan-speed WMI control path. Add it as a fan-control-only board so the hwmon PWM interface is enabled without forcing Victus S thermal-profile handling on this model. Tested on a Victus by HP Gaming Laptop 15-fb0xxx, board 8A3D, BIOS F.22. The fan table query succeeded and returned rows including cpu=23/gpu=0 followed by cpu=24/gpu=22. With 8A3D enabled in the fan-control path, pwm1 and pwm1_enable were exposed through hwmon. Signed-off-by: Radhey Kalra <radheykalra901@gmail.com> --- drivers/platform/x86/hp/hp-wmi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index dcfffe6..f463823 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -170,6 +170,10 @@ static const struct hp_wmi_board_params omen_v1_no_ec_board_params = { .fan_profile = &victus_s_fan_profile_params, }; +static const struct hp_wmi_board_params victus_8a3d_board_params = { + .fan_profile = &victus_s_fan_profile_params, +}; + static const struct hp_wmi_board_params *active_board_params; static const struct thermal_profile_params *hp_wmi_thermal_profile(void) @@ -230,6 +234,10 @@ static const char * const victus_thermal_profile_boards[] = { /* DMI board-specific feature data for Omen and Victus laptops. */ static const struct dmi_system_id hp_wmi_feature_boards[] __initconst = { + { + .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A3D") }, + .driver_data = (void *)&victus_8a3d_board_params, + }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "8A44") }, .driver_data = (void *)&omen_v1_legacy_board_params, -- 2.54.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control 2026-05-20 14:07 [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra 2026-05-20 14:07 ` [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data Radhey Kalra 2026-05-20 14:07 ` [PATCH v5 2/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra @ 2026-05-20 17:50 ` Krishna Chomal 2026-05-21 12:49 ` Radhey Kalra 2 siblings, 1 reply; 9+ messages in thread From: Krishna Chomal @ 2026-05-20 17:50 UTC (permalink / raw) To: Radhey Kalra; +Cc: platform-driver-x86, ilpo.jarvinen, hdegoede On Wed, May 20, 2026 at 07:37:46PM +0530, Radhey Kalra wrote: >Hi, > >This is a smaller v5 split for the Victus 15-fb0xxx fan-control change. >Patch 1 prepares the hp-wmi board data and hwmon fan-control selection >so fan support can be described independently from Victus S thermal >profiles. Patch 2 adds fan-control support for Victus 15-fb0xxx board >8A3D. > I am sure I must be missing something but I don't see why this isn't just a DMI table addition? I understand that you want to refactor the structs to decouple fan control from platform profile so that you can just use fan control feature and ignore platform profile, but I don't understand why that is done? If I use victus_8a3d_board_params quirk on my device (8C78), it effectively removes platform profile support, why is this choice made? >Based on platform-drivers-x86/for-next commit: >165e81354eefd5551358112773f24027aac59d5a > >Tested on a Victus by HP Gaming Laptop 15-fb0xxx, board 8A3D, BIOS >F.22. With the series applied, pwm1 and pwm1_enable are exposed and >the EC-layout warning is not emitted for 8A3D. > >Radhey Kalra (2): > platform/x86: hp-wmi: Prepare Victus fan control board data > platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control > > drivers/platform/x86/hp/hp-wmi.c | 212 ++++++++++++++++++++++--------- > 1 file changed, 153 insertions(+), 59 deletions(-) > >--- >Changes in v5: >- Reduce the series to two patches: one preparatory board-data/hwmon > patch and one focused 8A3D enablement patch. >- Drop the active_thermal_profile_params global and dereference the > thermal-profile data through active_board_params. >- Wrap the setup comment added in the preparatory patch to stay under > 80 columns. > >Changes in v4: >- Split v3 into two no-functional-changes-intended refactors, one > fan-table parsing fix, and one 8A3D support patch. >- Rebase on platform-drivers-x86/for-next commit 165e81354eefd555. >- Move revision notes to the cover letter. > >Changes in v3: >- Rebase on platform-drivers-x86/for-next commit 165e81354eefd555. >- Keep the v2 board-data approach and 8A3D fan-control-only handling. > >Changes in v2: >- Use real name in Signed-off-by. >- Replace the ad-hoc fan-control DMI table with board data in > .driver_data. >- Keep 8A3D fan-control-only instead of enabling Victus S thermal > profiles. >- Use the fixed fan-table parser path and derive gpu_delta from the > first non-zero GPU row. > >-- >2.54.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control 2026-05-20 17:50 ` [PATCH v5 0/2] " Krishna Chomal @ 2026-05-21 12:49 ` Radhey Kalra 2026-05-21 13:36 ` Krishna Chomal 0 siblings, 1 reply; 9+ messages in thread From: Radhey Kalra @ 2026-05-21 12:49 UTC (permalink / raw) To: Krishna Chomal; +Cc: platform-driver-x86, ilpo.jarvinen Hi Krishna, I tested the current platform-profile behavior on 8A3D more carefully. The board already exposes the generic hp-wmi platform-profile choices: cool quiet balanced performance Writes to all choices succeed and read back correctly, and I do not see hp_wmi errors in dmesg. However, under full CPU load I could not confirm that these profiles change CPU power behavior. Across quiet/balanced/performance/cool, CPU frequency stayed around 3.27 GHz and the reported PPT stayed around 33 W. Fan RPM rose somewhat later in the test, but the system was also heating up, so I cannot separate that from normal firmware thermal fan ramping. So I should not claim that platform-profile policy is meaningfully validated for 8A3D. What I have verified is that the Victus fan-control path works. That is why I avoided a plain addition to victus_s_thermal_profile_boards: it would move 8A3D from the existing generic platform-profile path to the Victus S-specific platform-profile path, which I have not verified on this board. Thanks, Radhey On Wed, May 20, 2026 at 11:20 PM Krishna Chomal <krishna.chomal108@gmail.com> wrote: > > On Wed, May 20, 2026 at 07:37:46PM +0530, Radhey Kalra wrote: > >Hi, > > > >This is a smaller v5 split for the Victus 15-fb0xxx fan-control change. > >Patch 1 prepares the hp-wmi board data and hwmon fan-control selection > >so fan support can be described independently from Victus S thermal > >profiles. Patch 2 adds fan-control support for Victus 15-fb0xxx board > >8A3D. > > > > I am sure I must be missing something but I don't see why this isn't > just a DMI table addition? > > I understand that you want to refactor the structs to decouple fan control > from platform profile so that you can just use fan control feature and > ignore platform profile, but I don't understand why that is done? > > If I use victus_8a3d_board_params quirk on my device (8C78), it effectively > removes platform profile support, why is this choice made? > > >Based on platform-drivers-x86/for-next commit: > >165e81354eefd5551358112773f24027aac59d5a > > > >Tested on a Victus by HP Gaming Laptop 15-fb0xxx, board 8A3D, BIOS > >F.22. With the series applied, pwm1 and pwm1_enable are exposed and > >the EC-layout warning is not emitted for 8A3D. > > > >Radhey Kalra (2): > > platform/x86: hp-wmi: Prepare Victus fan control board data > > platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control > > > > drivers/platform/x86/hp/hp-wmi.c | 212 ++++++++++++++++++++++--------- > > 1 file changed, 153 insertions(+), 59 deletions(-) > > > >--- > >Changes in v5: > >- Reduce the series to two patches: one preparatory board-data/hwmon > > patch and one focused 8A3D enablement patch. > >- Drop the active_thermal_profile_params global and dereference the > > thermal-profile data through active_board_params. > >- Wrap the setup comment added in the preparatory patch to stay under > > 80 columns. > > > >Changes in v4: > >- Split v3 into two no-functional-changes-intended refactors, one > > fan-table parsing fix, and one 8A3D support patch. > >- Rebase on platform-drivers-x86/for-next commit 165e81354eefd555. > >- Move revision notes to the cover letter. > > > >Changes in v3: > >- Rebase on platform-drivers-x86/for-next commit 165e81354eefd555. > >- Keep the v2 board-data approach and 8A3D fan-control-only handling. > > > >Changes in v2: > >- Use real name in Signed-off-by. > >- Replace the ad-hoc fan-control DMI table with board data in > > .driver_data. > >- Keep 8A3D fan-control-only instead of enabling Victus S thermal > > profiles. > >- Use the fixed fan-table parser path and derive gpu_delta from the > > first non-zero GPU row. > > > >-- > >2.54.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control 2026-05-21 12:49 ` Radhey Kalra @ 2026-05-21 13:36 ` Krishna Chomal 0 siblings, 0 replies; 9+ messages in thread From: Krishna Chomal @ 2026-05-21 13:36 UTC (permalink / raw) To: Radhey Kalra; +Cc: platform-driver-x86, ilpo.jarvinen On Thu, May 21, 2026 at 06:19:48PM +0530, Radhey Kalra wrote: >Hi Krishna, > >I tested the current platform-profile behavior on 8A3D more carefully. > >The board already exposes the generic hp-wmi platform-profile choices: > >cool quiet balanced performance > >Writes to all choices succeed and read back correctly, and I do not >see hp_wmi errors in dmesg. > >However, under full CPU load I could not confirm that these profiles >change CPU power behavior. Across quiet/balanced/performance/cool, CPU >frequency stayed around 3.27 GHz and the reported PPT stayed around 33 >W. Fan RPM rose somewhat later in the test, but the system was also >heating up, so I cannot separate that from normal firmware thermal fan >ramping. You are right. Because your board is not registered in any list, so it goes to a fallback route and registers quiet/balanced/performance/cool. Changes to platform profile are handled through this chain: hp_wmi_platform_profile_set -> thermal_profile_set -> hp_wmi_perform_query(HPWMI_THERMAL_PROFILE_QUERY) For my device, when I selected victus_8a3d_board_params quirk, the driver tried to use this query HPWMI_THERMAL_PROFILE_QUERY which failed and caused the driver to not load. In you case, it looks like the query does not return an error. However, not returning an error does not necessarily imply that it is working correctly, which can be further confirmed when you mention that changing power modes has no physical effect on the system. >So I should not claim that platform-profile policy is meaningfully >validated for 8A3D. What I have verified is that the Victus >fan-control path works. > >That is why I avoided a plain addition to >victus_s_thermal_profile_boards: it would move 8A3D from the existing >generic platform-profile path to the Victus S-specific >platform-profile path, which I have not verified on this board. > I think your board does need Victus-S-specific platform-profile path because the old/legacy queries did not have any effect on the system. >Thanks, Radhey > [...] ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-05-21 13:36 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-20 14:07 [PATCH v5 0/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra 2026-05-20 14:07 ` [PATCH v5 1/2] platform/x86: hp-wmi: Prepare Victus fan control board data Radhey Kalra 2026-05-21 13:02 ` Ilpo Järvinen 2026-05-21 13:06 ` Radhey Kalra 2026-05-21 13:17 ` Ilpo Järvinen 2026-05-20 14:07 ` [PATCH v5 2/2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control Radhey Kalra 2026-05-20 17:50 ` [PATCH v5 0/2] " Krishna Chomal 2026-05-21 12:49 ` Radhey Kalra 2026-05-21 13:36 ` 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.