* Re: [PATCH] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control
2026-05-07 10:13 [PATCH] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control jR4dh3y
@ 2026-05-07 11:20 ` Ilpo Järvinen
2026-05-07 19:15 ` Krishna Chomal
2026-05-16 9:05 ` [PATCH v2] " Radhey Kalra
2 siblings, 0 replies; 5+ messages in thread
From: Ilpo Järvinen @ 2026-05-07 11:20 UTC (permalink / raw)
To: jR4dh3y, Krishna Chomal; +Cc: platform-driver-x86, hdegoede
On Thu, 7 May 2026, jR4dh3y wrote:
> HP Victus 15-fb0xxx board 8A3D supports the same WMI fan speed
> set command used by the Victus manual fan control path, but it is
> not a Victus S thermal-profile board.
>
> Enable the hwmon PWM manual fan interface for this board without
> adding it to the Victus S thermal profile DMI table. This preserves
> the existing generic platform-profile choices on this machine.
>
> The board does not expose a Victus S fan table, so use the RPM limits
> validated on hardware: CPU fan 2600-5800 RPM, GPU fan about 300 RPM
> higher.
>
> Compile-tested against 7.0.3-1-cachyos-bore-lto. The WMI fan-speed
> set path was validated on a Victus by HP Gaming Laptop 15-fb0xxx with
> board 8A3D and BIOS F.22.
>
> Signed-off-by: jR4dh3y <radheykalra901@gmail.com>
Hi,
The sign off should be based on your real name (sorry, no nicknames or
like).
> ---
> drivers/platform/x86/hp/hp-wmi.c | 56 +++++++++++++++++++++++++-------
> 1 file changed, 45 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
> index 304d9ac..b2a6d50 100644
> --- a/drivers/platform/x86/hp/hp-wmi.c
> +++ b/drivers/platform/x86/hp/hp-wmi.c
> @@ -204,6 +204,11 @@ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst
> {},
> };
>
> +/* DMI Board names of Victus laptops with the Victus fan-control WMI calls. */
> +static const char * const victus_fan_control_boards[] = {
> + "8A3D", /* Victus by HP Gaming Laptop 15-fb0xxx */
> +};
> +
> static bool is_victus_s_board;
>
> enum hp_wmi_radio {
> @@ -1715,6 +1720,22 @@ static bool is_victus_s_thermal_profile(void)
> return is_victus_s_board;
> }
>
> +static bool is_victus_fan_control(void)
> +{
> + const char *board_name;
> +
> + if (is_victus_s_thermal_profile())
> + return true;
> +
> + board_name = dmi_get_system_info(DMI_BOARD_NAME);
> + if (!board_name)
> + return false;
> +
> + return match_string(victus_fan_control_boards,
> + ARRAY_SIZE(victus_fan_control_boards),
> + board_name) >= 0;
> +}
Instead of piling up more if()s and dmi checks everywhere, the approach
current used for victus_s_thermal_profile_boards should be extended to
cover a wider set of driver features and models including this one. The
model specific differences should be (mostly) handled by what is stored
into the struct in .driver_data.
If such an extension seems impossible for some reason, I might reconsider
but it needs to be explored first.
> +
> static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable,
> bool *ppab_enable,
> u8 *dstate,
> @@ -2324,7 +2345,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 (is_victus_fan_control())
> hp_wmi_get_fan_count_userdefine_trigger();
> ret = hp_wmi_fan_speed_max_set(1);
> if (ret < 0)
> @@ -2333,7 +2354,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 (!is_victus_fan_control())
> return -EOPNOTSUPP;
> ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv));
> if (ret < 0)
> @@ -2342,7 +2363,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 (is_victus_fan_control()) {
> hp_wmi_get_fan_count_userdefine_trigger();
> ret = hp_wmi_fan_speed_max_reset(priv);
> } else {
> @@ -2366,7 +2387,7 @@ 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 && !is_victus_fan_control())
> return 0;
> return 0644;
> case hwmon_fan:
> @@ -2404,10 +2425,13 @@ 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 (!is_victus_fan_control())
> return -EOPNOTSUPP;
>
> - rpm = hp_wmi_get_fan_speed_victus_s(channel);
> + if (is_victus_s_thermal_profile())
> + rpm = hp_wmi_get_fan_speed_victus_s(channel);
> + else
> + rpm = hp_wmi_get_fan_speed(channel);
Structure held in .driver_data should somehow tell which of these function
to call or perhaps just store the function pointer (in which case NULL
would imply -EOPNOTSUPP).
> if (rpm < 0)
> return rpm;
> *val = rpm_to_pwm(rpm / 100, priv);
> @@ -2438,7 +2462,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 (!is_victus_fan_control())
> return -EOPNOTSUPP;
> /* PWM input is invalid when not in manual mode */
> if (priv->mode != PWM_MODE_MANUAL)
> @@ -2455,13 +2479,16 @@ 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 (!is_victus_fan_control())
> 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);
> + if (is_victus_s_thermal_profile())
> + rpm = hp_wmi_get_fan_speed_victus_s(channel);
> + else
> + rpm = hp_wmi_get_fan_speed(channel);
> if (rpm < 0)
> return rpm;
> priv->pwm = rpm_to_pwm(rpm / 100, priv);
> @@ -2519,9 +2546,16 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
> /* 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 the Victus fan-control WMI calls. */
> + if (!is_victus_fan_control())
> + return 0;
> +
> + if (!is_victus_s_thermal_profile()) {
> + priv->min_rpm = 26;
> + priv->max_rpm = 58;
> + priv->gpu_delta = 3;
These should come from information stored into driver_data, not be
hardcoded into code like this (if we really cannot get them from HW).
> return 0;
> + }
>
> ret = hp_wmi_perform_query(HPWMI_VICTUS_S_GET_FAN_TABLE_QUERY,
> HPWMI_GM, &fan_data, 4, sizeof(fan_data));
>
--
i.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control
2026-05-07 10:13 [PATCH] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control jR4dh3y
2026-05-07 11:20 ` Ilpo Järvinen
@ 2026-05-07 19:15 ` Krishna Chomal
2026-05-07 20:13 ` Radhey Kalra
2026-05-16 9:05 ` [PATCH v2] " Radhey Kalra
2 siblings, 1 reply; 5+ messages in thread
From: Krishna Chomal @ 2026-05-07 19:15 UTC (permalink / raw)
To: jR4dh3y; +Cc: platform-driver-x86, ilpo.jarvinen, hdegoede
Hi,
On Thu, May 07, 2026 at 03:43:44PM +0530, jR4dh3y wrote:
>HP Victus 15-fb0xxx board 8A3D supports the same WMI fan speed
>set command used by the Victus manual fan control path, but it is
>not a Victus S thermal-profile board.
>
I wanted to clarify that the names in this driver are currently a bit
misleading since victus_s_thermal_profile_boards[] contains both Victus
and Omen devices. The main idea is that, devices which support fan
control should go in victus_s_thermal_profile_boards[].
>Enable the hwmon PWM manual fan interface for this board without
>adding it to the Victus S thermal profile DMI table. This preserves
>the existing generic platform-profile choices on this machine.
>
>The board does not expose a Victus S fan table, so use the RPM limits
>validated on hardware: CPU fan 2600-5800 RPM, GPU fan about 300 RPM
>higher.
>
This is really interesting because as per my understanding the OGH
software on Windows derives the fan curve for all fan-control supporting
devices via WMI calls. Can you explain why it "does not expose a Victus S
fan table"? Is it a WMI call failure or issue in parsing the table data?
NOTE: There is a known regression [1] causing a failure in parsing
the fan table so you should build against mainline 7.1-rc1 at least, or
manually cherry-pick 9d317a54e46d ("platform/x86: hp-wmi: fix fan table
parsing") into your tree.
[1] https://lore.kernel.org/all/CABd86uaQY9-ZSU-_PHKtZZyWnDFHLEsuaM+NBV5nOLWA+YSX7A@mail.gmail.com
>Compile-tested against 7.0.3-1-cachyos-bore-lto. The WMI fan-speed
>set path was validated on a Victus by HP Gaming Laptop 15-fb0xxx with
>board 8A3D and BIOS F.22.
>
>Signed-off-by: jR4dh3y <radheykalra901@gmail.com>
>---
> drivers/platform/x86/hp/hp-wmi.c | 56 +++++++++++++++++++++++++-------
> 1 file changed, 45 insertions(+), 11 deletions(-)
>
>diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
>index 304d9ac..b2a6d50 100644
>--- a/drivers/platform/x86/hp/hp-wmi.c
>+++ b/drivers/platform/x86/hp/hp-wmi.c
>@@ -204,6 +204,11 @@ static const struct dmi_system_id victus_s_thermal_profile_boards[] __initconst
> {},
> };
>
>+/* DMI Board names of Victus laptops with the Victus fan-control WMI calls. */
>+static const char * const victus_fan_control_boards[] = {
>+ "8A3D", /* Victus by HP Gaming Laptop 15-fb0xxx */
>+};
>+
> static bool is_victus_s_board;
>
> enum hp_wmi_radio {
>@@ -1715,6 +1720,22 @@ static bool is_victus_s_thermal_profile(void)
> return is_victus_s_board;
> }
>
>+static bool is_victus_fan_control(void)
>+{
>+ const char *board_name;
>+
>+ if (is_victus_s_thermal_profile())
>+ return true;
>+
>+ board_name = dmi_get_system_info(DMI_BOARD_NAME);
>+ if (!board_name)
>+ return false;
>+
>+ return match_string(victus_fan_control_boards,
>+ ARRAY_SIZE(victus_fan_control_boards),
>+ board_name) >= 0;
>+}
>+
> static int victus_s_gpu_thermal_profile_get(bool *ctgp_enable,
> bool *ppab_enable,
> u8 *dstate,
>@@ -2324,7 +2345,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 (is_victus_fan_control())
> hp_wmi_get_fan_count_userdefine_trigger();
> ret = hp_wmi_fan_speed_max_set(1);
> if (ret < 0)
>@@ -2333,7 +2354,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 (!is_victus_fan_control())
> return -EOPNOTSUPP;
> ret = hp_wmi_fan_speed_set(priv, pwm_to_rpm(priv->pwm, priv));
> if (ret < 0)
>@@ -2342,7 +2363,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 (is_victus_fan_control()) {
> hp_wmi_get_fan_count_userdefine_trigger();
> ret = hp_wmi_fan_speed_max_reset(priv);
> } else {
>@@ -2366,7 +2387,7 @@ 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 && !is_victus_fan_control())
> return 0;
> return 0644;
> case hwmon_fan:
>@@ -2404,10 +2425,13 @@ 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 (!is_victus_fan_control())
> return -EOPNOTSUPP;
>
>- rpm = hp_wmi_get_fan_speed_victus_s(channel);
>+ if (is_victus_s_thermal_profile())
>+ rpm = hp_wmi_get_fan_speed_victus_s(channel);
>+ else
>+ rpm = hp_wmi_get_fan_speed(channel);
> if (rpm < 0)
> return rpm;
> *val = rpm_to_pwm(rpm / 100, priv);
>@@ -2438,7 +2462,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 (!is_victus_fan_control())
> return -EOPNOTSUPP;
> /* PWM input is invalid when not in manual mode */
> if (priv->mode != PWM_MODE_MANUAL)
>@@ -2455,13 +2479,16 @@ 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 (!is_victus_fan_control())
> 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);
>+ if (is_victus_s_thermal_profile())
>+ rpm = hp_wmi_get_fan_speed_victus_s(channel);
>+ else
>+ rpm = hp_wmi_get_fan_speed(channel);
> if (rpm < 0)
> return rpm;
> priv->pwm = rpm_to_pwm(rpm / 100, priv);
>@@ -2519,9 +2546,16 @@ static int hp_wmi_setup_fan_settings(struct hp_wmi_hwmon_priv *priv)
> /* 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 the Victus fan-control WMI calls. */
>+ if (!is_victus_fan_control())
>+ return 0;
>+
>+ if (!is_victus_s_thermal_profile()) {
>+ priv->min_rpm = 26;
>+ priv->max_rpm = 58;
>+ priv->gpu_delta = 3;
> return 0;
>+ }
>
> ret = hp_wmi_perform_query(HPWMI_VICTUS_S_GET_FAN_TABLE_QUERY,
> HPWMI_GM, &fan_data, 4, sizeof(fan_data));
>--
>2.54.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control
2026-05-07 10:13 [PATCH] platform/x86: hp-wmi: Add Victus 15-fb0xxx fan control jR4dh3y
2026-05-07 11:20 ` Ilpo Järvinen
2026-05-07 19:15 ` Krishna Chomal
@ 2026-05-16 9:05 ` Radhey Kalra
2 siblings, 0 replies; 5+ messages in thread
From: Radhey Kalra @ 2026-05-16 9:05 UTC (permalink / raw)
To: platform-driver-x86; +Cc: ilpo.jarvinen, krishna.chomal108, hansg, 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.
Extend the DMI .driver_data from thermal-profile-only parameters to board
parameters containing thermal-profile and fan-control data. Existing table
entries keep both thermal and fan-control data, while 8A3D only selects
the fan-control profile.
The 8A3D fan table starts with a valid CPU row whose GPU RPM field is
zero. Derive gpu_delta from the first row with non-zero GPU RPM instead of
always using row 0.
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>
---
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.
drivers/platform/x86/hp/hp-wmi.c | 199 +++++++++++++++++++++----------
1 file changed, 137 insertions(+), 62 deletions(-)
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 6950bec..7435484 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -133,11 +133,50 @@ 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;
+static const 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 victus_8a3d_board_params = {
+ .fan_profile = &victus_s_fan_profile_params,
+};
+
+static const struct hp_wmi_board_params *active_board_params;
/* DMI board names of devices that should use the omen specific path for
* thermal profiles.
@@ -187,71 +226,75 @@ 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, "8A3D") },
+ .driver_data = (void *)&victus_8a3d_board_params,
+ },
{
.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, "8BC2") },
- .driver_data = (void *)&omen_v1_thermal_params,
+ .driver_data = (void *)&omen_v1_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 *)&omen_v1_no_ec_thermal_params,
+ .driver_data = (void *)&omen_v1_no_ec_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,
},
{},
};
@@ -1773,6 +1816,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,
@@ -1908,7 +1983,7 @@ 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;
@@ -2384,7 +2459,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;
@@ -2396,7 +2471,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)
@@ -2405,7 +2480,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;
@@ -2429,12 +2504,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)
@@ -2458,8 +2533,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)
@@ -2468,10 +2543,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);
@@ -2505,7 +2580,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)
@@ -2522,13 +2597,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);
@@ -2589,13 +2664,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,
@@ -2629,12 +2705,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;
@@ -2677,26 +2756,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;
- /*
- * 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) {
- /*
- * 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) {
- 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));
+ active_board_params = id->driver_data;
+ active_thermal_profile_params = active_board_params->thermal_profile;
+ if (active_thermal_profile_params) {
+ /*
+ * Marking this boolean is required to ensure that
+ * is_victus_s_thermal_profile() behaves like a valid
+ * wrapper.
+ */
+ is_victus_s_board = true;
+ if (active_thermal_profile_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));
+ }
}
}
}
@@ -2728,11 +2806,8 @@ static int __init hp_wmi_init(void)
goto err_destroy_input;
}
- /*
- * Setup active board's thermal profile parameters before
- * starting platform driver probe.
- */
- setup_active_thermal_profile_params();
+ /* Setup active board feature data before starting platform driver probe. */
+ 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] 5+ messages in thread