The GPU fan interface is same as the CPU fan, so it is straightforward. Signed-off-by: Vasiliy Kupriakov <rublag-ns@xxxxxxxxx> --- drivers/platform/x86/asus-wmi.c | 43 ++++++++++++++++++++++ include/linux/platform_data/x86/asus-wmi.h | 1 + 2 files changed, 44 insertions(+) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 82505307ec17..07508c4d1a9a 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -71,6 +71,8 @@ MODULE_LICENSE("GPL"); #define ASUS_FAN_SFUN_READ 0x06 #define ASUS_FAN_SFUN_WRITE 0x07 +#define ASUS_GPU_FAN_DESC "gpu_fan" + /* Based on standard hwmon pwmX_enable values */ #define ASUS_FAN_CTRL_FULLSPEED 0 #define ASUS_FAN_CTRL_MANUAL 1 @@ -201,6 +203,7 @@ struct asus_wmi { enum fan_type fan_type; int fan_pwm_mode; int agfn_pwm; + bool gpu_fan_available; bool fan_boost_mode_available; u8 fan_boost_mode_mask; @@ -1546,6 +1549,29 @@ static ssize_t fan1_label_show(struct device *dev, return sprintf(buf, "%s\n", ASUS_FAN_DESC); } +static ssize_t fan2_input_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + int value; + int ret; + + ret = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL, &value); + if (ret < 0) + return ret; + + value &= 0xFFFF; + return sprintf(buf, "%d\n", value < 0 ? -1 : value * 100); +} + +static ssize_t fan2_label_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%s\n", ASUS_GPU_FAN_DESC); +} + static ssize_t asus_hwmon_temp1(struct device *dev, struct device_attribute *attr, char *buf) @@ -1568,6 +1594,10 @@ static DEVICE_ATTR_RW(pwm1_enable); static DEVICE_ATTR_RO(fan1_input); static DEVICE_ATTR_RO(fan1_label); +/* GPU fan */ +static DEVICE_ATTR_RO(fan2_input); +static DEVICE_ATTR_RO(fan2_label); + /* Temperature */ static DEVICE_ATTR(temp1_input, S_IRUGO, asus_hwmon_temp1, NULL); @@ -1577,6 +1607,9 @@ static struct attribute *hwmon_attributes[] = { &dev_attr_fan1_input.attr, &dev_attr_fan1_label.attr, + &dev_attr_fan2_input.attr, + &dev_attr_fan2_label.attr, + &dev_attr_temp1_input.attr, NULL }; @@ -1596,6 +1629,10 @@ 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_fan2_input.attr + || attr == &dev_attr_fan2_label.attr) { + if (!asus->gpu_fan_available) + return 0; } else if (attr == &dev_attr_temp1_input.attr) { int err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_THERMAL_CTRL, @@ -1640,6 +1677,7 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) { asus->fan_type = FAN_TYPE_NONE; asus->agfn_pwm = -1; + asus->gpu_fan_available = false; if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CPU_FAN_CTRL)) asus->fan_type = FAN_TYPE_SPEC83; @@ -1653,6 +1691,11 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) asus_fan_set_auto(asus); asus->fan_pwm_mode = ASUS_FAN_CTRL_AUTO; + + if (asus->fan_type == FAN_TYPE_SPEC83 && + asus_wmi_has_fan(asus, ASUS_WMI_DEVID_GPU_FAN_CTRL)) + asus->gpu_fan_available = true; + return 0; } diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 897b8332a39f..c0364ba63813 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -75,6 +75,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 /* Power */ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012 -- 2.28.0