1 /* 2 * Copyright 2021 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #include "amdgpu.h" 24 #include "amdgpu_i2c.h" 25 #include "amdgpu_atombios.h" 26 #include "atom.h" 27 #include "amd_pcie.h" 28 #include "legacy_dpm.h" 29 #include "amdgpu_dpm_internal.h" 30 #include "amdgpu_display.h" 31 32 #define amdgpu_dpm_pre_set_power_state(adev) \ 33 ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) 34 35 #define amdgpu_dpm_post_set_power_state(adev) \ 36 ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) 37 38 #define amdgpu_dpm_display_configuration_changed(adev) \ 39 ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) 40 41 #define amdgpu_dpm_print_power_state(adev, ps) \ 42 ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) 43 44 #define amdgpu_dpm_vblank_too_short(adev) \ 45 ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) 46 47 #define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ 48 ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) 49 50 void amdgpu_dpm_print_class_info(u32 class, u32 class2) 51 { 52 const char *s; 53 54 switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { 55 case ATOM_PPLIB_CLASSIFICATION_UI_NONE: 56 default: 57 s = "none"; 58 break; 59 case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: 60 s = "battery"; 61 break; 62 case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: 63 s = "balanced"; 64 break; 65 case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: 66 s = "performance"; 67 break; 68 } 69 printk("\tui class: %s\n", s); 70 printk("\tinternal class:"); 71 if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && 72 (class2 == 0)) 73 pr_cont(" none"); 74 else { 75 if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) 76 pr_cont(" boot"); 77 if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 78 pr_cont(" thermal"); 79 if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 80 pr_cont(" limited_pwr"); 81 if (class & ATOM_PPLIB_CLASSIFICATION_REST) 82 pr_cont(" rest"); 83 if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) 84 pr_cont(" forced"); 85 if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 86 pr_cont(" 3d_perf"); 87 if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 88 pr_cont(" ovrdrv"); 89 if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 90 pr_cont(" uvd"); 91 if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) 92 pr_cont(" 3d_low"); 93 if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) 94 pr_cont(" acpi"); 95 if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 96 pr_cont(" uvd_hd2"); 97 if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 98 pr_cont(" uvd_hd"); 99 if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 100 pr_cont(" uvd_sd"); 101 if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 102 pr_cont(" limited_pwr2"); 103 if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 104 pr_cont(" ulv"); 105 if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 106 pr_cont(" uvd_mvc"); 107 } 108 pr_cont("\n"); 109 } 110 111 void amdgpu_dpm_print_cap_info(u32 caps) 112 { 113 printk("\tcaps:"); 114 if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) 115 pr_cont(" single_disp"); 116 if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) 117 pr_cont(" video"); 118 if (caps & ATOM_PPLIB_DISALLOW_ON_DC) 119 pr_cont(" no_dc"); 120 pr_cont("\n"); 121 } 122 123 void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, 124 struct amdgpu_ps *rps) 125 { 126 printk("\tstatus:"); 127 if (rps == adev->pm.dpm.current_ps) 128 pr_cont(" c"); 129 if (rps == adev->pm.dpm.requested_ps) 130 pr_cont(" r"); 131 if (rps == adev->pm.dpm.boot_ps) 132 pr_cont(" b"); 133 pr_cont("\n"); 134 } 135 136 void amdgpu_pm_print_power_states(struct amdgpu_device *adev) 137 { 138 int i; 139 140 if (adev->powerplay.pp_funcs->print_power_state == NULL) 141 return; 142 143 for (i = 0; i < adev->pm.dpm.num_ps; i++) 144 amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); 145 146 } 147 148 union power_info { 149 struct _ATOM_POWERPLAY_INFO info; 150 struct _ATOM_POWERPLAY_INFO_V2 info_2; 151 struct _ATOM_POWERPLAY_INFO_V3 info_3; 152 struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 153 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 154 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 155 struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; 156 struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; 157 }; 158 159 int amdgpu_get_platform_caps(struct amdgpu_device *adev) 160 { 161 struct amdgpu_mode_info *mode_info = &adev->mode_info; 162 union power_info *power_info; 163 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 164 u16 data_offset; 165 u8 frev, crev; 166 167 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 168 &frev, &crev, &data_offset)) 169 return -EINVAL; 170 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 171 172 adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); 173 adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); 174 adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); 175 176 return 0; 177 } 178 179 union fan_info { 180 struct _ATOM_PPLIB_FANTABLE fan; 181 struct _ATOM_PPLIB_FANTABLE2 fan2; 182 struct _ATOM_PPLIB_FANTABLE3 fan3; 183 }; 184 185 static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, 186 ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) 187 { 188 u32 size = atom_table->ucNumEntries * 189 sizeof(struct amdgpu_clock_voltage_dependency_entry); 190 int i; 191 ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; 192 193 amdgpu_table->entries = kzalloc(size, GFP_KERNEL); 194 if (!amdgpu_table->entries) 195 return -ENOMEM; 196 197 entry = &atom_table->entries[0]; 198 for (i = 0; i < atom_table->ucNumEntries; i++) { 199 amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | 200 (entry->ucClockHigh << 16); 201 amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); 202 entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) 203 ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); 204 } 205 amdgpu_table->count = atom_table->ucNumEntries; 206 207 return 0; 208 } 209 210 /* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ 211 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 212 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 213 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 214 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 215 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 216 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 217 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 218 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 219 220 int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) 221 { 222 struct amdgpu_mode_info *mode_info = &adev->mode_info; 223 union power_info *power_info; 224 union fan_info *fan_info; 225 ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; 226 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 227 u16 data_offset; 228 u8 frev, crev; 229 int ret, i; 230 231 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 232 &frev, &crev, &data_offset)) 233 return -EINVAL; 234 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 235 236 /* fan table */ 237 if (le16_to_cpu(power_info->pplib.usTableSize) >= 238 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 239 if (power_info->pplib3.usFanTableOffset) { 240 fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + 241 le16_to_cpu(power_info->pplib3.usFanTableOffset)); 242 adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; 243 adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); 244 adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); 245 adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); 246 adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); 247 adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); 248 adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); 249 if (fan_info->fan.ucFanTableFormat >= 2) 250 adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); 251 else 252 adev->pm.dpm.fan.t_max = 10900; 253 adev->pm.dpm.fan.cycle_delay = 100000; 254 if (fan_info->fan.ucFanTableFormat >= 3) { 255 adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; 256 adev->pm.dpm.fan.default_max_fan_pwm = 257 le16_to_cpu(fan_info->fan3.usFanPWMMax); 258 adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; 259 adev->pm.dpm.fan.fan_output_sensitivity = 260 le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); 261 } 262 adev->pm.dpm.fan.ucode_fan_control = true; 263 } 264 } 265 266 /* clock dependancy tables, shedding tables */ 267 if (le16_to_cpu(power_info->pplib.usTableSize) >= 268 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { 269 if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { 270 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 271 (mode_info->atom_context->bios + data_offset + 272 le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); 273 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, 274 dep_table); 275 if (ret) { 276 amdgpu_free_extended_power_table(adev); 277 return ret; 278 } 279 } 280 if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { 281 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 282 (mode_info->atom_context->bios + data_offset + 283 le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); 284 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, 285 dep_table); 286 if (ret) { 287 amdgpu_free_extended_power_table(adev); 288 return ret; 289 } 290 } 291 if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { 292 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 293 (mode_info->atom_context->bios + data_offset + 294 le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); 295 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, 296 dep_table); 297 if (ret) { 298 amdgpu_free_extended_power_table(adev); 299 return ret; 300 } 301 } 302 if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { 303 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 304 (mode_info->atom_context->bios + data_offset + 305 le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); 306 ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, 307 dep_table); 308 if (ret) { 309 amdgpu_free_extended_power_table(adev); 310 return ret; 311 } 312 } 313 if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { 314 ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = 315 (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 316 (mode_info->atom_context->bios + data_offset + 317 le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); 318 if (clk_v->ucNumEntries) { 319 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = 320 le16_to_cpu(clk_v->entries[0].usSclkLow) | 321 (clk_v->entries[0].ucSclkHigh << 16); 322 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = 323 le16_to_cpu(clk_v->entries[0].usMclkLow) | 324 (clk_v->entries[0].ucMclkHigh << 16); 325 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = 326 le16_to_cpu(clk_v->entries[0].usVddc); 327 adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = 328 le16_to_cpu(clk_v->entries[0].usVddci); 329 } 330 } 331 if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { 332 ATOM_PPLIB_PhaseSheddingLimits_Table *psl = 333 (ATOM_PPLIB_PhaseSheddingLimits_Table *) 334 (mode_info->atom_context->bios + data_offset + 335 le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); 336 ATOM_PPLIB_PhaseSheddingLimits_Record *entry; 337 338 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = 339 kcalloc(psl->ucNumEntries, 340 sizeof(struct amdgpu_phase_shedding_limits_entry), 341 GFP_KERNEL); 342 if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { 343 amdgpu_free_extended_power_table(adev); 344 return -ENOMEM; 345 } 346 347 entry = &psl->entries[0]; 348 for (i = 0; i < psl->ucNumEntries; i++) { 349 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = 350 le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); 351 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = 352 le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); 353 adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = 354 le16_to_cpu(entry->usVoltage); 355 entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) 356 ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); 357 } 358 adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = 359 psl->ucNumEntries; 360 } 361 } 362 363 /* cac data */ 364 if (le16_to_cpu(power_info->pplib.usTableSize) >= 365 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { 366 adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); 367 adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); 368 adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; 369 adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); 370 if (adev->pm.dpm.tdp_od_limit) 371 adev->pm.dpm.power_control = true; 372 else 373 adev->pm.dpm.power_control = false; 374 adev->pm.dpm.tdp_adjustment = 0; 375 adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); 376 adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); 377 adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); 378 if (power_info->pplib5.usCACLeakageTableOffset) { 379 ATOM_PPLIB_CAC_Leakage_Table *cac_table = 380 (ATOM_PPLIB_CAC_Leakage_Table *) 381 (mode_info->atom_context->bios + data_offset + 382 le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); 383 ATOM_PPLIB_CAC_Leakage_Record *entry; 384 u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); 385 adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); 386 if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { 387 amdgpu_free_extended_power_table(adev); 388 return -ENOMEM; 389 } 390 entry = &cac_table->entries[0]; 391 for (i = 0; i < cac_table->ucNumEntries; i++) { 392 if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { 393 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = 394 le16_to_cpu(entry->usVddc1); 395 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = 396 le16_to_cpu(entry->usVddc2); 397 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = 398 le16_to_cpu(entry->usVddc3); 399 } else { 400 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = 401 le16_to_cpu(entry->usVddc); 402 adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = 403 le32_to_cpu(entry->ulLeakageValue); 404 } 405 entry = (ATOM_PPLIB_CAC_Leakage_Record *) 406 ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); 407 } 408 adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; 409 } 410 } 411 412 /* ext tables */ 413 if (le16_to_cpu(power_info->pplib.usTableSize) >= 414 sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { 415 ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) 416 (mode_info->atom_context->bios + data_offset + 417 le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); 418 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && 419 ext_hdr->usVCETableOffset) { 420 VCEClockInfoArray *array = (VCEClockInfoArray *) 421 (mode_info->atom_context->bios + data_offset + 422 le16_to_cpu(ext_hdr->usVCETableOffset) + 1); 423 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = 424 (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 425 (mode_info->atom_context->bios + data_offset + 426 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 427 1 + array->ucNumEntries * sizeof(VCEClockInfo)); 428 ATOM_PPLIB_VCE_State_Table *states = 429 (ATOM_PPLIB_VCE_State_Table *) 430 (mode_info->atom_context->bios + data_offset + 431 le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + 432 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + 433 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); 434 ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; 435 ATOM_PPLIB_VCE_State_Record *state_entry; 436 VCEClockInfo *vce_clk; 437 u32 size = limits->numEntries * 438 sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); 439 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = 440 kzalloc(size, GFP_KERNEL); 441 if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { 442 amdgpu_free_extended_power_table(adev); 443 return -ENOMEM; 444 } 445 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = 446 limits->numEntries; 447 entry = &limits->entries[0]; 448 state_entry = &states->entries[0]; 449 for (i = 0; i < limits->numEntries; i++) { 450 vce_clk = (VCEClockInfo *) 451 ((u8 *)&array->entries[0] + 452 (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 453 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = 454 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 455 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = 456 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 457 adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = 458 le16_to_cpu(entry->usVoltage); 459 entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) 460 ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); 461 } 462 adev->pm.dpm.num_of_vce_states = 463 states->numEntries > AMD_MAX_VCE_LEVELS ? 464 AMD_MAX_VCE_LEVELS : states->numEntries; 465 for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { 466 vce_clk = (VCEClockInfo *) 467 ((u8 *)&array->entries[0] + 468 (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); 469 adev->pm.dpm.vce_states[i].evclk = 470 le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); 471 adev->pm.dpm.vce_states[i].ecclk = 472 le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); 473 adev->pm.dpm.vce_states[i].clk_idx = 474 state_entry->ucClockInfoIndex & 0x3f; 475 adev->pm.dpm.vce_states[i].pstate = 476 (state_entry->ucClockInfoIndex & 0xc0) >> 6; 477 state_entry = (ATOM_PPLIB_VCE_State_Record *) 478 ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); 479 } 480 } 481 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && 482 ext_hdr->usUVDTableOffset) { 483 UVDClockInfoArray *array = (UVDClockInfoArray *) 484 (mode_info->atom_context->bios + data_offset + 485 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); 486 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = 487 (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 488 (mode_info->atom_context->bios + data_offset + 489 le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + 490 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); 491 ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; 492 u32 size = limits->numEntries * 493 sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); 494 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = 495 kzalloc(size, GFP_KERNEL); 496 if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { 497 amdgpu_free_extended_power_table(adev); 498 return -ENOMEM; 499 } 500 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = 501 limits->numEntries; 502 entry = &limits->entries[0]; 503 for (i = 0; i < limits->numEntries; i++) { 504 UVDClockInfo *uvd_clk = (UVDClockInfo *) 505 ((u8 *)&array->entries[0] + 506 (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); 507 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = 508 le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); 509 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = 510 le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); 511 adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = 512 le16_to_cpu(entry->usVoltage); 513 entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) 514 ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); 515 } 516 } 517 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && 518 ext_hdr->usSAMUTableOffset) { 519 ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = 520 (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 521 (mode_info->atom_context->bios + data_offset + 522 le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); 523 ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; 524 u32 size = limits->numEntries * 525 sizeof(struct amdgpu_clock_voltage_dependency_entry); 526 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = 527 kzalloc(size, GFP_KERNEL); 528 if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { 529 amdgpu_free_extended_power_table(adev); 530 return -ENOMEM; 531 } 532 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = 533 limits->numEntries; 534 entry = &limits->entries[0]; 535 for (i = 0; i < limits->numEntries; i++) { 536 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = 537 le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); 538 adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = 539 le16_to_cpu(entry->usVoltage); 540 entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) 541 ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); 542 } 543 } 544 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && 545 ext_hdr->usPPMTableOffset) { 546 ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) 547 (mode_info->atom_context->bios + data_offset + 548 le16_to_cpu(ext_hdr->usPPMTableOffset)); 549 adev->pm.dpm.dyn_state.ppm_table = 550 kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); 551 if (!adev->pm.dpm.dyn_state.ppm_table) { 552 amdgpu_free_extended_power_table(adev); 553 return -ENOMEM; 554 } 555 adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; 556 adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = 557 le16_to_cpu(ppm->usCpuCoreNumber); 558 adev->pm.dpm.dyn_state.ppm_table->platform_tdp = 559 le32_to_cpu(ppm->ulPlatformTDP); 560 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = 561 le32_to_cpu(ppm->ulSmallACPlatformTDP); 562 adev->pm.dpm.dyn_state.ppm_table->platform_tdc = 563 le32_to_cpu(ppm->ulPlatformTDC); 564 adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = 565 le32_to_cpu(ppm->ulSmallACPlatformTDC); 566 adev->pm.dpm.dyn_state.ppm_table->apu_tdp = 567 le32_to_cpu(ppm->ulApuTDP); 568 adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = 569 le32_to_cpu(ppm->ulDGpuTDP); 570 adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = 571 le32_to_cpu(ppm->ulDGpuUlvPower); 572 adev->pm.dpm.dyn_state.ppm_table->tj_max = 573 le32_to_cpu(ppm->ulTjmax); 574 } 575 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && 576 ext_hdr->usACPTableOffset) { 577 ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = 578 (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 579 (mode_info->atom_context->bios + data_offset + 580 le16_to_cpu(ext_hdr->usACPTableOffset) + 1); 581 ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; 582 u32 size = limits->numEntries * 583 sizeof(struct amdgpu_clock_voltage_dependency_entry); 584 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = 585 kzalloc(size, GFP_KERNEL); 586 if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { 587 amdgpu_free_extended_power_table(adev); 588 return -ENOMEM; 589 } 590 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = 591 limits->numEntries; 592 entry = &limits->entries[0]; 593 for (i = 0; i < limits->numEntries; i++) { 594 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = 595 le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); 596 adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = 597 le16_to_cpu(entry->usVoltage); 598 entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) 599 ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); 600 } 601 } 602 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && 603 ext_hdr->usPowerTuneTableOffset) { 604 u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + 605 le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 606 ATOM_PowerTune_Table *pt; 607 adev->pm.dpm.dyn_state.cac_tdp_table = 608 kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); 609 if (!adev->pm.dpm.dyn_state.cac_tdp_table) { 610 amdgpu_free_extended_power_table(adev); 611 return -ENOMEM; 612 } 613 if (rev > 0) { 614 ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) 615 (mode_info->atom_context->bios + data_offset + 616 le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 617 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 618 ppt->usMaximumPowerDeliveryLimit; 619 pt = &ppt->power_tune_table; 620 } else { 621 ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) 622 (mode_info->atom_context->bios + data_offset + 623 le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); 624 adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; 625 pt = &ppt->power_tune_table; 626 } 627 adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); 628 adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = 629 le16_to_cpu(pt->usConfigurableTDP); 630 adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); 631 adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = 632 le16_to_cpu(pt->usBatteryPowerLimit); 633 adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = 634 le16_to_cpu(pt->usSmallPowerLimit); 635 adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = 636 le16_to_cpu(pt->usLowCACLeakage); 637 adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = 638 le16_to_cpu(pt->usHighCACLeakage); 639 } 640 if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && 641 ext_hdr->usSclkVddgfxTableOffset) { 642 dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 643 (mode_info->atom_context->bios + data_offset + 644 le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); 645 ret = amdgpu_parse_clk_voltage_dep_table( 646 &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, 647 dep_table); 648 if (ret) { 649 kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); 650 return ret; 651 } 652 } 653 } 654 655 return 0; 656 } 657 658 void amdgpu_free_extended_power_table(struct amdgpu_device *adev) 659 { 660 struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; 661 662 kfree(dyn_state->vddc_dependency_on_sclk.entries); 663 kfree(dyn_state->vddci_dependency_on_mclk.entries); 664 kfree(dyn_state->vddc_dependency_on_mclk.entries); 665 kfree(dyn_state->mvdd_dependency_on_mclk.entries); 666 kfree(dyn_state->cac_leakage_table.entries); 667 kfree(dyn_state->phase_shedding_limits_table.entries); 668 kfree(dyn_state->ppm_table); 669 kfree(dyn_state->cac_tdp_table); 670 kfree(dyn_state->vce_clock_voltage_dependency_table.entries); 671 kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); 672 kfree(dyn_state->samu_clock_voltage_dependency_table.entries); 673 kfree(dyn_state->acp_clock_voltage_dependency_table.entries); 674 kfree(dyn_state->vddgfx_dependency_on_sclk.entries); 675 } 676 677 static const char *pp_lib_thermal_controller_names[] = { 678 "NONE", 679 "lm63", 680 "adm1032", 681 "adm1030", 682 "max6649", 683 "lm64", 684 "f75375", 685 "RV6xx", 686 "RV770", 687 "adt7473", 688 "NONE", 689 "External GPIO", 690 "Evergreen", 691 "emc2103", 692 "Sumo", 693 "Northern Islands", 694 "Southern Islands", 695 "lm96163", 696 "Sea Islands", 697 "Kaveri/Kabini", 698 }; 699 700 void amdgpu_add_thermal_controller(struct amdgpu_device *adev) 701 { 702 struct amdgpu_mode_info *mode_info = &adev->mode_info; 703 ATOM_PPLIB_POWERPLAYTABLE *power_table; 704 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 705 ATOM_PPLIB_THERMALCONTROLLER *controller; 706 struct amdgpu_i2c_bus_rec i2c_bus; 707 u16 data_offset; 708 u8 frev, crev; 709 710 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 711 &frev, &crev, &data_offset)) 712 return; 713 power_table = (ATOM_PPLIB_POWERPLAYTABLE *) 714 (mode_info->atom_context->bios + data_offset); 715 controller = &power_table->sThermalController; 716 717 /* add the i2c bus for thermal/fan chip */ 718 if (controller->ucType > 0) { 719 if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) 720 adev->pm.no_fan = true; 721 adev->pm.fan_pulses_per_revolution = 722 controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 723 if (adev->pm.fan_pulses_per_revolution) { 724 adev->pm.fan_min_rpm = controller->ucFanMinRPM; 725 adev->pm.fan_max_rpm = controller->ucFanMaxRPM; 726 } 727 if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { 728 DRM_INFO("Internal thermal controller %s fan control\n", 729 (controller->ucFanParameters & 730 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 731 adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; 732 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { 733 DRM_INFO("Internal thermal controller %s fan control\n", 734 (controller->ucFanParameters & 735 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 736 adev->pm.int_thermal_type = THERMAL_TYPE_RV770; 737 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { 738 DRM_INFO("Internal thermal controller %s fan control\n", 739 (controller->ucFanParameters & 740 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 741 adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; 742 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { 743 DRM_INFO("Internal thermal controller %s fan control\n", 744 (controller->ucFanParameters & 745 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 746 adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; 747 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { 748 DRM_INFO("Internal thermal controller %s fan control\n", 749 (controller->ucFanParameters & 750 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 751 adev->pm.int_thermal_type = THERMAL_TYPE_NI; 752 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { 753 DRM_INFO("Internal thermal controller %s fan control\n", 754 (controller->ucFanParameters & 755 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 756 adev->pm.int_thermal_type = THERMAL_TYPE_SI; 757 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { 758 DRM_INFO("Internal thermal controller %s fan control\n", 759 (controller->ucFanParameters & 760 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 761 adev->pm.int_thermal_type = THERMAL_TYPE_CI; 762 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { 763 DRM_INFO("Internal thermal controller %s fan control\n", 764 (controller->ucFanParameters & 765 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 766 adev->pm.int_thermal_type = THERMAL_TYPE_KV; 767 } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { 768 DRM_INFO("External GPIO thermal controller %s fan control\n", 769 (controller->ucFanParameters & 770 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 771 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; 772 } else if (controller->ucType == 773 ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { 774 DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", 775 (controller->ucFanParameters & 776 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 777 adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; 778 } else if (controller->ucType == 779 ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { 780 DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", 781 (controller->ucFanParameters & 782 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 783 adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; 784 } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { 785 DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", 786 pp_lib_thermal_controller_names[controller->ucType], 787 controller->ucI2cAddress >> 1, 788 (controller->ucFanParameters & 789 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 790 adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; 791 i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); 792 adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); 793 #ifdef notyet 794 if (adev->pm.i2c_bus) { 795 struct i2c_board_info info = { }; 796 const char *name = pp_lib_thermal_controller_names[controller->ucType]; 797 info.addr = controller->ucI2cAddress >> 1; 798 strlcpy(info.type, name, sizeof(info.type)); 799 i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); 800 } 801 #endif 802 } else { 803 DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", 804 controller->ucType, 805 controller->ucI2cAddress >> 1, 806 (controller->ucFanParameters & 807 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); 808 } 809 } 810 } 811 812 struct amd_vce_state* amdgpu_get_vce_clock_state(void *handle, u32 idx) 813 { 814 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 815 816 if (idx < adev->pm.dpm.num_of_vce_states) 817 return &adev->pm.dpm.vce_states[idx]; 818 819 return NULL; 820 } 821 822 static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, 823 enum amd_pm_state_type dpm_state) 824 { 825 int i; 826 struct amdgpu_ps *ps; 827 u32 ui_class; 828 bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? 829 true : false; 830 831 /* check if the vblank period is too short to adjust the mclk */ 832 if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { 833 if (amdgpu_dpm_vblank_too_short(adev)) 834 single_display = false; 835 } 836 837 /* certain older asics have a separare 3D performance state, 838 * so try that first if the user selected performance 839 */ 840 if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) 841 dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; 842 /* balanced states don't exist at the moment */ 843 if (dpm_state == POWER_STATE_TYPE_BALANCED) 844 dpm_state = POWER_STATE_TYPE_PERFORMANCE; 845 846 restart_search: 847 /* Pick the best power state based on current conditions */ 848 for (i = 0; i < adev->pm.dpm.num_ps; i++) { 849 ps = &adev->pm.dpm.ps[i]; 850 ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; 851 switch (dpm_state) { 852 /* user states */ 853 case POWER_STATE_TYPE_BATTERY: 854 if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { 855 if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 856 if (single_display) 857 return ps; 858 } else 859 return ps; 860 } 861 break; 862 case POWER_STATE_TYPE_BALANCED: 863 if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { 864 if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 865 if (single_display) 866 return ps; 867 } else 868 return ps; 869 } 870 break; 871 case POWER_STATE_TYPE_PERFORMANCE: 872 if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { 873 if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { 874 if (single_display) 875 return ps; 876 } else 877 return ps; 878 } 879 break; 880 /* internal states */ 881 case POWER_STATE_TYPE_INTERNAL_UVD: 882 if (adev->pm.dpm.uvd_ps) 883 return adev->pm.dpm.uvd_ps; 884 else 885 break; 886 case POWER_STATE_TYPE_INTERNAL_UVD_SD: 887 if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 888 return ps; 889 break; 890 case POWER_STATE_TYPE_INTERNAL_UVD_HD: 891 if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 892 return ps; 893 break; 894 case POWER_STATE_TYPE_INTERNAL_UVD_HD2: 895 if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 896 return ps; 897 break; 898 case POWER_STATE_TYPE_INTERNAL_UVD_MVC: 899 if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 900 return ps; 901 break; 902 case POWER_STATE_TYPE_INTERNAL_BOOT: 903 return adev->pm.dpm.boot_ps; 904 case POWER_STATE_TYPE_INTERNAL_THERMAL: 905 if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 906 return ps; 907 break; 908 case POWER_STATE_TYPE_INTERNAL_ACPI: 909 if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) 910 return ps; 911 break; 912 case POWER_STATE_TYPE_INTERNAL_ULV: 913 if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 914 return ps; 915 break; 916 case POWER_STATE_TYPE_INTERNAL_3DPERF: 917 if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 918 return ps; 919 break; 920 default: 921 break; 922 } 923 } 924 /* use a fallback state if we didn't match */ 925 switch (dpm_state) { 926 case POWER_STATE_TYPE_INTERNAL_UVD_SD: 927 dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; 928 goto restart_search; 929 case POWER_STATE_TYPE_INTERNAL_UVD_HD: 930 case POWER_STATE_TYPE_INTERNAL_UVD_HD2: 931 case POWER_STATE_TYPE_INTERNAL_UVD_MVC: 932 if (adev->pm.dpm.uvd_ps) { 933 return adev->pm.dpm.uvd_ps; 934 } else { 935 dpm_state = POWER_STATE_TYPE_PERFORMANCE; 936 goto restart_search; 937 } 938 case POWER_STATE_TYPE_INTERNAL_THERMAL: 939 dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; 940 goto restart_search; 941 case POWER_STATE_TYPE_INTERNAL_ACPI: 942 dpm_state = POWER_STATE_TYPE_BATTERY; 943 goto restart_search; 944 case POWER_STATE_TYPE_BATTERY: 945 case POWER_STATE_TYPE_BALANCED: 946 case POWER_STATE_TYPE_INTERNAL_3DPERF: 947 dpm_state = POWER_STATE_TYPE_PERFORMANCE; 948 goto restart_search; 949 default: 950 break; 951 } 952 953 return NULL; 954 } 955 956 static int amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) 957 { 958 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 959 struct amdgpu_ps *ps; 960 enum amd_pm_state_type dpm_state; 961 int ret; 962 bool equal = false; 963 964 /* if dpm init failed */ 965 if (!adev->pm.dpm_enabled) 966 return 0; 967 968 if (adev->pm.dpm.user_state != adev->pm.dpm.state) { 969 /* add other state override checks here */ 970 if ((!adev->pm.dpm.thermal_active) && 971 (!adev->pm.dpm.uvd_active)) 972 adev->pm.dpm.state = adev->pm.dpm.user_state; 973 } 974 dpm_state = adev->pm.dpm.state; 975 976 ps = amdgpu_dpm_pick_power_state(adev, dpm_state); 977 if (ps) 978 adev->pm.dpm.requested_ps = ps; 979 else 980 return -EINVAL; 981 982 if (amdgpu_dpm == 1 && pp_funcs->print_power_state) { 983 printk("switching from power state:\n"); 984 amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); 985 printk("switching to power state:\n"); 986 amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); 987 } 988 989 /* update whether vce is active */ 990 ps->vce_active = adev->pm.dpm.vce_active; 991 if (pp_funcs->display_configuration_changed) 992 amdgpu_dpm_display_configuration_changed(adev); 993 994 ret = amdgpu_dpm_pre_set_power_state(adev); 995 if (ret) 996 return ret; 997 998 if (pp_funcs->check_state_equal) { 999 if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) 1000 equal = false; 1001 } 1002 1003 if (equal) 1004 return 0; 1005 1006 if (pp_funcs->set_power_state) 1007 pp_funcs->set_power_state(adev->powerplay.pp_handle); 1008 1009 amdgpu_dpm_post_set_power_state(adev); 1010 1011 adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; 1012 adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; 1013 1014 if (pp_funcs->force_performance_level) { 1015 if (adev->pm.dpm.thermal_active) { 1016 enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; 1017 /* force low perf level for thermal */ 1018 pp_funcs->force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); 1019 /* save the user's level */ 1020 adev->pm.dpm.forced_level = level; 1021 } else { 1022 /* otherwise, user selected level */ 1023 pp_funcs->force_performance_level(adev, adev->pm.dpm.forced_level); 1024 } 1025 } 1026 1027 return 0; 1028 } 1029 1030 void amdgpu_legacy_dpm_compute_clocks(void *handle) 1031 { 1032 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1033 1034 amdgpu_dpm_get_active_displays(adev); 1035 1036 amdgpu_dpm_change_power_state_locked(adev); 1037 } 1038 1039 void amdgpu_dpm_thermal_work_handler(struct work_struct *work) 1040 { 1041 struct amdgpu_device *adev = 1042 container_of(work, struct amdgpu_device, 1043 pm.dpm.thermal.work); 1044 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1045 /* switch to the thermal state */ 1046 enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; 1047 int temp, size = sizeof(temp); 1048 1049 if (!adev->pm.dpm_enabled) 1050 return; 1051 1052 if (!pp_funcs->read_sensor(adev->powerplay.pp_handle, 1053 AMDGPU_PP_SENSOR_GPU_TEMP, 1054 (void *)&temp, 1055 &size)) { 1056 if (temp < adev->pm.dpm.thermal.min_temp) 1057 /* switch back the user state */ 1058 dpm_state = adev->pm.dpm.user_state; 1059 } else { 1060 if (adev->pm.dpm.thermal.high_to_low) 1061 /* switch back the user state */ 1062 dpm_state = adev->pm.dpm.user_state; 1063 } 1064 1065 if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) 1066 adev->pm.dpm.thermal_active = true; 1067 else 1068 adev->pm.dpm.thermal_active = false; 1069 1070 adev->pm.dpm.state = dpm_state; 1071 1072 amdgpu_legacy_dpm_compute_clocks(adev->powerplay.pp_handle); 1073 } 1074