add common fan control asic callbacks
Subsystems (2)
PATCH 1/3 add common fan control asic callbacks
Adds 4 callbacks for managing fan state/speed
* fan_ctrl_set_mode - manages fan control mode (nonzero == manual)
* fan_ctrl_get_mode - queries fan control mode
* set_fan_speed_percent - manages fan speed as percentage value
* get_fan_speed_percent - queries fan speed as percentage value
--- drivers/gpu/drm/radeon/radeon.h | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/radeon/radeon.h +4 -0
@@ -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_mode)(struct radeon_device *rdev,u32 mode); +u32 (*fan_ctrl_get_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 {
Signature · 6 lines
2.1.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/3 add hwmon interface for managing fan pwm
This adds percent-based fan control. Attributes (I hope) follow the sysfs-interface specification:
* pwm1 - fan speed query/manage
* pwm1_max, pwm1_min - min/max values for fan pwm (constant)
* pwm1_enable - fan control query/manage (enable/disable)
(There is no rpm-based control for now)
--- drivers/gpu/drm/radeon/radeon_pm.c | 129 ++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/radeon_pm.c +128 -1
@@ -24,6 +24,7 @@#include "radeon.h" #include "avivod.h" #include "atom.h" +#include "r600_dpm.h" #include <linux/power_supply.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h>
@@ -554,6 +555,94 @@ 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_mode) + pwm_mode = rdev->asic->dpm.fan_ctrl_get_mode (rdev); + +return sprintf (buf,"%i\n" , pwm_mode ==FDO_PWM_MODE_STATIC ); +} + +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_mode) +return -EINVAL ; + + err =kstrtoint (buf,10 , &value); +if (err) +return err; + +switch (value) { +case 1 :// manual, percent-based + rdev->asic->dpm.fan_ctrl_set_mode (rdev,FDO_PWM_MODE_STATIC ); +break ; +default :// disable + rdev->asic->dpm.fan_ctrl_set_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 );// pwm uses 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; + + 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 +690,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 };
@@ -614,6 +712,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, { struct device *dev = container_of(kobj, struct device, kobj);struct radeon_device *rdev =dev_get_drvdata (dev); +umode_t effective_mode = attr->mode;/* Skip limit attributes if DPM is not enabled */ if (rdev->pm.pm_method != PM_METHOD_DPM &&
@@ -621,7 +720,35 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))return 0 ; -return attr->mode; +/* Skip fan attributes if fan is not present */ +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 ; + +/* mask fan attributes if we have no bindings for this asic to expose */ +if ((!rdev->asic->dpm.get_fan_speed_percent && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) ||// can't query fan + (!rdev->asic->dpm.fan_ctrl_get_mode && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr))// can't query state + effective_mode &= ~S_IRUGO ; + +if ((!rdev->asic->dpm.set_fan_speed_percent && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) ||// can't manage fan + (!rdev->asic->dpm.fan_ctrl_set_mode && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr))// can't manage state + effective_mode &= ~S_IWUSR ; + +/* hide max/min values if we can't both query and manage the fan */ +if ((!rdev->asic->dpm.set_fan_speed_percent && + !rdev->asic->dpm.get_fan_speed_percent) && + (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) +return 0 ; + +return effective_mode; }static const struct attribute_group hwmon_attrgroup = {
Signature · 6 lines
2.1.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/3 bind fan control on CI cards to hwmon interface
In reply to Oleg ChernovskiyThis adds a possibility to control fan on CI parts via exported hwmon variables. Note that automatic ucode fan management pauses if you choose to enable manual fan control
--- drivers/gpu/drm/radeon/ci_dpm.c | 32 ++++++++++++++++++++++++-------- drivers/gpu/drm/radeon/radeon_asic.c | 4 ++++ drivers/gpu/drm/radeon/radeon_asic.h | 7 +++++++ 3 files changed, 35 insertions(+), 8 deletions(-)
drivers/gpu/drm/radeon/ci_dpm.c +24 -8
@@ -187,6 +187,8 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate);static PPSMC_Result ci_send_msg_to_smc_with_parameter (struct radeon_device *rdev,PPSMC_Msg msg,u32 parameter); +static void ci_thermal_start_smc_fan_control (struct radeon_device *rdev); +static struct ci_power_info *ci_get_pi (struct radeon_device *rdev) {struct ci_power_info *pi = rdev->pm.dpm.priv;
@@ -1046,7 +1048,6 @@ 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) {PPSMC_Result ret;
@@ -1058,7 +1059,7 @@ 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, +int ci_fan_ctrl_get_fan_speed_percent (struct radeon_device *rdev,u32 *speed) {u32 duty, duty100;
@@ -1083,7 +1084,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;
@@ -1096,9 +1097,6 @@ static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev,if (speed >100 )return -EINVAL ; -if (rdev->pm.dpm.fan.ucode_fan_control) -ci_fan_ctrl_stop_smc_fan_control (rdev); - duty100 = (RREG32_SMC (CG_FDO_CTRL1 ) &FMAX_DUTY100_MASK ) >>FMAX_DUTY100_SHIFT ;if (duty100 ==0 )
@@ -1112,11 +1110,29 @@ static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, tmp |=FDO_STATIC_DUTY (duty);WREG32_SMC (CG_FDO_CTRL0 , tmp); -ci_fan_ctrl_set_static_mode (rdev,FDO_PWM_MODE_STATIC ); -return 0 ; } +void ci_fan_ctrl_set_mode (struct radeon_device *rdev,u32 mode) +{ +if (mode) { +// stop auto-manage +if (rdev->pm.dpm.fan.ucode_fan_control) +ci_fan_ctrl_stop_smc_fan_control (rdev); +ci_fan_ctrl_set_static_mode (rdev, mode); + }else { +// restart auto-manage +ci_thermal_start_smc_fan_control (rdev); + } +} + +u32 ci_fan_cntrl_get_mode (struct radeon_device *rdev) +{ +u32 tmp =RREG32_SMC (CG_FDO_CTRL2 ) &FDO_PWM_MODE_MASK ; +return (tmp >>FDO_PWM_MODE_SHIFT ); +} + +#if 0 static int ci_fan_ctrl_get_fan_speed_rpm (struct radeon_device *rdev,u32 *speed) {
drivers/gpu/drm/radeon/radeon_asic.c +4 -0
@@ -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_mode = &ci_fan_ctrl_set_mode, + .fan_ctrl_get_mode = &ci_fan_cntrl_get_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,
drivers/gpu/drm/radeon/radeon_asic.h +7 -0
@@ -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_mode (struct radeon_device *rdev); +void ci_fan_ctrl_set_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);
Signature · 6 lines
2.1.3 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel