Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/x86: acer-wmi: Fix setting of fan behavior

After studying the linuwu_sense driver
(https://github.com/0x7375646F/Linuwu-Sense) i was able to understand
the meaning of the SetGamingFanBehavior() WMI method:

- the first 16-bit are a bitmap of all fans affected by a fan behavior
change request.

- the next 8 bits contain four fan mode fields (2-bit), each being
associated with a bit inside the fan bitmap.

There are three fan modes: auto, turbo and custom.

Use this newfound knowledge to fix the turbo fan handling by setting
the correct bits before calling SetGamingFanBehavior(). Also check
the result of the WMI method call and return an error should the ACPI
firmware signal failure.

Reviewed-by: Kurt Borja <kuurtb@gmail.com>
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20251016180008.465593-2-W_Armin@gmx.de
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Armin Wolf and committed by
Ilpo Järvinen
d8e8362b 1c72d9c3

+51 -22
+51 -22
drivers/platform/x86/acer-wmi.c
··· 68 68 #define ACER_WMID_SET_GAMING_LED_METHODID 2 69 69 #define ACER_WMID_GET_GAMING_LED_METHODID 4 70 70 #define ACER_WMID_GET_GAMING_SYS_INFO_METHODID 5 71 - #define ACER_WMID_SET_GAMING_FAN_BEHAVIOR 14 71 + #define ACER_WMID_SET_GAMING_FAN_BEHAVIOR_METHODID 14 72 72 #define ACER_WMID_SET_GAMING_MISC_SETTING_METHODID 22 73 73 #define ACER_WMID_GET_GAMING_MISC_SETTING_METHODID 23 74 + 75 + #define ACER_GAMING_FAN_BEHAVIOR_CPU BIT(0) 76 + #define ACER_GAMING_FAN_BEHAVIOR_GPU BIT(3) 77 + 78 + #define ACER_GAMING_FAN_BEHAVIOR_STATUS_MASK GENMASK_ULL(7, 0) 79 + #define ACER_GAMING_FAN_BEHAVIOR_ID_MASK GENMASK_ULL(15, 0) 80 + #define ACER_GAMING_FAN_BEHAVIOR_SET_CPU_MODE_MASK GENMASK(17, 16) 81 + #define ACER_GAMING_FAN_BEHAVIOR_SET_GPU_MODE_MASK GENMASK(23, 22) 74 82 75 83 #define ACER_GAMING_MISC_SETTING_STATUS_MASK GENMASK_ULL(7, 0) 76 84 #define ACER_GAMING_MISC_SETTING_INDEX_MASK GENMASK_ULL(7, 0) ··· 127 119 ACER_WMID_SENSOR_EXTERNAL_TEMPERATURE_2 = 0x03, 128 120 ACER_WMID_SENSOR_GPU_FAN_SPEED = 0x06, 129 121 ACER_WMID_SENSOR_GPU_TEMPERATURE = 0x0A, 122 + }; 123 + 124 + enum acer_wmi_gaming_fan_mode { 125 + ACER_WMID_FAN_MODE_AUTO = 0x01, 126 + ACER_WMID_FAN_MODE_TURBO = 0x02, 127 + ACER_WMID_FAN_MODE_CUSTOM = 0x03, 130 128 }; 131 129 132 130 enum acer_wmi_predator_v4_oc { ··· 1577 1563 case ACER_CAP_TURBO_LED: 1578 1564 method_id = ACER_WMID_SET_GAMING_LED_METHODID; 1579 1565 break; 1580 - case ACER_CAP_TURBO_FAN: 1581 - method_id = ACER_WMID_SET_GAMING_FAN_BEHAVIOR; 1582 - break; 1583 1566 default: 1584 1567 return AE_BAD_PARAMETER; 1585 1568 } ··· 1627 1616 return 0; 1628 1617 } 1629 1618 1630 - static void WMID_gaming_set_fan_mode(u8 fan_mode) 1619 + static int WMID_gaming_set_fan_behavior(u16 fan_bitmap, enum acer_wmi_gaming_fan_mode mode) 1631 1620 { 1632 - /* fan_mode = 1 is used for auto, fan_mode = 2 used for turbo*/ 1633 - u64 gpu_fan_config1 = 0, gpu_fan_config2 = 0; 1634 - int i; 1621 + acpi_status status; 1622 + u64 input = 0; 1623 + u64 result; 1624 + 1625 + input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_ID_MASK, fan_bitmap); 1626 + 1627 + if (fan_bitmap & ACER_GAMING_FAN_BEHAVIOR_CPU) 1628 + input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_SET_CPU_MODE_MASK, mode); 1629 + 1630 + if (fan_bitmap & ACER_GAMING_FAN_BEHAVIOR_GPU) 1631 + input |= FIELD_PREP(ACER_GAMING_FAN_BEHAVIOR_SET_GPU_MODE_MASK, mode); 1632 + 1633 + status = WMI_gaming_execute_u64(ACER_WMID_SET_GAMING_FAN_BEHAVIOR_METHODID, input, 1634 + &result); 1635 + if (ACPI_FAILURE(status)) 1636 + return -EIO; 1637 + 1638 + /* The return status must be zero for the operation to have succeeded */ 1639 + if (FIELD_GET(ACER_GAMING_FAN_BEHAVIOR_STATUS_MASK, result)) 1640 + return -EIO; 1641 + 1642 + return 0; 1643 + } 1644 + 1645 + static void WMID_gaming_set_fan_mode(enum acer_wmi_gaming_fan_mode mode) 1646 + { 1647 + u16 fan_bitmap = 0; 1635 1648 1636 1649 if (quirks->cpu_fans > 0) 1637 - gpu_fan_config2 |= 1; 1638 - for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i) 1639 - gpu_fan_config2 |= 1 << (i + 1); 1640 - for (i = 0; i < quirks->gpu_fans; ++i) 1641 - gpu_fan_config2 |= 1 << (i + 3); 1642 - if (quirks->cpu_fans > 0) 1643 - gpu_fan_config1 |= fan_mode; 1644 - for (i = 0; i < (quirks->cpu_fans + quirks->gpu_fans); ++i) 1645 - gpu_fan_config1 |= fan_mode << (2 * i + 2); 1646 - for (i = 0; i < quirks->gpu_fans; ++i) 1647 - gpu_fan_config1 |= fan_mode << (2 * i + 6); 1648 - WMID_gaming_set_u64(gpu_fan_config2 | gpu_fan_config1 << 16, ACER_CAP_TURBO_FAN); 1650 + fan_bitmap |= ACER_GAMING_FAN_BEHAVIOR_CPU; 1651 + 1652 + if (quirks->gpu_fans > 0) 1653 + fan_bitmap |= ACER_GAMING_FAN_BEHAVIOR_GPU; 1654 + 1655 + WMID_gaming_set_fan_behavior(fan_bitmap, mode); 1649 1656 } 1650 1657 1651 1658 static int WMID_gaming_set_misc_setting(enum acer_wmi_gaming_misc_setting setting, u8 value) ··· 1950 1921 WMID_gaming_set_u64(0x1, ACER_CAP_TURBO_LED); 1951 1922 1952 1923 /* Set FAN mode to auto */ 1953 - WMID_gaming_set_fan_mode(0x1); 1924 + WMID_gaming_set_fan_mode(ACER_WMID_FAN_MODE_AUTO); 1954 1925 1955 1926 /* Set OC to normal */ 1956 1927 if (has_cap(ACER_CAP_TURBO_OC)) { ··· 1964 1935 WMID_gaming_set_u64(0x10001, ACER_CAP_TURBO_LED); 1965 1936 1966 1937 /* Set FAN mode to turbo */ 1967 - WMID_gaming_set_fan_mode(0x2); 1938 + WMID_gaming_set_fan_mode(ACER_WMID_FAN_MODE_TURBO); 1968 1939 1969 1940 /* Set OC to turbo mode */ 1970 1941 if (has_cap(ACER_CAP_TURBO_OC)) {