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

drm/radeon/dpm: add smc fan control for CI (v2)

Enable smc fan control for CI boards. Should
reduce the fan noise on systems with a higher
default fan profile.

v2: disable by default, add additional fan setup, rpm control

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=73338

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

+443 -4
+344 -1
drivers/gpu/drm/radeon/ci_dpm.c
··· 184 184 u32 target_tdp); 185 185 static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate); 186 186 187 + static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, 188 + PPSMC_Msg msg, u32 parameter); 189 + 187 190 static struct ci_power_info *ci_get_pi(struct radeon_device *rdev) 188 191 { 189 192 struct ci_power_info *pi = rdev->pm.dpm.priv; ··· 358 355 return 0; 359 356 } 360 357 358 + static int ci_populate_fuzzy_fan(struct radeon_device *rdev) 359 + { 360 + struct ci_power_info *pi = ci_get_pi(rdev); 361 + 362 + if ((rdev->pm.dpm.fan.fan_output_sensitivity & (1 << 15)) || 363 + (rdev->pm.dpm.fan.fan_output_sensitivity == 0)) 364 + rdev->pm.dpm.fan.fan_output_sensitivity = 365 + rdev->pm.dpm.fan.default_fan_output_sensitivity; 366 + 367 + pi->smc_powertune_table.FuzzyFan_PwmSetDelta = 368 + cpu_to_be16(rdev->pm.dpm.fan.fan_output_sensitivity); 369 + 370 + return 0; 371 + } 372 + 361 373 static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct radeon_device *rdev) 362 374 { 363 375 struct ci_power_info *pi = ci_get_pi(rdev); ··· 496 478 if (ret) 497 479 return ret; 498 480 ret = ci_populate_dw8(rdev); 481 + if (ret) 482 + return ret; 483 + ret = ci_populate_fuzzy_fan(rdev); 499 484 if (ret) 500 485 return ret; 501 486 ret = ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(rdev); ··· 880 859 881 860 if (enable) { 882 861 thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); 862 + WREG32_SMC(CG_THERMAL_INT, thermal_int); 883 863 rdev->irq.dpm_thermal = false; 884 864 result = ci_send_msg_to_smc(rdev, PPSMC_MSG_Thermal_Cntl_Enable); 885 865 if (result != PPSMC_Result_OK) { ··· 889 867 } 890 868 } else { 891 869 thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; 870 + WREG32_SMC(CG_THERMAL_INT, thermal_int); 892 871 rdev->irq.dpm_thermal = true; 893 872 result = ci_send_msg_to_smc(rdev, PPSMC_MSG_Thermal_Cntl_Disable); 894 873 if (result != PPSMC_Result_OK) { ··· 898 875 } 899 876 } 900 877 901 - WREG32_SMC(CG_THERMAL_INT, thermal_int); 878 + return 0; 879 + } 880 + 881 + static void ci_fan_ctrl_set_static_mode(struct radeon_device *rdev, u32 mode) 882 + { 883 + struct ci_power_info *pi = ci_get_pi(rdev); 884 + u32 tmp; 885 + 886 + if (pi->fan_ctrl_is_in_default_mode) { 887 + tmp = (RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT; 888 + pi->fan_ctrl_default_mode = tmp; 889 + tmp = (RREG32_SMC(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT; 890 + pi->t_min = tmp; 891 + pi->fan_ctrl_is_in_default_mode = false; 892 + } 893 + 894 + tmp = RREG32_SMC(CG_FDO_CTRL2) & ~TMIN_MASK; 895 + tmp |= TMIN(0); 896 + WREG32_SMC(CG_FDO_CTRL2, tmp); 897 + 898 + tmp = RREG32_SMC(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; 899 + tmp |= FDO_PWM_MODE(mode); 900 + WREG32_SMC(CG_FDO_CTRL2, tmp); 901 + } 902 + 903 + static int ci_thermal_setup_fan_table(struct radeon_device *rdev) 904 + { 905 + struct ci_power_info *pi = ci_get_pi(rdev); 906 + SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; 907 + u32 duty100; 908 + u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2; 909 + u16 fdo_min, slope1, slope2; 910 + u32 reference_clock, tmp; 911 + int ret; 912 + u64 tmp64; 913 + 914 + if (!pi->fan_table_start) { 915 + rdev->pm.dpm.fan.ucode_fan_control = false; 916 + return 0; 917 + } 918 + 919 + duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; 920 + 921 + if (duty100 == 0) { 922 + rdev->pm.dpm.fan.ucode_fan_control = false; 923 + return 0; 924 + } 925 + 926 + tmp64 = (u64)rdev->pm.dpm.fan.pwm_min * duty100; 927 + do_div(tmp64, 10000); 928 + fdo_min = (u16)tmp64; 929 + 930 + t_diff1 = rdev->pm.dpm.fan.t_med - rdev->pm.dpm.fan.t_min; 931 + t_diff2 = rdev->pm.dpm.fan.t_high - rdev->pm.dpm.fan.t_med; 932 + 933 + pwm_diff1 = rdev->pm.dpm.fan.pwm_med - rdev->pm.dpm.fan.pwm_min; 934 + pwm_diff2 = rdev->pm.dpm.fan.pwm_high - rdev->pm.dpm.fan.pwm_med; 935 + 936 + slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); 937 + slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); 938 + 939 + fan_table.TempMin = cpu_to_be16((50 + rdev->pm.dpm.fan.t_min) / 100); 940 + fan_table.TempMed = cpu_to_be16((50 + rdev->pm.dpm.fan.t_med) / 100); 941 + fan_table.TempMax = cpu_to_be16((50 + rdev->pm.dpm.fan.t_max) / 100); 942 + 943 + fan_table.Slope1 = cpu_to_be16(slope1); 944 + fan_table.Slope2 = cpu_to_be16(slope2); 945 + 946 + fan_table.FdoMin = cpu_to_be16(fdo_min); 947 + 948 + fan_table.HystDown = cpu_to_be16(rdev->pm.dpm.fan.t_hyst); 949 + 950 + fan_table.HystUp = cpu_to_be16(1); 951 + 952 + fan_table.HystSlope = cpu_to_be16(1); 953 + 954 + fan_table.TempRespLim = cpu_to_be16(5); 955 + 956 + reference_clock = radeon_get_xclk(rdev); 957 + 958 + fan_table.RefreshPeriod = cpu_to_be32((rdev->pm.dpm.fan.cycle_delay * 959 + reference_clock) / 1600); 960 + 961 + fan_table.FdoMax = cpu_to_be16((u16)duty100); 962 + 963 + tmp = (RREG32_SMC(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; 964 + fan_table.TempSrc = (uint8_t)tmp; 965 + 966 + ret = ci_copy_bytes_to_smc(rdev, 967 + pi->fan_table_start, 968 + (u8 *)(&fan_table), 969 + sizeof(fan_table), 970 + pi->sram_end); 971 + 972 + if (ret) { 973 + DRM_ERROR("Failed to load fan table to the SMC."); 974 + rdev->pm.dpm.fan.ucode_fan_control = false; 975 + } 902 976 903 977 return 0; 978 + } 979 + 980 + static int ci_fan_ctrl_start_smc_fan_control(struct radeon_device *rdev) 981 + { 982 + struct ci_power_info *pi = ci_get_pi(rdev); 983 + PPSMC_Result ret; 984 + 985 + if (pi->caps_od_fuzzy_fan_control_support) { 986 + ret = ci_send_msg_to_smc_with_parameter(rdev, 987 + PPSMC_StartFanControl, 988 + FAN_CONTROL_FUZZY); 989 + if (ret != PPSMC_Result_OK) 990 + return -EINVAL; 991 + ret = ci_send_msg_to_smc_with_parameter(rdev, 992 + PPSMC_MSG_SetFanPwmMax, 993 + rdev->pm.dpm.fan.default_max_fan_pwm); 994 + if (ret != PPSMC_Result_OK) 995 + return -EINVAL; 996 + } else { 997 + ret = ci_send_msg_to_smc_with_parameter(rdev, 998 + PPSMC_StartFanControl, 999 + FAN_CONTROL_TABLE); 1000 + if (ret != PPSMC_Result_OK) 1001 + return -EINVAL; 1002 + } 1003 + 1004 + return 0; 1005 + } 1006 + 1007 + #if 0 1008 + static int ci_fan_ctrl_stop_smc_fan_control(struct radeon_device *rdev) 1009 + { 1010 + PPSMC_Result ret; 1011 + 1012 + ret = ci_send_msg_to_smc(rdev, PPSMC_StopFanControl); 1013 + if (ret == PPSMC_Result_OK) 1014 + return 0; 1015 + else 1016 + return -EINVAL; 1017 + } 1018 + 1019 + static int ci_fan_ctrl_get_fan_speed_percent(struct radeon_device *rdev, 1020 + u32 *speed) 1021 + { 1022 + u32 duty, duty100; 1023 + u64 tmp64; 1024 + 1025 + if (rdev->pm.no_fan) 1026 + return -ENOENT; 1027 + 1028 + duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; 1029 + duty = (RREG32_SMC(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT; 1030 + 1031 + if (duty100 == 0) 1032 + return -EINVAL; 1033 + 1034 + tmp64 = (u64)duty * 100; 1035 + do_div(tmp64, duty100); 1036 + *speed = (u32)tmp64; 1037 + 1038 + if (*speed > 100) 1039 + *speed = 100; 1040 + 1041 + return 0; 1042 + } 1043 + 1044 + static int ci_fan_ctrl_set_fan_speed_percent(struct radeon_device *rdev, 1045 + u32 speed) 1046 + { 1047 + u32 tmp; 1048 + u32 duty, duty100; 1049 + u64 tmp64; 1050 + 1051 + if (rdev->pm.no_fan) 1052 + return -ENOENT; 1053 + 1054 + if (speed > 100) 1055 + return -EINVAL; 1056 + 1057 + if (rdev->pm.dpm.fan.ucode_fan_control) 1058 + ci_fan_ctrl_stop_smc_fan_control(rdev); 1059 + 1060 + duty100 = (RREG32_SMC(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; 1061 + 1062 + if (duty100 == 0) 1063 + return -EINVAL; 1064 + 1065 + tmp64 = (u64)speed * duty100; 1066 + do_div(tmp64, 100); 1067 + duty = (u32)tmp64; 1068 + 1069 + tmp = RREG32_SMC(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK; 1070 + tmp |= FDO_STATIC_DUTY(duty); 1071 + WREG32_SMC(CG_FDO_CTRL0, tmp); 1072 + 1073 + ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); 1074 + 1075 + return 0; 1076 + } 1077 + 1078 + static int ci_fan_ctrl_get_fan_speed_rpm(struct radeon_device *rdev, 1079 + u32 *speed) 1080 + { 1081 + u32 tach_period; 1082 + u32 xclk = radeon_get_xclk(rdev); 1083 + 1084 + if (rdev->pm.no_fan) 1085 + return -ENOENT; 1086 + 1087 + if (rdev->pm.fan_pulses_per_revolution == 0) 1088 + return -ENOENT; 1089 + 1090 + tach_period = (RREG32_SMC(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT; 1091 + if (tach_period == 0) 1092 + return -ENOENT; 1093 + 1094 + *speed = 60 * xclk * 10000 / tach_period; 1095 + 1096 + return 0; 1097 + } 1098 + 1099 + static int ci_fan_ctrl_set_fan_speed_rpm(struct radeon_device *rdev, 1100 + u32 speed) 1101 + { 1102 + u32 tach_period, tmp; 1103 + u32 xclk = radeon_get_xclk(rdev); 1104 + 1105 + if (rdev->pm.no_fan) 1106 + return -ENOENT; 1107 + 1108 + if (rdev->pm.fan_pulses_per_revolution == 0) 1109 + return -ENOENT; 1110 + 1111 + if ((speed < rdev->pm.fan_min_rpm) || 1112 + (speed > rdev->pm.fan_max_rpm)) 1113 + return -EINVAL; 1114 + 1115 + if (rdev->pm.dpm.fan.ucode_fan_control) 1116 + ci_fan_ctrl_stop_smc_fan_control(rdev); 1117 + 1118 + tach_period = 60 * xclk * 10000 / (8 * speed); 1119 + tmp = RREG32_SMC(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK; 1120 + tmp |= TARGET_PERIOD(tach_period); 1121 + WREG32_SMC(CG_TACH_CTRL, tmp); 1122 + 1123 + ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); 1124 + 1125 + return 0; 1126 + } 1127 + #endif 1128 + 1129 + static void ci_fan_ctrl_set_default_mode(struct radeon_device *rdev) 1130 + { 1131 + struct ci_power_info *pi = ci_get_pi(rdev); 1132 + u32 tmp; 1133 + 1134 + if (!pi->fan_ctrl_is_in_default_mode) { 1135 + tmp = RREG32_SMC(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; 1136 + tmp |= FDO_PWM_MODE(pi->fan_ctrl_default_mode); 1137 + WREG32_SMC(CG_FDO_CTRL2, tmp); 1138 + 1139 + tmp = RREG32_SMC(CG_FDO_CTRL2) & TMIN_MASK; 1140 + tmp |= TMIN(pi->t_min); 1141 + WREG32_SMC(CG_FDO_CTRL2, tmp); 1142 + pi->fan_ctrl_is_in_default_mode = true; 1143 + } 1144 + } 1145 + 1146 + static void ci_thermal_start_smc_fan_control(struct radeon_device *rdev) 1147 + { 1148 + if (rdev->pm.dpm.fan.ucode_fan_control) { 1149 + ci_fan_ctrl_start_smc_fan_control(rdev); 1150 + ci_fan_ctrl_set_static_mode(rdev, FDO_PWM_MODE_STATIC); 1151 + } 1152 + } 1153 + 1154 + static void ci_thermal_initialize(struct radeon_device *rdev) 1155 + { 1156 + u32 tmp; 1157 + 1158 + if (rdev->pm.fan_pulses_per_revolution) { 1159 + tmp = RREG32_SMC(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK; 1160 + tmp |= EDGE_PER_REV(rdev->pm.fan_pulses_per_revolution -1); 1161 + WREG32_SMC(CG_TACH_CTRL, tmp); 1162 + } 1163 + 1164 + tmp = RREG32_SMC(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK; 1165 + tmp |= TACH_PWM_RESP_RATE(0x28); 1166 + WREG32_SMC(CG_FDO_CTRL2, tmp); 1167 + } 1168 + 1169 + static int ci_thermal_start_thermal_controller(struct radeon_device *rdev) 1170 + { 1171 + int ret; 1172 + 1173 + ci_thermal_initialize(rdev); 1174 + ret = ci_thermal_set_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 1175 + if (ret) 1176 + return ret; 1177 + ret = ci_thermal_enable_alert(rdev, true); 1178 + if (ret) 1179 + return ret; 1180 + if (rdev->pm.dpm.fan.ucode_fan_control) { 1181 + ret = ci_thermal_setup_fan_table(rdev); 1182 + if (ret) 1183 + return ret; 1184 + ci_thermal_start_smc_fan_control(rdev); 1185 + } 1186 + 1187 + return 0; 1188 + } 1189 + 1190 + static void ci_thermal_stop_thermal_controller(struct radeon_device *rdev) 1191 + { 1192 + if (!rdev->pm.no_fan) 1193 + ci_fan_ctrl_set_default_mode(rdev); 904 1194 } 905 1195 906 1196 #if 0 ··· 5177 4841 5178 4842 ci_enable_auto_throttle_source(rdev, RADEON_DPM_AUTO_THROTTLE_SRC_THERMAL, true); 5179 4843 4844 + ci_thermal_start_thermal_controller(rdev); 4845 + 5180 4846 ci_update_current_ps(rdev, boot_ps); 5181 4847 5182 4848 return 0; ··· 5223 4885 5224 4886 if (!ci_is_smc_running(rdev)) 5225 4887 return; 4888 + 4889 + ci_thermal_stop_thermal_controller(rdev); 5226 4890 5227 4891 if (pi->thermal_protection) 5228 4892 ci_enable_thermal_protection(rdev, false); ··· 5812 5472 (rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0)) 5813 5473 rdev->pm.dpm.dyn_state.max_clock_voltage_on_dc = 5814 5474 rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac; 5475 + 5476 + pi->fan_ctrl_is_in_default_mode = true; 5477 + rdev->pm.dpm.fan.ucode_fan_control = false; 5815 5478 5816 5479 return 0; 5817 5480 }
+5
drivers/gpu/drm/radeon/ci_dpm.h
··· 266 266 bool caps_automatic_dc_transition; 267 267 bool caps_sclk_throttle_low_notification; 268 268 bool caps_dynamic_ac_timing; 269 + bool caps_od_fuzzy_fan_control_support; 269 270 /* flags */ 270 271 bool thermal_protection; 271 272 bool pcie_performance_request; ··· 288 287 struct ci_ps current_ps; 289 288 struct radeon_ps requested_rps; 290 289 struct ci_ps requested_ps; 290 + /* fan control */ 291 + bool fan_ctrl_is_in_default_mode; 292 + u32 t_min; 293 + u32 fan_ctrl_default_mode; 291 294 }; 292 295 293 296 #define CISLANDS_VOLTAGE_CONTROL_NONE 0x0
+38 -2
drivers/gpu/drm/radeon/cikd.h
··· 186 186 #define DIG_THERM_DPM(x) ((x) << 14) 187 187 #define DIG_THERM_DPM_MASK 0x003FC000 188 188 #define DIG_THERM_DPM_SHIFT 14 189 - 189 + #define CG_THERMAL_STATUS 0xC0300008 190 + #define FDO_PWM_DUTY(x) ((x) << 9) 191 + #define FDO_PWM_DUTY_MASK (0xff << 9) 192 + #define FDO_PWM_DUTY_SHIFT 9 190 193 #define CG_THERMAL_INT 0xC030000C 191 194 #define CI_DIG_THERM_INTH(x) ((x) << 8) 192 195 #define CI_DIG_THERM_INTH_MASK 0x0000FF00 ··· 199 196 #define CI_DIG_THERM_INTL_SHIFT 16 200 197 #define THERM_INT_MASK_HIGH (1 << 24) 201 198 #define THERM_INT_MASK_LOW (1 << 25) 202 - 199 + #define CG_MULT_THERMAL_CTRL 0xC0300010 200 + #define TEMP_SEL(x) ((x) << 20) 201 + #define TEMP_SEL_MASK (0xff << 20) 202 + #define TEMP_SEL_SHIFT 20 203 203 #define CG_MULT_THERMAL_STATUS 0xC0300014 204 204 #define ASIC_MAX_TEMP(x) ((x) << 0) 205 205 #define ASIC_MAX_TEMP_MASK 0x000001ff ··· 210 204 #define CTF_TEMP(x) ((x) << 9) 211 205 #define CTF_TEMP_MASK 0x0003fe00 212 206 #define CTF_TEMP_SHIFT 9 207 + 208 + #define CG_FDO_CTRL0 0xC0300064 209 + #define FDO_STATIC_DUTY(x) ((x) << 0) 210 + #define FDO_STATIC_DUTY_MASK 0x0000000F 211 + #define FDO_STATIC_DUTY_SHIFT 0 212 + #define CG_FDO_CTRL1 0xC0300068 213 + #define FMAX_DUTY100(x) ((x) << 0) 214 + #define FMAX_DUTY100_MASK 0x0000000F 215 + #define FMAX_DUTY100_SHIFT 0 216 + #define CG_FDO_CTRL2 0xC030006C 217 + #define TMIN(x) ((x) << 0) 218 + #define TMIN_MASK 0x0000000F 219 + #define TMIN_SHIFT 0 220 + #define FDO_PWM_MODE(x) ((x) << 11) 221 + #define FDO_PWM_MODE_MASK (3 << 11) 222 + #define FDO_PWM_MODE_SHIFT 11 223 + #define TACH_PWM_RESP_RATE(x) ((x) << 25) 224 + #define TACH_PWM_RESP_RATE_MASK (0x7f << 25) 225 + #define TACH_PWM_RESP_RATE_SHIFT 25 226 + #define CG_TACH_CTRL 0xC0300070 227 + # define EDGE_PER_REV(x) ((x) << 0) 228 + # define EDGE_PER_REV_MASK (0x7 << 0) 229 + # define EDGE_PER_REV_SHIFT 0 230 + # define TARGET_PERIOD(x) ((x) << 3) 231 + # define TARGET_PERIOD_MASK 0xfffffff8 232 + # define TARGET_PERIOD_SHIFT 3 233 + #define CG_TACH_STATUS 0xC0300074 234 + # define TACH_PERIOD(x) ((x) << 0) 235 + # define TACH_PERIOD_MASK 0xffffffff 236 + # define TACH_PERIOD_SHIFT 0 213 237 214 238 #define CG_ECLK_CNTL 0xC05000AC 215 239 # define ECLK_DIVIDER_MASK 0x7f
+6
drivers/gpu/drm/radeon/ppsmc.h
··· 59 59 #define FDO_MODE_HARDWARE 0 60 60 #define FDO_MODE_PIECE_WISE_LINEAR 1 61 61 62 + enum FAN_CONTROL { 63 + FAN_CONTROL_FUZZY, 64 + FAN_CONTROL_TABLE 65 + }; 66 + 62 67 #define PPSMC_Result_OK ((uint8_t)0x01) 63 68 #define PPSMC_Result_Failed ((uint8_t)0xFF) 64 69 ··· 160 155 #define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) 161 156 #define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) 162 157 #define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) 158 + #define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) 163 159 164 160 #define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) 165 161 #define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201)
+8
drivers/gpu/drm/radeon/pptable.h
··· 96 96 USHORT usTMax; // The max temperature 97 97 } ATOM_PPLIB_FANTABLE2; 98 98 99 + typedef struct _ATOM_PPLIB_FANTABLE3 100 + { 101 + ATOM_PPLIB_FANTABLE2 basicTable2; 102 + UCHAR ucFanControlMode; 103 + USHORT usFanPWMMax; 104 + USHORT usFanOutputSensitivity; 105 + } ATOM_PPLIB_FANTABLE3; 106 + 99 107 typedef struct _ATOM_PPLIB_EXTENDEDHEADER 100 108 { 101 109 USHORT usSize;
+9
drivers/gpu/drm/radeon/r600_dpm.c
··· 811 811 union fan_info { 812 812 struct _ATOM_PPLIB_FANTABLE fan; 813 813 struct _ATOM_PPLIB_FANTABLE2 fan2; 814 + struct _ATOM_PPLIB_FANTABLE3 fan3; 814 815 }; 815 816 816 817 static int r600_parse_clk_voltage_dep_table(struct radeon_clock_voltage_dependency_table *radeon_table, ··· 901 900 else 902 901 rdev->pm.dpm.fan.t_max = 10900; 903 902 rdev->pm.dpm.fan.cycle_delay = 100000; 903 + if (fan_info->fan.ucFanTableFormat >= 3) { 904 + rdev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; 905 + rdev->pm.dpm.fan.default_max_fan_pwm = 906 + le16_to_cpu(fan_info->fan3.usFanPWMMax); 907 + rdev->pm.dpm.fan.default_fan_output_sensitivity = 4836; 908 + rdev->pm.dpm.fan.fan_output_sensitivity = 909 + le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); 910 + } 904 911 rdev->pm.dpm.fan.ucode_fan_control = true; 905 912 } 906 913 }
+4
drivers/gpu/drm/radeon/radeon.h
··· 1494 1494 u8 t_hyst; 1495 1495 u32 cycle_delay; 1496 1496 u16 t_max; 1497 + u8 control_mode; 1498 + u16 default_max_fan_pwm; 1499 + u16 default_fan_output_sensitivity; 1500 + u16 fan_output_sensitivity; 1497 1501 bool ucode_fan_control; 1498 1502 }; 1499 1503
+29 -1
drivers/gpu/drm/radeon/smu7_discrete.h
··· 431 431 432 432 typedef struct SMU7_Discrete_MCRegisters SMU7_Discrete_MCRegisters; 433 433 434 + struct SMU7_Discrete_FanTable 435 + { 436 + uint16_t FdoMode; 437 + int16_t TempMin; 438 + int16_t TempMed; 439 + int16_t TempMax; 440 + int16_t Slope1; 441 + int16_t Slope2; 442 + int16_t FdoMin; 443 + int16_t HystUp; 444 + int16_t HystDown; 445 + int16_t HystSlope; 446 + int16_t TempRespLim; 447 + int16_t TempCurr; 448 + int16_t SlopeCurr; 449 + int16_t PwmCurr; 450 + uint32_t RefreshPeriod; 451 + int16_t FdoMax; 452 + uint8_t TempSrc; 453 + int8_t Padding; 454 + }; 455 + 456 + typedef struct SMU7_Discrete_FanTable SMU7_Discrete_FanTable; 457 + 458 + 434 459 struct SMU7_Discrete_PmFuses { 435 460 // dw0-dw1 436 461 uint8_t BapmVddCVidHiSidd[8]; ··· 487 462 uint8_t BapmVddCVidHiSidd2[8]; 488 463 489 464 // dw11-dw12 490 - uint32_t Reserved6[2]; 465 + int16_t FuzzyFan_ErrorSetDelta; 466 + int16_t FuzzyFan_ErrorRateSetDelta; 467 + int16_t FuzzyFan_PwmSetDelta; 468 + uint16_t CalcMeasPowerBlend; 491 469 492 470 // dw13-dw16 493 471 uint8_t GnbLPML[16];