Skip to content

Commit 7df7483

Browse files
Antheas KapenekakisKyleGospo
authored andcommitted
[FROM-ML] platform/x86: msi-wmi-platform: Restore fan curves on PWM disable and unload
MSI software is a bit weird in that even when the manual fan curve is disabled, the fan speed is still somewhat affected by the curve. So we have to restore the fan curves on unload and PWM disable, as it is done in Windows. Suggested-by: Armin Wolf <W_Armin@gmx.de> Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
1 parent 3925507 commit 7df7483

1 file changed

Lines changed: 122 additions & 1 deletion

File tree

drivers/platform/x86/msi-wmi-platform.c

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,25 @@ struct msi_wmi_platform_quirk {
123123
bool shift_mode; /* Shift mode is supported */
124124
bool charge_threshold; /* Charge threshold is supported */
125125
bool dual_fans; /* For devices with two hwmon fans */
126+
bool restore_curves; /* Restore factory curves on unload */
126127
int pl_min; /* Minimum PLx value */
127128
int pl1_max; /* Maximum PL1 value */
128129
int pl2_max; /* Maximum PL2 value */
129130
};
130131

132+
struct msi_wmi_platform_factory_curves {
133+
u8 cpu_fan_table[32];
134+
u8 gpu_fan_table[32];
135+
u8 cpu_temp_table[32];
136+
u8 gpu_temp_table[32];
137+
};
138+
131139
struct msi_wmi_platform_data {
132140
struct wmi_device *wdev;
133141
struct msi_wmi_platform_quirk *quirks;
134142
struct mutex wmi_lock; /* Necessary when calling WMI methods */
135143
struct device *ppdev;
144+
struct msi_wmi_platform_factory_curves factory_curves;
136145
struct acpi_battery_hook battery_hook;
137146
struct device *fw_attrs_dev;
138147
struct kset *fw_attrs_kset;
@@ -219,6 +228,7 @@ static struct msi_wmi_platform_quirk quirk_gen1 = {
219228
.shift_mode = true,
220229
.charge_threshold = true,
221230
.dual_fans = true,
231+
.restore_curves = true,
222232
.pl_min = 8,
223233
.pl1_max = 43,
224234
.pl2_max = 45
@@ -227,6 +237,7 @@ static struct msi_wmi_platform_quirk quirk_gen2 = {
227237
.shift_mode = true,
228238
.charge_threshold = true,
229239
.dual_fans = true,
240+
.restore_curves = true,
230241
.pl_min = 8,
231242
.pl1_max = 30,
232243
.pl2_max = 37
@@ -507,6 +518,94 @@ static struct attribute *msi_wmi_platform_hwmon_attrs[] = {
507518
};
508519
ATTRIBUTE_GROUPS(msi_wmi_platform_hwmon);
509520

521+
static int msi_wmi_platform_curves_save(struct msi_wmi_platform_data *data)
522+
{
523+
int ret;
524+
525+
data->factory_curves.cpu_fan_table[0] =
526+
MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE;
527+
ret = msi_wmi_platform_query_unlocked(
528+
data, MSI_PLATFORM_GET_FAN,
529+
data->factory_curves.cpu_fan_table,
530+
sizeof(data->factory_curves.cpu_fan_table));
531+
if (ret < 0)
532+
return ret;
533+
data->factory_curves.cpu_fan_table[0] =
534+
MSI_PLATFORM_FAN_SUBFEATURE_CPU_FAN_TABLE;
535+
536+
data->factory_curves.gpu_fan_table[0] =
537+
MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE;
538+
ret = msi_wmi_platform_query_unlocked(
539+
data, MSI_PLATFORM_GET_FAN,
540+
data->factory_curves.gpu_fan_table,
541+
sizeof(data->factory_curves.gpu_fan_table));
542+
if (ret < 0)
543+
return ret;
544+
data->factory_curves.gpu_fan_table[0] =
545+
MSI_PLATFORM_FAN_SUBFEATURE_GPU_FAN_TABLE;
546+
547+
data->factory_curves.cpu_temp_table[0] =
548+
MSI_PLATFORM_FAN_SUBFEATURE_CPU_TEMP_TABLE;
549+
ret = msi_wmi_platform_query_unlocked(
550+
data, MSI_PLATFORM_GET_TEMPERATURE,
551+
data->factory_curves.cpu_temp_table,
552+
sizeof(data->factory_curves.cpu_temp_table));
553+
if (ret < 0)
554+
return ret;
555+
data->factory_curves.cpu_temp_table[0] =
556+
MSI_PLATFORM_FAN_SUBFEATURE_CPU_TEMP_TABLE;
557+
558+
data->factory_curves.gpu_temp_table[0] =
559+
MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE;
560+
ret = msi_wmi_platform_query_unlocked(
561+
data, MSI_PLATFORM_GET_TEMPERATURE,
562+
data->factory_curves.gpu_temp_table,
563+
sizeof(data->factory_curves.gpu_temp_table));
564+
if (ret < 0)
565+
return ret;
566+
data->factory_curves.gpu_temp_table[0] =
567+
MSI_PLATFORM_FAN_SUBFEATURE_GPU_TEMP_TABLE;
568+
569+
return 0;
570+
}
571+
572+
static int msi_wmi_platform_curves_load(struct msi_wmi_platform_data *data)
573+
{
574+
u8 buffer[32] = { };
575+
int ret;
576+
577+
memcpy(buffer, data->factory_curves.cpu_fan_table,
578+
sizeof(data->factory_curves.cpu_fan_table));
579+
ret = msi_wmi_platform_query_unlocked(data, MSI_PLATFORM_SET_FAN,
580+
buffer, sizeof(buffer));
581+
if (ret < 0)
582+
return ret;
583+
584+
memcpy(buffer, data->factory_curves.gpu_fan_table,
585+
sizeof(data->factory_curves.gpu_fan_table));
586+
ret = msi_wmi_platform_query_unlocked(data, MSI_PLATFORM_SET_FAN,
587+
buffer, sizeof(buffer));
588+
if (ret < 0)
589+
return ret;
590+
591+
memcpy(buffer, data->factory_curves.cpu_temp_table,
592+
sizeof(data->factory_curves.cpu_temp_table));
593+
ret = msi_wmi_platform_query_unlocked(
594+
data, MSI_PLATFORM_SET_TEMPERATURE, buffer, sizeof(buffer));
595+
if (ret < 0)
596+
return ret;
597+
598+
memcpy(buffer, data->factory_curves.gpu_temp_table,
599+
sizeof(data->factory_curves.gpu_temp_table));
600+
ret = msi_wmi_platform_query_unlocked(
601+
data, MSI_PLATFORM_SET_TEMPERATURE, buffer, sizeof(buffer));
602+
if (ret < 0)
603+
return ret;
604+
605+
return 0;
606+
}
607+
608+
510609
static umode_t msi_wmi_platform_is_visible(const void *drvdata, enum hwmon_sensor_types type,
511610
u32 attr, int channel)
512611
{
@@ -603,9 +702,19 @@ static int msi_wmi_platform_write(struct device *dev, enum hwmon_sensor_types ty
603702
return -EINVAL;
604703
}
605704

606-
return msi_wmi_platform_query_unlocked(
705+
ret = msi_wmi_platform_query_unlocked(
607706
data, MSI_PLATFORM_SET_AP, buffer,
608707
sizeof(buffer));
708+
if (ret < 0)
709+
return ret;
710+
711+
if (val == 2 && data->quirks->restore_curves) {
712+
ret = msi_wmi_platform_curves_load(data);
713+
if (ret < 0)
714+
return ret;
715+
}
716+
717+
return 0;
609718
default:
610719
return -EOPNOTSUPP;
611720
}
@@ -1373,6 +1482,13 @@ static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
13731482

13741483
msi_wmi_platform_profile_setup(data);
13751484

1485+
if (data->quirks->restore_curves) {
1486+
guard(mutex)(&data->wmi_lock);
1487+
ret = msi_wmi_platform_curves_save(data);
1488+
if (ret < 0)
1489+
return ret;
1490+
}
1491+
13761492
return msi_wmi_platform_hwmon_init(data);
13771493
}
13781494

@@ -1382,6 +1498,11 @@ static void msi_wmi_platform_remove(struct wmi_device *wdev)
13821498

13831499
if (data->quirks->charge_threshold)
13841500
battery_hook_unregister(&data->battery_hook);
1501+
1502+
if (data->quirks->restore_curves) {
1503+
guard(mutex)(&data->wmi_lock);
1504+
msi_wmi_platform_curves_load(data);
1505+
}
13851506
}
13861507

13871508
static const struct wmi_device_id msi_wmi_platform_id_table[] = {

0 commit comments

Comments
 (0)