platform/x86: asus-wmi: Support the GPU fan on TUF laptops

Add support for TUF laptops which have the ability to control
the GPU fan. This will show as a second fan in hwmon, and has
the ability to run as boost (fullspeed), or auto.

Signed-off-by: Luke D. Jones <luke@ljones.dev>
Link: https://lore.kernel.org/r/20220826004210.356534-3-luke@ljones.dev
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Luke D. Jones 2022-08-26 12:42:10 +12:00 committed by Hans de Goede
parent 601eb4c8e1
commit 12ff4c803d
2 changed files with 72 additions and 0 deletions

View File

@ -226,7 +226,9 @@ struct asus_wmi {
u32 tablet_switch_dev_id;
enum fan_type fan_type;
enum fan_type gpu_fan_type;
int fan_pwm_mode;
int gpu_fan_pwm_mode;
int agfn_pwm;
bool fan_boost_mode_available;
@ -1734,6 +1736,18 @@ static int asus_fan_set_auto(struct asus_wmi *asus)
return -ENXIO;
}
/*
* Modern models like the G713 also have GPU fan control (this is not AGFN)
*/
if (asus->gpu_fan_type == FAN_TYPE_SPEC83) {
status = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_FAN_CTRL,
0, &retval);
if (status)
return status;
if (retval != 1)
return -EIO;
}
return 0;
}
@ -1936,9 +1950,57 @@ static ssize_t asus_hwmon_temp1(struct device *dev,
deci_kelvin_to_millicelsius(value & 0xFFFF));
}
/* GPU fan on modern ROG laptops */
static ssize_t pwm2_enable_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct asus_wmi *asus = dev_get_drvdata(dev);
return sysfs_emit(buf, "%d\n", asus->gpu_fan_pwm_mode);
}
static ssize_t pwm2_enable_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct asus_wmi *asus = dev_get_drvdata(dev);
int state;
int value;
int ret;
u32 retval;
ret = kstrtouint(buf, 10, &state);
if (ret)
return ret;
switch (state) { /* standard documented hwmon values */
case ASUS_FAN_CTRL_FULLSPEED:
value = 1;
break;
case ASUS_FAN_CTRL_AUTO:
value = 0;
break;
default:
return -EINVAL;
}
ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_FAN_CTRL,
value, &retval);
if (ret)
return ret;
if (retval != 1)
return -EIO;
asus->gpu_fan_pwm_mode = state;
return count;
}
/* Fan1 */
static DEVICE_ATTR_RW(pwm1);
static DEVICE_ATTR_RW(pwm1_enable);
static DEVICE_ATTR_RW(pwm2_enable);
static DEVICE_ATTR_RO(fan1_input);
static DEVICE_ATTR_RO(fan1_label);
@ -1948,6 +2010,7 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL);
static struct attribute *hwmon_attributes[] = {
&dev_attr_pwm1.attr,
&dev_attr_pwm1_enable.attr,
&dev_attr_pwm2_enable.attr,
&dev_attr_fan1_input.attr,
&dev_attr_fan1_label.attr,
@ -1970,6 +2033,9 @@ static umode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
|| attr == &dev_attr_pwm1_enable.attr) {
if (asus->fan_type == FAN_TYPE_NONE)
return 0;
} else if (attr == &dev_attr_pwm2_enable.attr) {
if (asus->gpu_fan_type == FAN_TYPE_NONE)
return 0;
} else if (attr == &dev_attr_temp1_input.attr) {
int err = asus_wmi_get_devstate(asus,
ASUS_WMI_DEVID_THERMAL_CTRL,
@ -2012,6 +2078,7 @@ static int asus_wmi_hwmon_init(struct asus_wmi *asus)
static int asus_wmi_fan_init(struct asus_wmi *asus)
{
asus->gpu_fan_type = FAN_TYPE_NONE;
asus->fan_type = FAN_TYPE_NONE;
asus->agfn_pwm = -1;
@ -2020,6 +2087,10 @@ static int asus_wmi_fan_init(struct asus_wmi *asus)
else if (asus_wmi_has_agfn_fan(asus))
asus->fan_type = FAN_TYPE_AGFN;
/* Modern models like G713 also have GPU fan control */
if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL))
asus->gpu_fan_type = FAN_TYPE_SPEC83;
if (asus->fan_type == FAN_TYPE_NONE)
return -ENODEV;

View File

@ -79,6 +79,7 @@
#define ASUS_WMI_DEVID_THERMAL_CTRL 0x00110011
#define ASUS_WMI_DEVID_FAN_CTRL 0x00110012 /* deprecated */
#define ASUS_WMI_DEVID_CPU_FAN_CTRL 0x00110013
#define ASUS_WMI_DEVID_GPU_FAN_CTRL 0x00110014
#define ASUS_WMI_DEVID_CPU_FAN_CURVE 0x00110024
#define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025