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

drm/amd/powerplay: new interfaces for overdrive vega20 sclk and mclk

Add support for the new SMU firmware interface for clock adjustment.

Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Evan Quan and committed by
Alex Deucher
d617d4d7 7dd67c0d

+169
+169
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
··· 1101 1101 return 0; 1102 1102 } 1103 1103 1104 + static int vega20_od8_set_settings( 1105 + struct pp_hwmgr *hwmgr, 1106 + uint32_t index, 1107 + uint32_t value) 1108 + { 1109 + OverDriveTable_t od_table; 1110 + int ret = 0; 1111 + 1112 + ret = vega20_copy_table_from_smc(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE); 1113 + PP_ASSERT_WITH_CODE(!ret, 1114 + "Failed to export over drive table!", 1115 + return ret); 1116 + 1117 + switch(index) { 1118 + case OD8_SETTING_GFXCLK_FMIN: 1119 + od_table.GfxclkFmin = (uint16_t)value; 1120 + break; 1121 + case OD8_SETTING_GFXCLK_FMAX: 1122 + od_table.GfxclkFmax = (uint16_t)value; 1123 + break; 1124 + case OD8_SETTING_GFXCLK_FREQ1: 1125 + od_table.GfxclkFreq1 = (uint16_t)value; 1126 + break; 1127 + case OD8_SETTING_GFXCLK_VOLTAGE1: 1128 + od_table.GfxclkOffsetVolt1 = (uint16_t)value; 1129 + break; 1130 + case OD8_SETTING_GFXCLK_FREQ2: 1131 + od_table.GfxclkFreq2 = (uint16_t)value; 1132 + break; 1133 + case OD8_SETTING_GFXCLK_VOLTAGE2: 1134 + od_table.GfxclkOffsetVolt2 = (uint16_t)value; 1135 + break; 1136 + case OD8_SETTING_GFXCLK_FREQ3: 1137 + od_table.GfxclkFreq3 = (uint16_t)value; 1138 + break; 1139 + case OD8_SETTING_GFXCLK_VOLTAGE3: 1140 + od_table.GfxclkOffsetVolt3 = (uint16_t)value; 1141 + break; 1142 + case OD8_SETTING_UCLK_FMAX: 1143 + od_table.UclkFmax = (uint16_t)value; 1144 + break; 1145 + case OD8_SETTING_POWER_PERCENTAGE: 1146 + od_table.OverDrivePct = (int16_t)value; 1147 + break; 1148 + case OD8_SETTING_FAN_ACOUSTIC_LIMIT: 1149 + od_table.FanMaximumRpm = (uint16_t)value; 1150 + break; 1151 + case OD8_SETTING_FAN_MIN_SPEED: 1152 + od_table.FanMinimumPwm = (uint16_t)value; 1153 + break; 1154 + case OD8_SETTING_FAN_TARGET_TEMP: 1155 + od_table.FanTargetTemperature = (uint16_t)value; 1156 + break; 1157 + case OD8_SETTING_OPERATING_TEMP_MAX: 1158 + od_table.MaxOpTemp = (uint16_t)value; 1159 + break; 1160 + } 1161 + 1162 + ret = vega20_copy_table_to_smc(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE); 1163 + PP_ASSERT_WITH_CODE(!ret, 1164 + "Failed to import over drive table!", 1165 + return ret); 1166 + 1167 + return 0; 1168 + } 1169 + 1170 + static int vega20_get_sclk_od( 1171 + struct pp_hwmgr *hwmgr) 1172 + { 1173 + struct vega20_hwmgr *data = hwmgr->backend; 1174 + struct vega20_single_dpm_table *sclk_table = 1175 + &(data->dpm_table.gfx_table); 1176 + struct vega20_single_dpm_table *golden_sclk_table = 1177 + &(data->golden_dpm_table.gfx_table); 1178 + int value; 1179 + 1180 + /* od percentage */ 1181 + value = DIV_ROUND_UP((sclk_table->dpm_levels[sclk_table->count - 1].value - 1182 + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * 100, 1183 + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value); 1184 + 1185 + return value; 1186 + } 1187 + 1188 + static int vega20_set_sclk_od( 1189 + struct pp_hwmgr *hwmgr, uint32_t value) 1190 + { 1191 + struct vega20_hwmgr *data = hwmgr->backend; 1192 + struct vega20_single_dpm_table *sclk_table = 1193 + &(data->dpm_table.gfx_table); 1194 + struct vega20_single_dpm_table *golden_sclk_table = 1195 + &(data->golden_dpm_table.gfx_table); 1196 + uint32_t od_sclk; 1197 + int ret = 0; 1198 + 1199 + od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value; 1200 + do_div(od_sclk, 100); 1201 + od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; 1202 + 1203 + ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk); 1204 + PP_ASSERT_WITH_CODE(!ret, 1205 + "[SetSclkOD] failed to set od gfxclk!", 1206 + return ret); 1207 + 1208 + /* refresh gfxclk table */ 1209 + ret = vega20_setup_single_dpm_table(hwmgr, sclk_table, PPCLK_GFXCLK); 1210 + PP_ASSERT_WITH_CODE(!ret, 1211 + "[SetSclkOD] failed to refresh gfxclk table!", 1212 + return ret); 1213 + 1214 + return 0; 1215 + } 1216 + 1217 + static int vega20_get_mclk_od( 1218 + struct pp_hwmgr *hwmgr) 1219 + { 1220 + struct vega20_hwmgr *data = hwmgr->backend; 1221 + struct vega20_single_dpm_table *mclk_table = 1222 + &(data->dpm_table.mem_table); 1223 + struct vega20_single_dpm_table *golden_mclk_table = 1224 + &(data->golden_dpm_table.mem_table); 1225 + int value; 1226 + 1227 + /* od percentage */ 1228 + value = DIV_ROUND_UP((mclk_table->dpm_levels[mclk_table->count - 1].value - 1229 + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * 100, 1230 + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value); 1231 + 1232 + return value; 1233 + } 1234 + 1235 + static int vega20_set_mclk_od( 1236 + struct pp_hwmgr *hwmgr, uint32_t value) 1237 + { 1238 + struct vega20_hwmgr *data = hwmgr->backend; 1239 + struct vega20_single_dpm_table *mclk_table = 1240 + &(data->dpm_table.mem_table); 1241 + struct vega20_single_dpm_table *golden_mclk_table = 1242 + &(data->golden_dpm_table.mem_table); 1243 + uint32_t od_mclk; 1244 + int ret = 0; 1245 + 1246 + od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value; 1247 + do_div(od_mclk, 100); 1248 + od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; 1249 + 1250 + ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk); 1251 + PP_ASSERT_WITH_CODE(!ret, 1252 + "[SetMclkOD] failed to set od memclk!", 1253 + return ret); 1254 + 1255 + /* refresh memclk table */ 1256 + ret = vega20_setup_single_dpm_table(hwmgr, mclk_table, PPCLK_UCLK); 1257 + PP_ASSERT_WITH_CODE(!ret, 1258 + "[SetMclkOD] failed to refresh memclk table!", 1259 + return ret); 1260 + 1261 + return 0; 1262 + } 1263 + 1104 1264 static int vega20_populate_umdpstate_clocks( 1105 1265 struct pp_hwmgr *hwmgr) 1106 1266 { ··· 2764 2604 vega20_get_power_profile_mode, 2765 2605 .set_power_profile_mode = 2766 2606 vega20_set_power_profile_mode, 2607 + /* od related */ 2767 2608 .set_power_limit = 2768 2609 vega20_set_power_limit, 2610 + .get_sclk_od = 2611 + vega20_get_sclk_od, 2612 + .set_sclk_od = 2613 + vega20_set_sclk_od, 2614 + .get_mclk_od = 2615 + vega20_get_mclk_od, 2616 + .set_mclk_od = 2617 + vega20_set_mclk_od, 2769 2618 /* for sysfs to retrive/set gfxclk/memclk */ 2770 2619 .force_clock_level = 2771 2620 vega20_force_clock_level,