summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c103
1 files changed, 96 insertions, 7 deletions
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 31c6cca6ec34..304d9ac63c8a 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -46,9 +46,13 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45E9-BE91-3D44E2C707E4");
#define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
#define HPWMI_BIOS_GUID "5FB7F034-2C63-45E9-BE91-3D44E2C707E4"
-#define HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET 0x62
-#define HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET 0x63
-#define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95
+enum hp_ec_offsets {
+ HP_EC_OFFSET_UNKNOWN = 0x00,
+ HP_VICTUS_S_EC_THERMAL_PROFILE_OFFSET = 0x59,
+ HP_OMEN_EC_THERMAL_PROFILE_FLAGS_OFFSET = 0x62,
+ HP_OMEN_EC_THERMAL_PROFILE_TIMER_OFFSET = 0x63,
+ HP_OMEN_EC_THERMAL_PROFILE_OFFSET = 0x95,
+};
#define HP_FAN_SPEED_AUTOMATIC 0x00
#define HP_POWER_LIMIT_DEFAULT 0x00
@@ -94,22 +98,26 @@ enum hp_thermal_profile {
HP_THERMAL_PROFILE_QUIET = 0x03,
};
+
struct thermal_profile_params {
u8 performance;
u8 balanced;
u8 low_power;
+ u8 ec_tp_offset;
};
static const struct thermal_profile_params victus_s_thermal_params = {
.performance = HP_VICTUS_S_THERMAL_PROFILE_PERFORMANCE,
.balanced = HP_VICTUS_S_THERMAL_PROFILE_DEFAULT,
.low_power = HP_VICTUS_S_THERMAL_PROFILE_DEFAULT,
+ .ec_tp_offset = HP_EC_OFFSET_UNKNOWN,
};
static const struct thermal_profile_params omen_v1_thermal_params = {
.performance = HP_OMEN_V1_THERMAL_PROFILE_PERFORMANCE,
.balanced = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
.low_power = HP_OMEN_V1_THERMAL_PROFILE_DEFAULT,
+ .ec_tp_offset = HP_VICTUS_S_EC_THERMAL_PROFILE_OFFSET,
};
/*
@@ -1785,6 +1793,60 @@ static int victus_s_set_cpu_pl1_pl2(u8 pl1, u8 pl2)
return ret;
}
+static int platform_profile_victus_s_get_ec(enum platform_profile_option *profile)
+{
+ int ret = 0;
+ bool current_ctgp_state, current_ppab_state;
+ u8 current_dstate, current_gpu_slowdown_temp, tp;
+ const struct thermal_profile_params *params;
+
+ params = active_thermal_profile_params;
+ if (params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) {
+ *profile = active_platform_profile;
+ return 0;
+ }
+
+ ret = ec_read(params->ec_tp_offset, &tp);
+ if (ret)
+ 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.
+ */
+ if (tp == victus_s_thermal_params.performance ||
+ tp == omen_v1_thermal_params.performance) {
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ } else if (tp == victus_s_thermal_params.balanced ||
+ tp == omen_v1_thermal_params.balanced) {
+ /*
+ * Since both PLATFORM_PROFILE_LOW_POWER and
+ * PLATFORM_PROFILE_BALANCED share the same thermal profile
+ * parameter value, hence to differentiate between them, we
+ * query the GPU CTGP and PPAB states and compare based off of
+ * that.
+ */
+ ret = victus_s_gpu_thermal_profile_get(&current_ctgp_state,
+ &current_ppab_state,
+ &current_dstate,
+ &current_gpu_slowdown_temp);
+ if (ret < 0)
+ return ret;
+ if (current_ctgp_state == 0 && current_ppab_state == 0)
+ *profile = PLATFORM_PROFILE_LOW_POWER;
+ else if (current_ctgp_state == 0 && current_ppab_state == 1)
+ *profile = PLATFORM_PROFILE_BALANCED;
+ else
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int platform_profile_victus_s_set_ec(enum platform_profile_option profile)
{
struct thermal_profile_params *params;
@@ -1952,6 +2014,7 @@ static int victus_s_powersource_event(struct notifier_block *nb,
void *data)
{
struct acpi_bus_event *event_entry = data;
+ enum platform_profile_option actual_profile;
int err;
if (strcmp(event_entry->device_class, ACPI_AC_CLASS) != 0)
@@ -1959,6 +2022,17 @@ static int victus_s_powersource_event(struct notifier_block *nb,
pr_debug("Received power source device event\n");
+ guard(mutex)(&active_platform_profile_lock);
+ err = platform_profile_victus_s_get_ec(&actual_profile);
+ if (err < 0) {
+ /*
+ * Although we failed to get the current platform profile, we
+ * still want the other event consumers to process it.
+ */
+ pr_warn("Failed to read current platform profile (%d)\n", err);
+ return NOTIFY_DONE;
+ }
+
/*
* Switching to battery power source while Performance mode is active
* needs manual triggering of CPU power limits. Same goes when switching
@@ -1967,7 +2041,7 @@ static int victus_s_powersource_event(struct notifier_block *nb,
* Seen on HP 16-s1034nf (board 8C9C) with F.11 and F.13 BIOS versions.
*/
- if (active_platform_profile == PLATFORM_PROFILE_PERFORMANCE) {
+ if (actual_profile == PLATFORM_PROFILE_PERFORMANCE) {
pr_debug("Triggering CPU PL1/PL2 actualization\n");
err = victus_s_set_cpu_pl1_pl2(HP_POWER_LIMIT_DEFAULT,
HP_POWER_LIMIT_DEFAULT);
@@ -2078,11 +2152,22 @@ static int thermal_profile_setup(struct platform_device *device)
ops = &platform_profile_victus_ops;
} else if (is_victus_s_thermal_profile()) {
/*
- * Being unable to retrieve laptop's current thermal profile,
- * during this setup, we set it to Balanced by default.
+ * 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.
*/
- active_platform_profile = PLATFORM_PROFILE_BALANCED;
+ if (active_thermal_profile_params->ec_tp_offset == HP_EC_OFFSET_UNKNOWN) {
+ active_platform_profile = PLATFORM_PROFILE_BALANCED;
+ } else {
+ err = platform_profile_victus_s_get_ec(&active_platform_profile);
+ if (err < 0)
+ return err;
+ }
+ /*
+ * call thermal profile write command to ensure that the
+ * firmware correctly sets the OEM variables
+ */
err = platform_profile_victus_s_set_ec(active_platform_profile);
if (err < 0)
return err;
@@ -2505,6 +2590,10 @@ static void __init setup_active_thermal_profile_params(void)
*/
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));
+ }
}
}