Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/radeon: bind fan control on CI cards to hwmon interface (v2)

This 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. Use with caution!

v2: agd5f: fix formatting, squash in:

minor fix for pwm1_enable exposed value

Track smc control in addition to fan mode
This fixes pwm1_enable being constantly set
to 1 because of enabled smc control

also handle the case where smc fan control is disabled.

Signed-off-by: Oleg Chernovskiy <algonkvel@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Oleg Chernovskiy and committed by
Alex Deucher
36689e57 99736703

+55 -10
+43 -10
drivers/gpu/drm/radeon/ci_dpm.c
··· 187 187 static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, 188 188 PPSMC_Msg msg, u32 parameter); 189 189 190 + static void ci_thermal_start_smc_fan_control(struct radeon_device *rdev); 191 + static void ci_fan_ctrl_set_default_mode(struct radeon_device *rdev); 192 + 190 193 static struct ci_power_info *ci_get_pi(struct radeon_device *rdev) 191 194 { 192 195 struct ci_power_info *pi = rdev->pm.dpm.priv; ··· 1046 1043 return -EINVAL; 1047 1044 } 1048 1045 1046 + pi->fan_is_controlled_by_smc = true; 1049 1047 return 0; 1050 1048 } 1051 1049 1052 - #if 0 1053 1050 static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) 1054 1051 { 1055 1052 PPSMC_Result ret; 1053 + struct ci_power_info *pi = ci_get_pi(rdev); 1056 1054 1057 1055 ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl); 1058 - if (ret == PPSMC_Result_OK) 1056 + if (ret == PPSMC_Result_OK) { 1057 + pi->fan_is_controlled_by_smc = false; 1059 1058 return 0; 1060 - else 1059 + } else 1061 1060 return -EINVAL; 1062 1061 } 1063 1062 1064 - static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, 1063 + int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, 1065 1064 u32 *speed) 1066 1065 { 1067 1066 u32 duty, duty100; ··· 1088 1083 return 0; 1089 1084 } 1090 1085 1091 - static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, 1086 + int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, 1092 1087 u32 speed) 1093 1088 { 1094 1089 u32 tmp; 1095 1090 u32 duty, duty100; 1096 1091 u64 tmp64; 1092 + struct ci_power_info *pi = ci_get_pi(rdev); 1097 1093 1098 1094 if (rdev->pm.no_fan) 1099 1095 return -ENOENT; 1100 1096 1101 - if (speed > 100) 1097 + if (pi->fan_is_controlled_by_smc) 1102 1098 return -EINVAL; 1103 1099 1104 - if (rdev->pm.dpm.fan.ucode_fan_control) 1105 - ci_fan_ctrl_stop_smc_fan_control(rdev); 1100 + if (speed > 100) 1101 + return -EINVAL; 1106 1102 1107 1103 duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; 1108 1104 ··· 1118 1112 tmp |= FDO_STATIC_DUTY(duty); 1119 1113 WREG32_SMC(CG_FDO_CTRL0, tmp); 1120 1114 1121 - ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); 1122 - 1123 1115 return 0; 1124 1116 } 1125 1117 1118 + void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode) 1119 + { 1120 + if (mode) { 1121 + /* stop auto-manage */ 1122 + if (rdev->pm.dpm.fan.ucode_fan_control) 1123 + ci_fan_ctrl_stop_smc_fan_control(rdev); 1124 + ci_fan_ctrl_set_static_mode(rdev, mode); 1125 + } else { 1126 + /* restart auto-manage */ 1127 + if (rdev->pm.dpm.fan.ucode_fan_control) 1128 + ci_thermal_start_smc_fan_control(rdev); 1129 + else 1130 + ci_fan_ctrl_set_default_mode(rdev); 1131 + } 1132 + } 1133 + 1134 + u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev) 1135 + { 1136 + struct ci_power_info *pi = ci_get_pi(rdev); 1137 + u32 tmp; 1138 + 1139 + if (pi->fan_is_controlled_by_smc) 1140 + return 0; 1141 + 1142 + tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; 1143 + return (tmp >> FDO_PWM_MODE_SHIFT); 1144 + } 1145 + 1146 + #if 0 1126 1147 static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, 1127 1148 u32 *speed) 1128 1149 {
+1
drivers/gpu/drm/radeon/ci_dpm.h
··· 291 291 struct ci_ps requested_ps; 292 292 /* fan control */ 293 293 bool fan_ctrl_is_in_default_mode; 294 + bool fan_is_controlled_by_smc; 294 295 u32 t_min; 295 296 u32 fan_ctrl_default_mode; 296 297 };
+4
drivers/gpu/drm/radeon/radeon_asic.c
··· 2118 2118 .force_performance_level = &ci_dpm_force_performance_level, 2119 2119 .vblank_too_short = &ci_dpm_vblank_too_short, 2120 2120 .powergate_uvd = &ci_dpm_powergate_uvd, 2121 + .fan_ctrl_set_mode = &ci_fan_ctrl_set_mode, 2122 + .fan_ctrl_get_mode = &ci_fan_ctrl_get_mode, 2123 + .get_fan_speed_percent = &ci_fan_ctrl_get_fan_speed_percent, 2124 + .set_fan_speed_percent = &ci_fan_ctrl_set_fan_speed_percent, 2121 2125 }, 2122 2126 .pflip = { 2123 2127 .page_flip = &evergreen_page_flip,
+7
drivers/gpu/drm/radeon/radeon_asic.h
··· 861 861 bool ci_dpm_vblank_too_short(struct radeon_device *rdev); 862 862 void ci_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); 863 863 864 + int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, 865 + u32 *speed); 866 + int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, 867 + u32 speed); 868 + u32 ci_fan_ctrl_get_mode(struct radeon_device *rdev); 869 + void ci_fan_ctrl_set_mode(struct radeon_device *rdev, u32 mode); 870 + 864 871 int kv_dpm_init(struct radeon_device *rdev); 865 872 int kv_dpm_enable(struct radeon_device *rdev); 866 873 int kv_dpm_late_enable(struct radeon_device *rdev);