platform/x86: thinkpad_acpi: Fix profile mode display in AMT mode
authorMark Pearson <mpearson-lenovo@squebb.ca>
Thu, 12 Jan 2023 22:12:28 +0000 (17:12 -0500)
committerHans de Goede <hdegoede@redhat.com>
Fri, 13 Jan 2023 10:40:30 +0000 (11:40 +0100)
Recently AMT mode was enabled (somewhat unexpectedly) on the Lenovo
Z13 platform. The FW is advertising it is available and the driver tries
to use it - unfortunately it reports the profile mode incorrectly.

Note, there is also some extra work needed to enable the dynamic aspect
of AMT support that I will be following up with; but more testing is
needed first. This patch just fixes things so the profiles are reported
correctly.

Link: https://gitlab.freedesktop.org/hadess/power-profiles-daemon/-/issues/115
Fixes: 46dcbc61b739 ("platform/x86: thinkpad-acpi: Add support for automatic mode transitions")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Link: https://lore.kernel.org/r/20230112221228.490946-1-mpearson-lenovo@squebb.ca
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
drivers/platform/x86/thinkpad_acpi.c

index 1195293b22fddf6065d7f7428b3e98547b86ef3b..a95946800ae9d3f947acbf752f69afdcd3114210 100644 (file)
@@ -10311,9 +10311,11 @@ static DEFINE_MUTEX(dytc_mutex);
 static int dytc_capabilities;
 static bool dytc_mmc_get_available;
 
-static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
+static int convert_dytc_to_profile(int funcmode, int dytcmode,
+               enum platform_profile_option *profile)
 {
-       if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
+       switch (funcmode) {
+       case DYTC_FUNCTION_MMC:
                switch (dytcmode) {
                case DYTC_MODE_MMC_LOWPOWER:
                        *profile = PLATFORM_PROFILE_LOW_POWER;
@@ -10329,8 +10331,7 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p
                        return -EINVAL;
                }
                return 0;
-       }
-       if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
+       case DYTC_FUNCTION_PSC:
                switch (dytcmode) {
                case DYTC_MODE_PSC_LOWPOWER:
                        *profile = PLATFORM_PROFILE_LOW_POWER;
@@ -10344,6 +10345,14 @@ static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *p
                default: /* Unknown mode */
                        return -EINVAL;
                }
+               return 0;
+       case DYTC_FUNCTION_AMT:
+               /* For now return balanced. It's the closest we have to 'auto' */
+               *profile =  PLATFORM_PROFILE_BALANCED;
+               return 0;
+       default:
+               /* Unknown function */
+               return -EOPNOTSUPP;
        }
        return 0;
 }
@@ -10492,6 +10501,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
                err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output);
                if (err)
                        goto unlock;
+
                /* system supports AMT, activate it when on balanced */
                if (dytc_capabilities & BIT(DYTC_FC_AMT))
                        dytc_control_amt(profile == PLATFORM_PROFILE_BALANCED);
@@ -10507,7 +10517,7 @@ static void dytc_profile_refresh(void)
 {
        enum platform_profile_option profile;
        int output, err = 0;
-       int perfmode;
+       int perfmode, funcmode;
 
        mutex_lock(&dytc_mutex);
        if (dytc_capabilities & BIT(DYTC_FC_MMC)) {
@@ -10522,8 +10532,9 @@ static void dytc_profile_refresh(void)
        if (err)
                return;
 
+       funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF;
        perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
-       convert_dytc_to_profile(perfmode, &profile);
+       convert_dytc_to_profile(funcmode, perfmode, &profile);
        if (profile != dytc_current_profile) {
                dytc_current_profile = profile;
                platform_profile_notify();