diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index f373a81..fba376e 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -920,7 +920,7 @@ static int ci_thermal_enable_alert(struct radeon_device *rdev, return 0; } -static void ci_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode) +void ci_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode) { struct ci_power_info *pi = ci_get_pi(rdev); u32 tmp; @@ -1019,7 +1019,7 @@ static int ci_thermal_setup_fan_table(struct radeon_device *rdev) return 0; } -static int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) +int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) { struct ci_power_info *pi = ci_get_pi(rdev); PPSMC_Result ret; @@ -1046,9 +1046,9 @@ static int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) return 0; } -#if 0 -static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) +int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) { + struct ci_power_info *pi = ci_get_pi(rdev); PPSMC_Result ret; ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl); @@ -1058,7 +1058,13 @@ static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) return -EINVAL; } -static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, +u32 ci_fan_cntrl_get_static_mode(struct radeon_device *rdev) +{ + u32 tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; + return (tmp >> FDO_PWM_MODE_SHIFT); +} + +int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, u32 *speed) { u32 duty, duty100; @@ -1083,7 +1089,7 @@ static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, return 0; } -static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, +int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, u32 speed) { u32 tmp; @@ -1117,6 +1123,7 @@ static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, return 0; } +#if 0 static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, u32 *speed) { diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 54529b8..7518052 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1967,6 +1967,10 @@ struct radeon_asic { bool (*vblank_too_short)(struct radeon_device *rdev); void (*powergate_uvd)(struct radeon_device *rdev, bool gate); void (*enable_bapm)(struct radeon_device *rdev, bool enable); + void (*fan_ctrl_set_static_mode)(struct radeon_device *rdev, u32 mode); + u32 (*fan_ctrl_get_static_mode)(struct radeon_device *rdev); + int (*set_fan_speed_percent)(struct radeon_device *rdev, u32 speed); + int (*get_fan_speed_percent)(struct radeon_device *rdev, u32 *speed); } dpm; /* pageflipping */ struct { diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 850de57..9183cdb 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2104,6 +2104,10 @@ static struct radeon_asic ci_asic = { .force_performance_level = &ci_dpm_force_performance_level, .vblank_too_short = &ci_dpm_vblank_too_short, .powergate_uvd = &ci_dpm_powergate_uvd, + .fan_ctrl_set_static_mode = &ci_fan_ctrl_set_static_mode, + .fan_ctrl_get_static_mode = &ci_fan_cntrl_get_static_mode, + .get_fan_speed_percent = &ci_fan_ctrl_get_fan_speed_percent, + .set_fan_speed_percent = &ci_fan_ctrl_set_fan_speed_percent, }, .pflip = { .page_flip = &evergreen_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 2a45d54..c463995 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -861,6 +861,13 @@ int ci_dpm_force_performance_level(struct radeon_device *rdev, bool ci_dpm_vblank_too_short(struct radeon_device *rdev); void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); +int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, + u32 *speed); +int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, + u32 speed); +u32 ci_fan_cntrl_get_static_mode(struct radeon_device *rdev); +void ci_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode); + int kv_dpm_init(struct radeon_device *rdev); int kv_dpm_enable(struct radeon_device *rdev); int kv_dpm_late_enable(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 32522cc..2ed6106 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -24,6 +24,7 @@ #include "radeon.h" #include "avivod.h" #include "atom.h" +#include "r600_dpm.h" #include #include #include @@ -554,6 +555,99 @@ fail: return count; } +static ssize_t radeon_hwmon_get_pwm1_enable(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct radeon_device *rdev = dev_get_drvdata(dev); + u32 pwm_mode = 0; + + if(rdev->asic->dpm.fan_ctrl_get_static_mode) + pwm_mode = rdev->asic->dpm.fan_ctrl_get_static_mode(rdev); + + return sprintf(buf, "%i\n", pwm_mode > 0); +} + +static ssize_t radeon_hwmon_set_pwm1_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct radeon_device *rdev = dev_get_drvdata(dev); + int err; + int value; + + if(!rdev->asic->dpm.fan_ctrl_set_static_mode) + return -EINVAL; + + err = kstrtoint(buf, 10, &value); + if(err) + return err; + + // XXX: we have percent-based and rpm-based + // fan controls, what should we set here? + switch(value) { + case 1: // manual + rdev->asic->dpm.fan_ctrl_set_static_mode(rdev, + FDO_PWM_MODE_STATIC); + break; + default: // disable + rdev->asic->dpm.fan_ctrl_set_static_mode(rdev, 0); + break; + } + + return count; +} + +static ssize_t radeon_hwmon_get_pwm1_min(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%i\n", 0); +} + +static ssize_t radeon_hwmon_get_pwm1_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%i\n", 100); // we're using percent-based fan-control +} + +static ssize_t radeon_hwmon_set_pwm1(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct radeon_device *rdev = dev_get_drvdata(dev); + int err; + u32 value; + + err = kstrtou32(buf, 10, &value); + if(err) + return err; + + // XXX: implicitly applies percent static mode and sets pwm1_enable into 1 + // Is this correct behaviour? + err = rdev->asic->dpm.set_fan_speed_percent(rdev, value); + if(err) + return err; + + return count; +} + +static ssize_t radeon_hwmon_get_pwm1(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct radeon_device *rdev = dev_get_drvdata(dev); + int err; + u32 speed; + err = rdev->asic->dpm.get_fan_speed_percent(rdev, &speed); + if(err) + return err; + + return sprintf(buf, "%i\n", speed); +} + static DEVICE_ATTR(power_profile, S_IRUGO | S_IWUSR, radeon_get_pm_profile, radeon_set_pm_profile); static DEVICE_ATTR(power_method, S_IRUGO | S_IWUSR, radeon_get_pm_method, radeon_set_pm_method); static DEVICE_ATTR(power_dpm_state, S_IRUGO | S_IWUSR, radeon_get_dpm_state, radeon_set_dpm_state); @@ -601,11 +695,20 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev, static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, radeon_hwmon_show_temp, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, radeon_hwmon_show_temp_thresh, NULL, 1); +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1, radeon_hwmon_set_pwm1, 0); +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, radeon_hwmon_get_pwm1_enable, radeon_hwmon_set_pwm1_enable, 0); +static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, radeon_hwmon_get_pwm1_min, NULL, 0); +static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, radeon_hwmon_get_pwm1_max, NULL, 0); + static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_min.dev_attr.attr, + &sensor_dev_attr_pwm1_max.dev_attr.attr, NULL }; @@ -621,6 +724,13 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) return 0; + if(rdev->pm.no_fan && + (attr == &sensor_dev_attr_pwm1.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) + return 0; + return attr->mode; }