Some of the new ASUS laptops like TUF Gaming FA706II do not set bit indicating presence of method. Instead, just the fan speed is returned. Implement ugly way to check if for the cpu fan. It seems that in other TUF models SPEC version and SFUN are the same. So it checks these two values, then tries to read fan speed, and last, checks that fan speed is in adequate range. Signed-off-by: Vasiliy Kupriakov <rublag-ns@xxxxxxxxx> --- drivers/platform/x86/asus-wmi.c | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 71559d429ba0..82505307ec17 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1309,6 +1309,38 @@ static bool asus_wmi_has_agfn_fan(struct asus_wmi *asus) || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT))); } +/* + * Check for fan availability. Some of the newer laptops don't set + * the ASUS_WMI_DSTS_PRESENCE_BIT. This is ad hoc solution. It compares + * few attributes to constants found in DSDT, then tries to read fan speed + */ +static bool asus_wmi_has_fan(struct asus_wmi *asus, u32 dev_id) +{ + int status; + u32 value; + + /* + * On multiple TUF laptops with similar DSDT interface + * for fans, these two values are as following. + * On some older laptops, they are different. + */ + if (asus->spec != 0x80001 || !(asus->sfun & 0x400000)) + return false; + + status = asus_wmi_get_devstate(asus, dev_id, &value); + if (status != 0 || value == ASUS_WMI_UNSUPPORTED_METHOD) + return false; + + /* + * Check that fan RPM is in adequate range (0 <= RPM <= 10000) + * Note that firmware returns RPM/100. + */ + if (value > 100) + return false; + + return true; +} + static int asus_fan_set_auto(struct asus_wmi *asus) { int status; @@ -1613,6 +1645,8 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) asus->fan_type = FAN_TYPE_SPEC83; else if (asus_wmi_has_agfn_fan(asus)) asus->fan_type = FAN_TYPE_AGFN; + else if (asus_wmi_has_fan(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL)) + asus->fan_type = FAN_TYPE_SPEC83; if (asus->fan_type == FAN_TYPE_NONE) return -ENODEV; -- 2.28.0