Skip to content

Commit 251e4b7

Browse files
Antheas KapenekakisKyleGospo
authored andcommitted
[FROM-ML] platform/x86: msi-wmi-platform: Add platform profile through shift mode
MSI's version of platform profile in Windows is called shift mode. Introduce it here, and add a profile handler to it. It has 5 modes: sport, comfort, green, eco, and user. Confusingly, for the Claw, MSI only uses sport, green, and eco, where they correspond to performance, balanced, and low-power. Therefore, comfort is mapped to balanced-performance, and user to custom. Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
1 parent c549695 commit 251e4b7

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

drivers/platform/x86/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,7 @@ config MSI_WMI_PLATFORM
570570
depends on ACPI_WMI
571571
depends on DMI
572572
depends on HWMON
573+
select ACPI_PLATFORM_PROFILE
573574
help
574575
Say Y here if you want to have support for WMI-based platform features
575576
like fan sensor access on MSI machines.

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

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/dmi.h>
1818
#include <linux/errno.h>
1919
#include <linux/fixp-arith.h>
20+
#include <linux/platform_profile.h>
2021
#include <linux/hwmon.h>
2122
#include <linux/hwmon-sysfs.h>
2223
#include <linux/kernel.h>
@@ -63,6 +64,16 @@
6364
#define MSI_PLATFORM_AP_FAN_FLAGS_OFFSET 1
6465
#define MSI_PLATFORM_AP_ENABLE_FAN_TABLES BIT(7)
6566

67+
/* Get_Data() and Set_Data() Shift Mode Register */
68+
#define MSI_PLATFORM_SHIFT_ADDR 0xd2
69+
#define MSI_PLATFORM_SHIFT_DISABLE BIT(7)
70+
#define MSI_PLATFORM_SHIFT_ENABLE (BIT(7) | BIT(6))
71+
#define MSI_PLATFORM_SHIFT_SPORT (MSI_PLATFORM_SHIFT_ENABLE + 4)
72+
#define MSI_PLATFORM_SHIFT_COMFORT (MSI_PLATFORM_SHIFT_ENABLE + 0)
73+
#define MSI_PLATFORM_SHIFT_GREEN (MSI_PLATFORM_SHIFT_ENABLE + 1)
74+
#define MSI_PLATFORM_SHIFT_ECO (MSI_PLATFORM_SHIFT_ENABLE + 2)
75+
#define MSI_PLATFORM_SHIFT_USER (MSI_PLATFORM_SHIFT_ENABLE + 3)
76+
6677
static bool force;
6778
module_param_unsafe(force, bool, 0);
6879
MODULE_PARM_DESC(force, "Force loading without checking for supported WMI interface versions");
@@ -100,12 +111,14 @@ enum msi_wmi_platform_method {
100111
};
101112

102113
struct msi_wmi_platform_quirk {
114+
bool shift_mode; /* Shift mode is supported */
103115
};
104116

105117
struct msi_wmi_platform_data {
106118
struct wmi_device *wdev;
107119
struct msi_wmi_platform_quirk *quirks;
108120
struct mutex wmi_lock; /* Necessary when calling WMI methods */
121+
struct device *ppdev;
109122
};
110123

111124
struct msi_wmi_platform_debugfs_data {
@@ -150,8 +163,10 @@ static const char * const msi_wmi_platform_debugfs_names[] = {
150163

151164
static struct msi_wmi_platform_quirk quirk_default = {};
152165
static struct msi_wmi_platform_quirk quirk_gen1 = {
166+
.shift_mode = true
153167
};
154168
static struct msi_wmi_platform_quirk quirk_gen2 = {
169+
.shift_mode = true
155170
};
156171

157172
static const struct dmi_system_id msi_quirks[] = {
@@ -561,6 +576,90 @@ static const struct hwmon_chip_info msi_wmi_platform_chip_info = {
561576
.info = msi_wmi_platform_info,
562577
};
563578

579+
static int msi_wmi_platform_profile_probe(void *drvdata, unsigned long *choices)
580+
{
581+
set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
582+
set_bit(PLATFORM_PROFILE_BALANCED, choices);
583+
set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
584+
set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
585+
return 0;
586+
}
587+
588+
static int msi_wmi_platform_profile_get(struct device *dev,
589+
enum platform_profile_option *profile)
590+
{
591+
struct msi_wmi_platform_data *data = dev_get_drvdata(dev);
592+
int ret;
593+
594+
u8 buffer[32] = { };
595+
596+
buffer[0] = MSI_PLATFORM_SHIFT_ADDR;
597+
598+
ret = msi_wmi_platform_query(data, MSI_PLATFORM_GET_DATA, buffer, sizeof(buffer));
599+
if (ret < 0)
600+
return ret;
601+
602+
if (buffer[0] != 1)
603+
return -EINVAL;
604+
605+
switch (buffer[1]) {
606+
case MSI_PLATFORM_SHIFT_SPORT:
607+
*profile = PLATFORM_PROFILE_PERFORMANCE;
608+
return 0;
609+
case MSI_PLATFORM_SHIFT_COMFORT:
610+
*profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
611+
return 0;
612+
case MSI_PLATFORM_SHIFT_GREEN:
613+
*profile = PLATFORM_PROFILE_BALANCED;
614+
return 0;
615+
case MSI_PLATFORM_SHIFT_ECO:
616+
*profile = PLATFORM_PROFILE_LOW_POWER;
617+
return 0;
618+
case MSI_PLATFORM_SHIFT_USER:
619+
*profile = PLATFORM_PROFILE_CUSTOM;
620+
return 0;
621+
default:
622+
return -EINVAL;
623+
}
624+
}
625+
626+
static int msi_wmi_platform_profile_set(struct device *dev,
627+
enum platform_profile_option profile)
628+
{
629+
struct msi_wmi_platform_data *data = dev_get_drvdata(dev);
630+
u8 buffer[32] = { };
631+
632+
buffer[0] = MSI_PLATFORM_SHIFT_ADDR;
633+
634+
switch (profile) {
635+
case PLATFORM_PROFILE_PERFORMANCE:
636+
buffer[1] = MSI_PLATFORM_SHIFT_SPORT;
637+
break;
638+
case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
639+
buffer[1] = MSI_PLATFORM_SHIFT_COMFORT;
640+
break;
641+
case PLATFORM_PROFILE_BALANCED:
642+
buffer[1] = MSI_PLATFORM_SHIFT_GREEN;
643+
break;
644+
case PLATFORM_PROFILE_LOW_POWER:
645+
buffer[1] = MSI_PLATFORM_SHIFT_ECO;
646+
break;
647+
case PLATFORM_PROFILE_CUSTOM:
648+
buffer[1] = MSI_PLATFORM_SHIFT_USER;
649+
break;
650+
default:
651+
return -EINVAL;
652+
}
653+
654+
return msi_wmi_platform_query(data, MSI_PLATFORM_SET_DATA, buffer, sizeof(buffer));
655+
}
656+
657+
static const struct platform_profile_ops msi_wmi_platform_profile_ops = {
658+
.probe = msi_wmi_platform_profile_probe,
659+
.profile_get = msi_wmi_platform_profile_get,
660+
.profile_set = msi_wmi_platform_profile_set,
661+
};
662+
564663
static ssize_t msi_wmi_platform_debugfs_write(struct file *fp, const char __user *input,
565664
size_t length, loff_t *offset)
566665
{
@@ -742,6 +841,22 @@ static int msi_wmi_platform_init(struct msi_wmi_platform_data *data)
742841
return 0;
743842
}
744843

844+
static int msi_wmi_platform_profile_setup(struct msi_wmi_platform_data *data)
845+
{
846+
int err;
847+
848+
if (!data->quirks->shift_mode)
849+
return 0;
850+
851+
data->ppdev = devm_platform_profile_register(
852+
&data->wdev->dev, "msi-wmi-platform", data,
853+
&msi_wmi_platform_profile_ops);
854+
if (err)
855+
return err;
856+
857+
return PTR_ERR_OR_ZERO(data->ppdev);
858+
}
859+
745860
static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
746861
{
747862
struct msi_wmi_platform_data *data;
@@ -775,6 +890,8 @@ static int msi_wmi_platform_probe(struct wmi_device *wdev, const void *context)
775890

776891
msi_wmi_platform_debugfs_init(data);
777892

893+
msi_wmi_platform_profile_setup(data);
894+
778895
return msi_wmi_platform_hwmon_init(data);
779896
}
780897

0 commit comments

Comments
 (0)