1/* 2 * Copyright 2014 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 24#include <linux/firmware.h> 25#include <linux/seq_file.h> 26#include "drmP.h" 27#include "amdgpu.h" 28#include "amdgpu_pm.h" 29#include "amdgpu_atombios.h" 30#include "vid.h" 31#include "vi_dpm.h" 32#include "amdgpu_dpm.h" 33#include "cz_dpm.h" 34#include "cz_ppsmc.h" 35#include "atom.h" 36 37#include "smu/smu_8_0_d.h" 38#include "smu/smu_8_0_sh_mask.h" 39#include "gca/gfx_8_0_d.h" 40#include "gca/gfx_8_0_sh_mask.h" 41#include "gmc/gmc_8_1_d.h" 42#include "bif/bif_5_1_d.h" 43#include "gfx_v8_0.h" 44 45static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate); 46static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate); 47 48static struct cz_ps *cz_get_ps(struct amdgpu_ps *rps) 49{ 50 struct cz_ps *ps = rps->ps_priv; 51 52 return ps; 53} 54 55static struct cz_power_info *cz_get_pi(struct amdgpu_device *adev) 56{ 57 struct cz_power_info *pi = adev->pm.dpm.priv; 58 59 return pi; 60} 61 62static uint16_t cz_convert_8bit_index_to_voltage(struct amdgpu_device *adev, 63 uint16_t voltage) 64{ 65 uint16_t tmp = 6200 - voltage * 25; 66 67 return tmp; 68} 69 70static void cz_construct_max_power_limits_table(struct amdgpu_device *adev, 71 struct amdgpu_clock_and_voltage_limits *table) 72{ 73 struct cz_power_info *pi = cz_get_pi(adev); 74 struct amdgpu_clock_voltage_dependency_table *dep_table = 75 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 76 77 if (dep_table->count > 0) { 78 table->sclk = dep_table->entries[dep_table->count - 1].clk; 79 table->vddc = cz_convert_8bit_index_to_voltage(adev, 80 dep_table->entries[dep_table->count - 1].v); 81 } 82 83 table->mclk = pi->sys_info.nbp_memory_clock[0]; 84 85} 86 87union igp_info { 88 struct _ATOM_INTEGRATED_SYSTEM_INFO info; 89 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; 90 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; 91 struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_9 info_9; 92}; 93 94static int cz_parse_sys_info_table(struct amdgpu_device *adev) 95{ 96 struct cz_power_info *pi = cz_get_pi(adev); 97 struct amdgpu_mode_info *mode_info = &adev->mode_info; 98 int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 99 union igp_info *igp_info; 100 u8 frev, crev; 101 u16 data_offset; 102 int i = 0; 103 104 if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 105 &frev, &crev, &data_offset)) { 106 igp_info = (union igp_info *)(mode_info->atom_context->bios + 107 data_offset); 108 109 if (crev != 9) { 110 DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 111 return -EINVAL; 112 } 113 pi->sys_info.bootup_sclk = 114 le32_to_cpu(igp_info->info_9.ulBootUpEngineClock); 115 pi->sys_info.bootup_uma_clk = 116 le32_to_cpu(igp_info->info_9.ulBootUpUMAClock); 117 pi->sys_info.dentist_vco_freq = 118 le32_to_cpu(igp_info->info_9.ulDentistVCOFreq); 119 pi->sys_info.bootup_nb_voltage_index = 120 le16_to_cpu(igp_info->info_9.usBootUpNBVoltage); 121 122 if (igp_info->info_9.ucHtcTmpLmt == 0) 123 pi->sys_info.htc_tmp_lmt = 203; 124 else 125 pi->sys_info.htc_tmp_lmt = igp_info->info_9.ucHtcTmpLmt; 126 127 if (igp_info->info_9.ucHtcHystLmt == 0) 128 pi->sys_info.htc_hyst_lmt = 5; 129 else 130 pi->sys_info.htc_hyst_lmt = igp_info->info_9.ucHtcHystLmt; 131 132 if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { 133 DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); 134 return -EINVAL; 135 } 136 137 if (le32_to_cpu(igp_info->info_9.ulSystemConfig) & (1 << 3) && 138 pi->enable_nb_ps_policy) 139 pi->sys_info.nb_dpm_enable = true; 140 else 141 pi->sys_info.nb_dpm_enable = false; 142 143 for (i = 0; i < CZ_NUM_NBPSTATES; i++) { 144 if (i < CZ_NUM_NBPMEMORY_CLOCK) 145 pi->sys_info.nbp_memory_clock[i] = 146 le32_to_cpu(igp_info->info_9.ulNbpStateMemclkFreq[i]); 147 pi->sys_info.nbp_n_clock[i] = 148 le32_to_cpu(igp_info->info_9.ulNbpStateNClkFreq[i]); 149 } 150 151 for (i = 0; i < CZ_MAX_DISPLAY_CLOCK_LEVEL; i++) 152 pi->sys_info.display_clock[i] = 153 le32_to_cpu(igp_info->info_9.sDispClkVoltageMapping[i].ulMaximumSupportedCLK); 154 155 for (i = 0; i < CZ_NUM_NBPSTATES; i++) 156 pi->sys_info.nbp_voltage_index[i] = 157 le32_to_cpu(igp_info->info_9.usNBPStateVoltage[i]); 158 159 if (le32_to_cpu(igp_info->info_9.ulGPUCapInfo) & 160 SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) 161 pi->caps_enable_dfs_bypass = true; 162 163 pi->sys_info.uma_channel_number = 164 igp_info->info_9.ucUMAChannelNumber; 165 166 cz_construct_max_power_limits_table(adev, 167 &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac); 168 } 169 170 return 0; 171} 172 173static void cz_patch_voltage_values(struct amdgpu_device *adev) 174{ 175 int i; 176 struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = 177 &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 178 struct amdgpu_vce_clock_voltage_dependency_table *vce_table = 179 &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 180 struct amdgpu_clock_voltage_dependency_table *acp_table = 181 &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 182 183 if (uvd_table->count) { 184 for (i = 0; i < uvd_table->count; i++) 185 uvd_table->entries[i].v = 186 cz_convert_8bit_index_to_voltage(adev, 187 uvd_table->entries[i].v); 188 } 189 190 if (vce_table->count) { 191 for (i = 0; i < vce_table->count; i++) 192 vce_table->entries[i].v = 193 cz_convert_8bit_index_to_voltage(adev, 194 vce_table->entries[i].v); 195 } 196 197 if (acp_table->count) { 198 for (i = 0; i < acp_table->count; i++) 199 acp_table->entries[i].v = 200 cz_convert_8bit_index_to_voltage(adev, 201 acp_table->entries[i].v); 202 } 203 204} 205 206static void cz_construct_boot_state(struct amdgpu_device *adev) 207{ 208 struct cz_power_info *pi = cz_get_pi(adev); 209 210 pi->boot_pl.sclk = pi->sys_info.bootup_sclk; 211 pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; 212 pi->boot_pl.ds_divider_index = 0; 213 pi->boot_pl.ss_divider_index = 0; 214 pi->boot_pl.allow_gnb_slow = 1; 215 pi->boot_pl.force_nbp_state = 0; 216 pi->boot_pl.display_wm = 0; 217 pi->boot_pl.vce_wm = 0; 218 219} 220 221static void cz_patch_boot_state(struct amdgpu_device *adev, 222 struct cz_ps *ps) 223{ 224 struct cz_power_info *pi = cz_get_pi(adev); 225 226 ps->num_levels = 1; 227 ps->levels[0] = pi->boot_pl; 228} 229 230union pplib_clock_info { 231 struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 232 struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 233 struct _ATOM_PPLIB_CZ_CLOCK_INFO carrizo; 234}; 235 236static void cz_parse_pplib_clock_info(struct amdgpu_device *adev, 237 struct amdgpu_ps *rps, int index, 238 union pplib_clock_info *clock_info) 239{ 240 struct cz_power_info *pi = cz_get_pi(adev); 241 struct cz_ps *ps = cz_get_ps(rps); 242 struct cz_pl *pl = &ps->levels[index]; 243 struct amdgpu_clock_voltage_dependency_table *table = 244 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 245 246 pl->sclk = table->entries[clock_info->carrizo.index].clk; 247 pl->vddc_index = table->entries[clock_info->carrizo.index].v; 248 249 ps->num_levels = index + 1; 250 251 if (pi->caps_sclk_ds) { 252 pl->ds_divider_index = 5; 253 pl->ss_divider_index = 5; 254 } 255 256} 257 258static void cz_parse_pplib_non_clock_info(struct amdgpu_device *adev, 259 struct amdgpu_ps *rps, 260 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, 261 u8 table_rev) 262{ 263 struct cz_ps *ps = cz_get_ps(rps); 264 265 rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); 266 rps->class = le16_to_cpu(non_clock_info->usClassification); 267 rps->class2 = le16_to_cpu(non_clock_info->usClassification2); 268 269 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { 270 rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); 271 rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); 272 } else { 273 rps->vclk = 0; 274 rps->dclk = 0; 275 } 276 277 if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { 278 adev->pm.dpm.boot_ps = rps; 279 cz_patch_boot_state(adev, ps); 280 } 281 if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 282 adev->pm.dpm.uvd_ps = rps; 283 284} 285 286union power_info { 287 struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 288 struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 289 struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 290 struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; 291 struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; 292}; 293 294union pplib_power_state { 295 struct _ATOM_PPLIB_STATE v1; 296 struct _ATOM_PPLIB_STATE_V2 v2; 297}; 298 299static int cz_parse_power_table(struct amdgpu_device *adev) 300{ 301 struct amdgpu_mode_info *mode_info = &adev->mode_info; 302 struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 303 union pplib_power_state *power_state; 304 int i, j, k, non_clock_array_index, clock_array_index; 305 union pplib_clock_info *clock_info; 306 struct _StateArray *state_array; 307 struct _ClockInfoArray *clock_info_array; 308 struct _NonClockInfoArray *non_clock_info_array; 309 union power_info *power_info; 310 int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 311 u16 data_offset; 312 u8 frev, crev; 313 u8 *power_state_offset; 314 struct cz_ps *ps; 315 316 if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, 317 &frev, &crev, &data_offset)) 318 return -EINVAL; 319 power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 320 321 state_array = (struct _StateArray *) 322 (mode_info->atom_context->bios + data_offset + 323 le16_to_cpu(power_info->pplib.usStateArrayOffset)); 324 clock_info_array = (struct _ClockInfoArray *) 325 (mode_info->atom_context->bios + data_offset + 326 le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 327 non_clock_info_array = (struct _NonClockInfoArray *) 328 (mode_info->atom_context->bios + data_offset + 329 le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 330 331 adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) * 332 state_array->ucNumEntries, GFP_KERNEL); 333 334 if (!adev->pm.dpm.ps) 335 return -ENOMEM; 336 337 power_state_offset = (u8 *)state_array->states; 338 adev->pm.dpm.platform_caps = 339 le32_to_cpu(power_info->pplib.ulPlatformCaps); 340 adev->pm.dpm.backbias_response_time = 341 le16_to_cpu(power_info->pplib.usBackbiasTime); 342 adev->pm.dpm.voltage_response_time = 343 le16_to_cpu(power_info->pplib.usVoltageTime); 344 345 for (i = 0; i < state_array->ucNumEntries; i++) { 346 power_state = (union pplib_power_state *)power_state_offset; 347 non_clock_array_index = power_state->v2.nonClockInfoIndex; 348 non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 349 &non_clock_info_array->nonClockInfo[non_clock_array_index]; 350 351 ps = kzalloc(sizeof(struct cz_ps), GFP_KERNEL); 352 if (ps == NULL) { 353 kfree(adev->pm.dpm.ps); 354 return -ENOMEM; 355 } 356 357 adev->pm.dpm.ps[i].ps_priv = ps; 358 k = 0; 359 for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 360 clock_array_index = power_state->v2.clockInfoIndex[j]; 361 if (clock_array_index >= clock_info_array->ucNumEntries) 362 continue; 363 if (k >= CZ_MAX_HARDWARE_POWERLEVELS) 364 break; 365 clock_info = (union pplib_clock_info *) 366 &clock_info_array->clockInfo[clock_array_index * 367 clock_info_array->ucEntrySize]; 368 cz_parse_pplib_clock_info(adev, &adev->pm.dpm.ps[i], 369 k, clock_info); 370 k++; 371 } 372 cz_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i], 373 non_clock_info, 374 non_clock_info_array->ucEntrySize); 375 power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 376 } 377 adev->pm.dpm.num_ps = state_array->ucNumEntries; 378 379 return 0; 380} 381 382static int cz_process_firmware_header(struct amdgpu_device *adev) 383{ 384 struct cz_power_info *pi = cz_get_pi(adev); 385 u32 tmp; 386 int ret; 387 388 ret = cz_read_smc_sram_dword(adev, SMU8_FIRMWARE_HEADER_LOCATION + 389 offsetof(struct SMU8_Firmware_Header, 390 DpmTable), 391 &tmp, pi->sram_end); 392 393 if (ret == 0) 394 pi->dpm_table_start = tmp; 395 396 return ret; 397} 398 399static int cz_dpm_init(struct amdgpu_device *adev) 400{ 401 struct cz_power_info *pi; 402 int ret, i; 403 404 pi = kzalloc(sizeof(struct cz_power_info), GFP_KERNEL); 405 if (NULL == pi) 406 return -ENOMEM; 407 408 adev->pm.dpm.priv = pi; 409 410 ret = amdgpu_get_platform_caps(adev); 411 if (ret) 412 return ret; 413 414 ret = amdgpu_parse_extended_power_table(adev); 415 if (ret) 416 return ret; 417 418 pi->sram_end = SMC_RAM_END; 419 420 /* set up DPM defaults */ 421 for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) 422 pi->active_target[i] = CZ_AT_DFLT; 423 424 pi->mgcg_cgtt_local0 = 0x0; 425 pi->mgcg_cgtt_local1 = 0x0; 426 pi->clock_slow_down_step = 25000; 427 pi->skip_clock_slow_down = 1; 428 pi->enable_nb_ps_policy = 0; 429 pi->caps_power_containment = true; 430 pi->caps_cac = true; 431 pi->didt_enabled = false; 432 if (pi->didt_enabled) { 433 pi->caps_sq_ramping = true; 434 pi->caps_db_ramping = true; 435 pi->caps_td_ramping = true; 436 pi->caps_tcp_ramping = true; 437 } 438 pi->caps_sclk_ds = true; 439 pi->voting_clients = 0x00c00033; 440 pi->auto_thermal_throttling_enabled = true; 441 pi->bapm_enabled = false; 442 pi->disable_nb_ps3_in_battery = false; 443 pi->voltage_drop_threshold = 0; 444 pi->caps_sclk_throttle_low_notification = false; 445 pi->gfx_pg_threshold = 500; 446 pi->caps_fps = true; 447 /* uvd */ 448 pi->caps_uvd_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_UVD) ? true : false; 449 pi->caps_uvd_dpm = true; 450 /* vce */ 451 pi->caps_vce_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_VCE) ? true : false; 452 pi->caps_vce_dpm = true; 453 /* acp */ 454 pi->caps_acp_pg = (adev->pg_flags & AMDGPU_PG_SUPPORT_ACP) ? true : false; 455 pi->caps_acp_dpm = true; 456 457 pi->caps_stable_power_state = false; 458 pi->nb_dpm_enabled_by_driver = true; 459 pi->nb_dpm_enabled = false; 460 pi->caps_voltage_island = false; 461 /* flags which indicate need to upload pptable */ 462 pi->need_pptable_upload = true; 463 464 ret = cz_parse_sys_info_table(adev); 465 if (ret) 466 return ret; 467 468 cz_patch_voltage_values(adev); 469 cz_construct_boot_state(adev); 470 471 ret = cz_parse_power_table(adev); 472 if (ret) 473 return ret; 474 475 ret = cz_process_firmware_header(adev); 476 if (ret) 477 return ret; 478 479 pi->dpm_enabled = true; 480 pi->uvd_dynamic_pg = false; 481 482 return 0; 483} 484 485static void cz_dpm_fini(struct amdgpu_device *adev) 486{ 487 int i; 488 489 for (i = 0; i < adev->pm.dpm.num_ps; i++) 490 kfree(adev->pm.dpm.ps[i].ps_priv); 491 492 kfree(adev->pm.dpm.ps); 493 kfree(adev->pm.dpm.priv); 494 amdgpu_free_extended_power_table(adev); 495} 496 497#define ixSMUSVI_NB_CURRENTVID 0xD8230044 498#define CURRENT_NB_VID_MASK 0xff000000 499#define CURRENT_NB_VID__SHIFT 24 500#define ixSMUSVI_GFX_CURRENTVID 0xD8230048 501#define CURRENT_GFX_VID_MASK 0xff000000 502#define CURRENT_GFX_VID__SHIFT 24 503 504static void 505cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev, 506 struct seq_file *m) 507{ 508 struct cz_power_info *pi = cz_get_pi(adev); 509 struct amdgpu_clock_voltage_dependency_table *table = 510 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 511 struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = 512 &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 513 struct amdgpu_vce_clock_voltage_dependency_table *vce_table = 514 &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 515 u32 sclk_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX), 516 TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); 517 u32 uvd_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2), 518 TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); 519 u32 vce_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2), 520 TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); 521 u32 sclk, vclk, dclk, ecclk, tmp; 522 u16 vddnb, vddgfx; 523 524 if (sclk_index >= NUM_SCLK_LEVELS) { 525 seq_printf(m, "invalid sclk dpm profile %d\n", sclk_index); 526 } else { 527 sclk = table->entries[sclk_index].clk; 528 seq_printf(m, "%u sclk: %u\n", sclk_index, sclk); 529 } 530 531 tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) & 532 CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; 533 vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); 534 tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) & 535 CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; 536 vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp); 537 seq_printf(m, "vddnb: %u vddgfx: %u\n", vddnb, vddgfx); 538 539 seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); 540 if (!pi->uvd_power_gated) { 541 if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { 542 seq_printf(m, "invalid uvd dpm level %d\n", uvd_index); 543 } else { 544 vclk = uvd_table->entries[uvd_index].vclk; 545 dclk = uvd_table->entries[uvd_index].dclk; 546 seq_printf(m, "%u uvd vclk: %u dclk: %u\n", uvd_index, vclk, dclk); 547 } 548 } 549 550 seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); 551 if (!pi->vce_power_gated) { 552 if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) { 553 seq_printf(m, "invalid vce dpm level %d\n", vce_index); 554 } else { 555 ecclk = vce_table->entries[vce_index].ecclk; 556 seq_printf(m, "%u vce ecclk: %u\n", vce_index, ecclk); 557 } 558 } 559} 560 561static void cz_dpm_print_power_state(struct amdgpu_device *adev, 562 struct amdgpu_ps *rps) 563{ 564 int i; 565 struct cz_ps *ps = cz_get_ps(rps); 566 567 amdgpu_dpm_print_class_info(rps->class, rps->class2); 568 amdgpu_dpm_print_cap_info(rps->caps); 569 570 DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 571 for (i = 0; i < ps->num_levels; i++) { 572 struct cz_pl *pl = &ps->levels[i]; 573 574 DRM_INFO("\t\tpower level %d sclk: %u vddc: %u\n", 575 i, pl->sclk, 576 cz_convert_8bit_index_to_voltage(adev, pl->vddc_index)); 577 } 578 579 amdgpu_dpm_print_ps_status(adev, rps); 580} 581 582static void cz_dpm_set_funcs(struct amdgpu_device *adev); 583 584static int cz_dpm_early_init(void *handle) 585{ 586 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 587 588 cz_dpm_set_funcs(adev); 589 590 return 0; 591} 592 593 594static int cz_dpm_late_init(void *handle) 595{ 596 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 597 598 if (amdgpu_dpm) { 599 int ret; 600 /* init the sysfs and debugfs files late */ 601 ret = amdgpu_pm_sysfs_init(adev); 602 if (ret) 603 return ret; 604 605 /* powerdown unused blocks for now */ 606 cz_dpm_powergate_uvd(adev, true); 607 cz_dpm_powergate_vce(adev, true); 608 } 609 610 return 0; 611} 612 613static int cz_dpm_sw_init(void *handle) 614{ 615 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 616 int ret = 0; 617 /* fix me to add thermal support TODO */ 618 619 /* default to balanced state */ 620 adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; 621 adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; 622 adev->pm.dpm.forced_level = AMDGPU_DPM_FORCED_LEVEL_AUTO; 623 adev->pm.default_sclk = adev->clock.default_sclk; 624 adev->pm.default_mclk = adev->clock.default_mclk; 625 adev->pm.current_sclk = adev->clock.default_sclk; 626 adev->pm.current_mclk = adev->clock.default_mclk; 627 adev->pm.int_thermal_type = THERMAL_TYPE_NONE; 628 629 if (amdgpu_dpm == 0) 630 return 0; 631 632 mutex_lock(&adev->pm.mutex); 633 ret = cz_dpm_init(adev); 634 if (ret) 635 goto dpm_init_failed; 636 637 adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; 638 if (amdgpu_dpm == 1) 639 amdgpu_pm_print_power_states(adev); 640 641 mutex_unlock(&adev->pm.mutex); 642 DRM_INFO("amdgpu: dpm initialized\n"); 643 644 return 0; 645 646dpm_init_failed: 647 cz_dpm_fini(adev); 648 mutex_unlock(&adev->pm.mutex); 649 DRM_ERROR("amdgpu: dpm initialization failed\n"); 650 651 return ret; 652} 653 654static int cz_dpm_sw_fini(void *handle) 655{ 656 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 657 658 mutex_lock(&adev->pm.mutex); 659 amdgpu_pm_sysfs_fini(adev); 660 cz_dpm_fini(adev); 661 mutex_unlock(&adev->pm.mutex); 662 663 return 0; 664} 665 666static void cz_reset_ap_mask(struct amdgpu_device *adev) 667{ 668 struct cz_power_info *pi = cz_get_pi(adev); 669 670 pi->active_process_mask = 0; 671 672} 673 674static int cz_dpm_download_pptable_from_smu(struct amdgpu_device *adev, 675 void **table) 676{ 677 int ret = 0; 678 679 ret = cz_smu_download_pptable(adev, table); 680 681 return ret; 682} 683 684static int cz_dpm_upload_pptable_to_smu(struct amdgpu_device *adev) 685{ 686 struct cz_power_info *pi = cz_get_pi(adev); 687 struct SMU8_Fusion_ClkTable *clock_table; 688 struct atom_clock_dividers dividers; 689 void *table = NULL; 690 uint8_t i = 0; 691 int ret = 0; 692 693 struct amdgpu_clock_voltage_dependency_table *vddc_table = 694 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 695 struct amdgpu_clock_voltage_dependency_table *vddgfx_table = 696 &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk; 697 struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = 698 &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 699 struct amdgpu_vce_clock_voltage_dependency_table *vce_table = 700 &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 701 struct amdgpu_clock_voltage_dependency_table *acp_table = 702 &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 703 704 if (!pi->need_pptable_upload) 705 return 0; 706 707 ret = cz_dpm_download_pptable_from_smu(adev, &table); 708 if (ret) { 709 DRM_ERROR("amdgpu: Failed to get power play table from SMU!\n"); 710 return -EINVAL; 711 } 712 713 clock_table = (struct SMU8_Fusion_ClkTable *)table; 714 /* patch clock table */ 715 if (vddc_table->count > CZ_MAX_HARDWARE_POWERLEVELS || 716 vddgfx_table->count > CZ_MAX_HARDWARE_POWERLEVELS || 717 uvd_table->count > CZ_MAX_HARDWARE_POWERLEVELS || 718 vce_table->count > CZ_MAX_HARDWARE_POWERLEVELS || 719 acp_table->count > CZ_MAX_HARDWARE_POWERLEVELS) { 720 DRM_ERROR("amdgpu: Invalid Clock Voltage Dependency Table!\n"); 721 return -EINVAL; 722 } 723 724 for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) { 725 726 /* vddc sclk */ 727 clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid = 728 (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0; 729 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency = 730 (i < vddc_table->count) ? vddc_table->entries[i].clk : 0; 731 ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 732 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency, 733 false, ÷rs); 734 if (ret) 735 return ret; 736 clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid = 737 (uint8_t)dividers.post_divider; 738 739 /* vddgfx sclk */ 740 clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid = 741 (i < vddgfx_table->count) ? (uint8_t)vddgfx_table->entries[i].v : 0; 742 743 /* acp breakdown */ 744 clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid = 745 (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0; 746 clock_table->AclkBreakdownTable.ClkLevel[i].Frequency = 747 (i < acp_table->count) ? acp_table->entries[i].clk : 0; 748 ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 749 clock_table->SclkBreakdownTable.ClkLevel[i].Frequency, 750 false, ÷rs); 751 if (ret) 752 return ret; 753 clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid = 754 (uint8_t)dividers.post_divider; 755 756 /* uvd breakdown */ 757 clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid = 758 (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; 759 clock_table->VclkBreakdownTable.ClkLevel[i].Frequency = 760 (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0; 761 ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 762 clock_table->VclkBreakdownTable.ClkLevel[i].Frequency, 763 false, ÷rs); 764 if (ret) 765 return ret; 766 clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid = 767 (uint8_t)dividers.post_divider; 768 769 clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid = 770 (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; 771 clock_table->DclkBreakdownTable.ClkLevel[i].Frequency = 772 (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0; 773 ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 774 clock_table->DclkBreakdownTable.ClkLevel[i].Frequency, 775 false, ÷rs); 776 if (ret) 777 return ret; 778 clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid = 779 (uint8_t)dividers.post_divider; 780 781 /* vce breakdown */ 782 clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid = 783 (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0; 784 clock_table->EclkBreakdownTable.ClkLevel[i].Frequency = 785 (i < vce_table->count) ? vce_table->entries[i].ecclk : 0; 786 ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, 787 clock_table->EclkBreakdownTable.ClkLevel[i].Frequency, 788 false, ÷rs); 789 if (ret) 790 return ret; 791 clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid = 792 (uint8_t)dividers.post_divider; 793 } 794 795 /* its time to upload to SMU */ 796 ret = cz_smu_upload_pptable(adev); 797 if (ret) { 798 DRM_ERROR("amdgpu: Failed to put power play table to SMU!\n"); 799 return ret; 800 } 801 802 return 0; 803} 804 805static void cz_init_sclk_limit(struct amdgpu_device *adev) 806{ 807 struct cz_power_info *pi = cz_get_pi(adev); 808 struct amdgpu_clock_voltage_dependency_table *table = 809 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 810 uint32_t clock = 0, level; 811 812 if (!table || !table->count) { 813 DRM_ERROR("Invalid Voltage Dependency table.\n"); 814 return; 815 } 816 817 pi->sclk_dpm.soft_min_clk = 0; 818 pi->sclk_dpm.hard_min_clk = 0; 819 cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxSclkLevel); 820 level = cz_get_argument(adev); 821 if (level < table->count) 822 clock = table->entries[level].clk; 823 else { 824 DRM_ERROR("Invalid SLCK Voltage Dependency table entry.\n"); 825 clock = table->entries[table->count - 1].clk; 826 } 827 828 pi->sclk_dpm.soft_max_clk = clock; 829 pi->sclk_dpm.hard_max_clk = clock; 830 831} 832 833static void cz_init_uvd_limit(struct amdgpu_device *adev) 834{ 835 struct cz_power_info *pi = cz_get_pi(adev); 836 struct amdgpu_uvd_clock_voltage_dependency_table *table = 837 &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; 838 uint32_t clock = 0, level; 839 840 if (!table || !table->count) { 841 DRM_ERROR("Invalid Voltage Dependency table.\n"); 842 return; 843 } 844 845 pi->uvd_dpm.soft_min_clk = 0; 846 pi->uvd_dpm.hard_min_clk = 0; 847 cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxUvdLevel); 848 level = cz_get_argument(adev); 849 if (level < table->count) 850 clock = table->entries[level].vclk; 851 else { 852 DRM_ERROR("Invalid UVD Voltage Dependency table entry.\n"); 853 clock = table->entries[table->count - 1].vclk; 854 } 855 856 pi->uvd_dpm.soft_max_clk = clock; 857 pi->uvd_dpm.hard_max_clk = clock; 858 859} 860 861static void cz_init_vce_limit(struct amdgpu_device *adev) 862{ 863 struct cz_power_info *pi = cz_get_pi(adev); 864 struct amdgpu_vce_clock_voltage_dependency_table *table = 865 &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 866 uint32_t clock = 0, level; 867 868 if (!table || !table->count) { 869 DRM_ERROR("Invalid Voltage Dependency table.\n"); 870 return; 871 } 872 873 pi->vce_dpm.soft_min_clk = table->entries[0].ecclk; 874 pi->vce_dpm.hard_min_clk = table->entries[0].ecclk; 875 cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxEclkLevel); 876 level = cz_get_argument(adev); 877 if (level < table->count) 878 clock = table->entries[level].ecclk; 879 else { 880 /* future BIOS would fix this error */ 881 DRM_ERROR("Invalid VCE Voltage Dependency table entry.\n"); 882 clock = table->entries[table->count - 1].ecclk; 883 } 884 885 pi->vce_dpm.soft_max_clk = clock; 886 pi->vce_dpm.hard_max_clk = clock; 887 888} 889 890static void cz_init_acp_limit(struct amdgpu_device *adev) 891{ 892 struct cz_power_info *pi = cz_get_pi(adev); 893 struct amdgpu_clock_voltage_dependency_table *table = 894 &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; 895 uint32_t clock = 0, level; 896 897 if (!table || !table->count) { 898 DRM_ERROR("Invalid Voltage Dependency table.\n"); 899 return; 900 } 901 902 pi->acp_dpm.soft_min_clk = 0; 903 pi->acp_dpm.hard_min_clk = 0; 904 cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxAclkLevel); 905 level = cz_get_argument(adev); 906 if (level < table->count) 907 clock = table->entries[level].clk; 908 else { 909 DRM_ERROR("Invalid ACP Voltage Dependency table entry.\n"); 910 clock = table->entries[table->count - 1].clk; 911 } 912 913 pi->acp_dpm.soft_max_clk = clock; 914 pi->acp_dpm.hard_max_clk = clock; 915 916} 917 918static void cz_init_pg_state(struct amdgpu_device *adev) 919{ 920 struct cz_power_info *pi = cz_get_pi(adev); 921 922 pi->uvd_power_gated = false; 923 pi->vce_power_gated = false; 924 pi->acp_power_gated = false; 925 926} 927 928static void cz_init_sclk_threshold(struct amdgpu_device *adev) 929{ 930 struct cz_power_info *pi = cz_get_pi(adev); 931 932 pi->low_sclk_interrupt_threshold = 0; 933 934} 935 936static void cz_dpm_setup_asic(struct amdgpu_device *adev) 937{ 938 cz_reset_ap_mask(adev); 939 cz_dpm_upload_pptable_to_smu(adev); 940 cz_init_sclk_limit(adev); 941 cz_init_uvd_limit(adev); 942 cz_init_vce_limit(adev); 943 cz_init_acp_limit(adev); 944 cz_init_pg_state(adev); 945 cz_init_sclk_threshold(adev); 946 947} 948 949static bool cz_check_smu_feature(struct amdgpu_device *adev, 950 uint32_t feature) 951{ 952 uint32_t smu_feature = 0; 953 int ret; 954 955 ret = cz_send_msg_to_smc_with_parameter(adev, 956 PPSMC_MSG_GetFeatureStatus, 0); 957 if (ret) { 958 DRM_ERROR("Failed to get SMU features from SMC.\n"); 959 return false; 960 } else { 961 smu_feature = cz_get_argument(adev); 962 if (feature & smu_feature) 963 return true; 964 } 965 966 return false; 967} 968 969static bool cz_check_for_dpm_enabled(struct amdgpu_device *adev) 970{ 971 if (cz_check_smu_feature(adev, 972 SMU_EnabledFeatureScoreboard_SclkDpmOn)) 973 return true; 974 975 return false; 976} 977 978static void cz_program_voting_clients(struct amdgpu_device *adev) 979{ 980 WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, PPCZ_VOTINGRIGHTSCLIENTS_DFLT0); 981} 982 983static void cz_clear_voting_clients(struct amdgpu_device *adev) 984{ 985 WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0); 986} 987 988static int cz_start_dpm(struct amdgpu_device *adev) 989{ 990 int ret = 0; 991 992 if (amdgpu_dpm) { 993 ret = cz_send_msg_to_smc_with_parameter(adev, 994 PPSMC_MSG_EnableAllSmuFeatures, SCLK_DPM_MASK); 995 if (ret) { 996 DRM_ERROR("SMU feature: SCLK_DPM enable failed\n"); 997 return -EINVAL; 998 } 999 } 1000 1001 return 0; 1002} 1003 1004static int cz_stop_dpm(struct amdgpu_device *adev) 1005{ 1006 int ret = 0; 1007 1008 if (amdgpu_dpm && adev->pm.dpm_enabled) { 1009 ret = cz_send_msg_to_smc_with_parameter(adev, 1010 PPSMC_MSG_DisableAllSmuFeatures, SCLK_DPM_MASK); 1011 if (ret) { 1012 DRM_ERROR("SMU feature: SCLK_DPM disable failed\n"); 1013 return -EINVAL; 1014 } 1015 } 1016 1017 return 0; 1018} 1019 1020static uint32_t cz_get_sclk_level(struct amdgpu_device *adev, 1021 uint32_t clock, uint16_t msg) 1022{ 1023 int i = 0; 1024 struct amdgpu_clock_voltage_dependency_table *table = 1025 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 1026 1027 switch (msg) { 1028 case PPSMC_MSG_SetSclkSoftMin: 1029 case PPSMC_MSG_SetSclkHardMin: 1030 for (i = 0; i < table->count; i++) 1031 if (clock <= table->entries[i].clk) 1032 break; 1033 if (i == table->count) 1034 i = table->count - 1; 1035 break; 1036 case PPSMC_MSG_SetSclkSoftMax: 1037 case PPSMC_MSG_SetSclkHardMax: 1038 for (i = table->count - 1; i >= 0; i--) 1039 if (clock >= table->entries[i].clk) 1040 break; 1041 if (i < 0) 1042 i = 0; 1043 break; 1044 default: 1045 break; 1046 } 1047 1048 return i; 1049} 1050 1051static uint32_t cz_get_eclk_level(struct amdgpu_device *adev, 1052 uint32_t clock, uint16_t msg) 1053{ 1054 int i = 0; 1055 struct amdgpu_vce_clock_voltage_dependency_table *table = 1056 &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 1057 1058 if (table->count == 0) 1059 return 0; 1060 1061 switch (msg) { 1062 case PPSMC_MSG_SetEclkSoftMin: 1063 case PPSMC_MSG_SetEclkHardMin: 1064 for (i = 0; i < table->count-1; i++) 1065 if (clock <= table->entries[i].ecclk) 1066 break; 1067 break; 1068 case PPSMC_MSG_SetEclkSoftMax: 1069 case PPSMC_MSG_SetEclkHardMax: 1070 for (i = table->count - 1; i > 0; i--) 1071 if (clock >= table->entries[i].ecclk) 1072 break; 1073 break; 1074 default: 1075 break; 1076 } 1077 1078 return i; 1079} 1080 1081static int cz_program_bootup_state(struct amdgpu_device *adev) 1082{ 1083 struct cz_power_info *pi = cz_get_pi(adev); 1084 uint32_t soft_min_clk = 0; 1085 uint32_t soft_max_clk = 0; 1086 int ret = 0; 1087 1088 pi->sclk_dpm.soft_min_clk = pi->sys_info.bootup_sclk; 1089 pi->sclk_dpm.soft_max_clk = pi->sys_info.bootup_sclk; 1090 1091 soft_min_clk = cz_get_sclk_level(adev, 1092 pi->sclk_dpm.soft_min_clk, 1093 PPSMC_MSG_SetSclkSoftMin); 1094 soft_max_clk = cz_get_sclk_level(adev, 1095 pi->sclk_dpm.soft_max_clk, 1096 PPSMC_MSG_SetSclkSoftMax); 1097 1098 ret = cz_send_msg_to_smc_with_parameter(adev, 1099 PPSMC_MSG_SetSclkSoftMin, soft_min_clk); 1100 if (ret) 1101 return -EINVAL; 1102 1103 ret = cz_send_msg_to_smc_with_parameter(adev, 1104 PPSMC_MSG_SetSclkSoftMax, soft_max_clk); 1105 if (ret) 1106 return -EINVAL; 1107 1108 return 0; 1109} 1110 1111/* TODO */ 1112static int cz_disable_cgpg(struct amdgpu_device *adev) 1113{ 1114 return 0; 1115} 1116 1117/* TODO */ 1118static int cz_enable_cgpg(struct amdgpu_device *adev) 1119{ 1120 return 0; 1121} 1122 1123/* TODO */ 1124static int cz_program_pt_config_registers(struct amdgpu_device *adev) 1125{ 1126 return 0; 1127} 1128 1129static void cz_do_enable_didt(struct amdgpu_device *adev, bool enable) 1130{ 1131 struct cz_power_info *pi = cz_get_pi(adev); 1132 uint32_t reg = 0; 1133 1134 if (pi->caps_sq_ramping) { 1135 reg = RREG32_DIDT(ixDIDT_SQ_CTRL0); 1136 if (enable) 1137 reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 1); 1138 else 1139 reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 0); 1140 WREG32_DIDT(ixDIDT_SQ_CTRL0, reg); 1141 } 1142 if (pi->caps_db_ramping) { 1143 reg = RREG32_DIDT(ixDIDT_DB_CTRL0); 1144 if (enable) 1145 reg = REG_SET_FIELD(reg, DIDT_DB_CTRL0, DIDT_CTRL_EN, 1); 1146 else 1147 reg = REG_SET_FIELD(reg, DIDT_DB_CTRL0, DIDT_CTRL_EN, 0); 1148 WREG32_DIDT(ixDIDT_DB_CTRL0, reg); 1149 } 1150 if (pi->caps_td_ramping) { 1151 reg = RREG32_DIDT(ixDIDT_TD_CTRL0); 1152 if (enable) 1153 reg = REG_SET_FIELD(reg, DIDT_TD_CTRL0, DIDT_CTRL_EN, 1); 1154 else 1155 reg = REG_SET_FIELD(reg, DIDT_TD_CTRL0, DIDT_CTRL_EN, 0); 1156 WREG32_DIDT(ixDIDT_TD_CTRL0, reg); 1157 } 1158 if (pi->caps_tcp_ramping) { 1159 reg = RREG32_DIDT(ixDIDT_TCP_CTRL0); 1160 if (enable) 1161 reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 1); 1162 else 1163 reg = REG_SET_FIELD(reg, DIDT_SQ_CTRL0, DIDT_CTRL_EN, 0); 1164 WREG32_DIDT(ixDIDT_TCP_CTRL0, reg); 1165 } 1166 1167} 1168 1169static int cz_enable_didt(struct amdgpu_device *adev, bool enable) 1170{ 1171 struct cz_power_info *pi = cz_get_pi(adev); 1172 int ret; 1173 1174 if (pi->caps_sq_ramping || pi->caps_db_ramping || 1175 pi->caps_td_ramping || pi->caps_tcp_ramping) { 1176 if (adev->gfx.gfx_current_status != AMDGPU_GFX_SAFE_MODE) { 1177 ret = cz_disable_cgpg(adev); 1178 if (ret) { 1179 DRM_ERROR("Pre Di/Dt disable cg/pg failed\n"); 1180 return -EINVAL; 1181 } 1182 adev->gfx.gfx_current_status = AMDGPU_GFX_SAFE_MODE; 1183 } 1184 1185 ret = cz_program_pt_config_registers(adev); 1186 if (ret) { 1187 DRM_ERROR("Di/Dt config failed\n"); 1188 return -EINVAL; 1189 } 1190 cz_do_enable_didt(adev, enable); 1191 1192 if (adev->gfx.gfx_current_status == AMDGPU_GFX_SAFE_MODE) { 1193 ret = cz_enable_cgpg(adev); 1194 if (ret) { 1195 DRM_ERROR("Post Di/Dt enable cg/pg failed\n"); 1196 return -EINVAL; 1197 } 1198 adev->gfx.gfx_current_status = AMDGPU_GFX_NORMAL_MODE; 1199 } 1200 } 1201 1202 return 0; 1203} 1204 1205/* TODO */ 1206static void cz_reset_acp_boot_level(struct amdgpu_device *adev) 1207{ 1208} 1209 1210static void cz_update_current_ps(struct amdgpu_device *adev, 1211 struct amdgpu_ps *rps) 1212{ 1213 struct cz_power_info *pi = cz_get_pi(adev); 1214 struct cz_ps *ps = cz_get_ps(rps); 1215 1216 pi->current_ps = *ps; 1217 pi->current_rps = *rps; 1218 pi->current_rps.ps_priv = ps; 1219 1220} 1221 1222static void cz_update_requested_ps(struct amdgpu_device *adev, 1223 struct amdgpu_ps *rps) 1224{ 1225 struct cz_power_info *pi = cz_get_pi(adev); 1226 struct cz_ps *ps = cz_get_ps(rps); 1227 1228 pi->requested_ps = *ps; 1229 pi->requested_rps = *rps; 1230 pi->requested_rps.ps_priv = ps; 1231 1232} 1233 1234/* PP arbiter support needed TODO */ 1235static void cz_apply_state_adjust_rules(struct amdgpu_device *adev, 1236 struct amdgpu_ps *new_rps, 1237 struct amdgpu_ps *old_rps) 1238{ 1239 struct cz_ps *ps = cz_get_ps(new_rps); 1240 struct cz_power_info *pi = cz_get_pi(adev); 1241 struct amdgpu_clock_and_voltage_limits *limits = 1242 &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; 1243 /* 10kHz memory clock */ 1244 uint32_t mclk = 0; 1245 1246 ps->force_high = false; 1247 ps->need_dfs_bypass = true; 1248 pi->video_start = new_rps->dclk || new_rps->vclk || 1249 new_rps->evclk || new_rps->ecclk; 1250 1251 if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 1252 ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) 1253 pi->battery_state = true; 1254 else 1255 pi->battery_state = false; 1256 1257 if (pi->caps_stable_power_state) 1258 mclk = limits->mclk; 1259 1260 if (mclk > pi->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORY_CLOCK - 1]) 1261 ps->force_high = true; 1262 1263} 1264 1265static int cz_dpm_enable(struct amdgpu_device *adev) 1266{ 1267 const char *chip_name; 1268 int ret = 0; 1269 1270 /* renable will hang up SMU, so check first */ 1271 if (cz_check_for_dpm_enabled(adev)) 1272 return -EINVAL; 1273 1274 cz_program_voting_clients(adev); 1275 1276 switch (adev->asic_type) { 1277 case CHIP_CARRIZO: 1278 chip_name = "carrizo"; 1279 break; 1280 case CHIP_STONEY: 1281 chip_name = "stoney"; 1282 break; 1283 default: 1284 BUG(); 1285 } 1286 1287 1288 ret = cz_start_dpm(adev); 1289 if (ret) { 1290 DRM_ERROR("%s DPM enable failed\n", chip_name); 1291 return -EINVAL; 1292 } 1293 1294 ret = cz_program_bootup_state(adev); 1295 if (ret) { 1296 DRM_ERROR("%s bootup state program failed\n", chip_name); 1297 return -EINVAL; 1298 } 1299 1300 ret = cz_enable_didt(adev, true); 1301 if (ret) { 1302 DRM_ERROR("%s enable di/dt failed\n", chip_name); 1303 return -EINVAL; 1304 } 1305 1306 cz_reset_acp_boot_level(adev); 1307 1308 cz_update_current_ps(adev, adev->pm.dpm.boot_ps); 1309 1310 return 0; 1311} 1312 1313static int cz_dpm_hw_init(void *handle) 1314{ 1315 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1316 int ret = 0; 1317 1318 mutex_lock(&adev->pm.mutex); 1319 1320 /* smu init only needs to be called at startup, not resume. 1321 * It should be in sw_init, but requires the fw info gathered 1322 * in sw_init from other IP modules. 1323 */ 1324 ret = cz_smu_init(adev); 1325 if (ret) { 1326 DRM_ERROR("amdgpu: smc initialization failed\n"); 1327 mutex_unlock(&adev->pm.mutex); 1328 return ret; 1329 } 1330 1331 /* do the actual fw loading */ 1332 ret = cz_smu_start(adev); 1333 if (ret) { 1334 DRM_ERROR("amdgpu: smc start failed\n"); 1335 mutex_unlock(&adev->pm.mutex); 1336 return ret; 1337 } 1338 1339 if (!amdgpu_dpm) { 1340 adev->pm.dpm_enabled = false; 1341 mutex_unlock(&adev->pm.mutex); 1342 return ret; 1343 } 1344 1345 /* cz dpm setup asic */ 1346 cz_dpm_setup_asic(adev); 1347 1348 /* cz dpm enable */ 1349 ret = cz_dpm_enable(adev); 1350 if (ret) 1351 adev->pm.dpm_enabled = false; 1352 else 1353 adev->pm.dpm_enabled = true; 1354 1355 mutex_unlock(&adev->pm.mutex); 1356 1357 return 0; 1358} 1359 1360static int cz_dpm_disable(struct amdgpu_device *adev) 1361{ 1362 int ret = 0; 1363 1364 if (!cz_check_for_dpm_enabled(adev)) 1365 return -EINVAL; 1366 1367 ret = cz_enable_didt(adev, false); 1368 if (ret) { 1369 DRM_ERROR("disable di/dt failed\n"); 1370 return -EINVAL; 1371 } 1372 1373 /* powerup blocks */ 1374 cz_dpm_powergate_uvd(adev, false); 1375 cz_dpm_powergate_vce(adev, false); 1376 1377 cz_clear_voting_clients(adev); 1378 cz_stop_dpm(adev); 1379 cz_update_current_ps(adev, adev->pm.dpm.boot_ps); 1380 1381 return 0; 1382} 1383 1384static int cz_dpm_hw_fini(void *handle) 1385{ 1386 int ret = 0; 1387 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1388 1389 mutex_lock(&adev->pm.mutex); 1390 1391 /* smu fini only needs to be called at teardown, not suspend. 1392 * It should be in sw_fini, but we put it here for symmetry 1393 * with smu init. 1394 */ 1395 cz_smu_fini(adev); 1396 1397 if (adev->pm.dpm_enabled) { 1398 ret = cz_dpm_disable(adev); 1399 1400 adev->pm.dpm.current_ps = 1401 adev->pm.dpm.requested_ps = 1402 adev->pm.dpm.boot_ps; 1403 } 1404 1405 adev->pm.dpm_enabled = false; 1406 1407 mutex_unlock(&adev->pm.mutex); 1408 1409 return ret; 1410} 1411 1412static int cz_dpm_suspend(void *handle) 1413{ 1414 int ret = 0; 1415 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1416 1417 if (adev->pm.dpm_enabled) { 1418 mutex_lock(&adev->pm.mutex); 1419 1420 ret = cz_dpm_disable(adev); 1421 1422 adev->pm.dpm.current_ps = 1423 adev->pm.dpm.requested_ps = 1424 adev->pm.dpm.boot_ps; 1425 1426 mutex_unlock(&adev->pm.mutex); 1427 } 1428 1429 return ret; 1430} 1431 1432static int cz_dpm_resume(void *handle) 1433{ 1434 int ret = 0; 1435 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 1436 1437 mutex_lock(&adev->pm.mutex); 1438 1439 /* do the actual fw loading */ 1440 ret = cz_smu_start(adev); 1441 if (ret) { 1442 DRM_ERROR("amdgpu: smc start failed\n"); 1443 mutex_unlock(&adev->pm.mutex); 1444 return ret; 1445 } 1446 1447 if (!amdgpu_dpm) { 1448 adev->pm.dpm_enabled = false; 1449 mutex_unlock(&adev->pm.mutex); 1450 return ret; 1451 } 1452 1453 /* cz dpm setup asic */ 1454 cz_dpm_setup_asic(adev); 1455 1456 /* cz dpm enable */ 1457 ret = cz_dpm_enable(adev); 1458 if (ret) 1459 adev->pm.dpm_enabled = false; 1460 else 1461 adev->pm.dpm_enabled = true; 1462 1463 mutex_unlock(&adev->pm.mutex); 1464 /* upon resume, re-compute the clocks */ 1465 if (adev->pm.dpm_enabled) 1466 amdgpu_pm_compute_clocks(adev); 1467 1468 return 0; 1469} 1470 1471static int cz_dpm_set_clockgating_state(void *handle, 1472 enum amd_clockgating_state state) 1473{ 1474 return 0; 1475} 1476 1477static int cz_dpm_set_powergating_state(void *handle, 1478 enum amd_powergating_state state) 1479{ 1480 return 0; 1481} 1482 1483/* borrowed from KV, need future unify */ 1484static int cz_dpm_get_temperature(struct amdgpu_device *adev) 1485{ 1486 int actual_temp = 0; 1487 uint32_t temp = RREG32_SMC(0xC0300E0C); 1488 1489 if (temp) 1490 actual_temp = 1000 * ((temp / 8) - 49); 1491 1492 return actual_temp; 1493} 1494 1495static int cz_dpm_pre_set_power_state(struct amdgpu_device *adev) 1496{ 1497 struct cz_power_info *pi = cz_get_pi(adev); 1498 struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; 1499 struct amdgpu_ps *new_ps = &requested_ps; 1500 1501 cz_update_requested_ps(adev, new_ps); 1502 cz_apply_state_adjust_rules(adev, &pi->requested_rps, 1503 &pi->current_rps); 1504 1505 return 0; 1506} 1507 1508static int cz_dpm_update_sclk_limit(struct amdgpu_device *adev) 1509{ 1510 struct cz_power_info *pi = cz_get_pi(adev); 1511 struct amdgpu_clock_and_voltage_limits *limits = 1512 &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; 1513 uint32_t clock, stable_ps_clock = 0; 1514 1515 clock = pi->sclk_dpm.soft_min_clk; 1516 1517 if (pi->caps_stable_power_state) { 1518 stable_ps_clock = limits->sclk * 75 / 100; 1519 if (clock < stable_ps_clock) 1520 clock = stable_ps_clock; 1521 } 1522 1523 if (clock != pi->sclk_dpm.soft_min_clk) { 1524 pi->sclk_dpm.soft_min_clk = clock; 1525 cz_send_msg_to_smc_with_parameter(adev, 1526 PPSMC_MSG_SetSclkSoftMin, 1527 cz_get_sclk_level(adev, clock, 1528 PPSMC_MSG_SetSclkSoftMin)); 1529 } 1530 1531 if (pi->caps_stable_power_state && 1532 pi->sclk_dpm.soft_max_clk != clock) { 1533 pi->sclk_dpm.soft_max_clk = clock; 1534 cz_send_msg_to_smc_with_parameter(adev, 1535 PPSMC_MSG_SetSclkSoftMax, 1536 cz_get_sclk_level(adev, clock, 1537 PPSMC_MSG_SetSclkSoftMax)); 1538 } else { 1539 cz_send_msg_to_smc_with_parameter(adev, 1540 PPSMC_MSG_SetSclkSoftMax, 1541 cz_get_sclk_level(adev, 1542 pi->sclk_dpm.soft_max_clk, 1543 PPSMC_MSG_SetSclkSoftMax)); 1544 } 1545 1546 return 0; 1547} 1548 1549static int cz_dpm_set_deep_sleep_sclk_threshold(struct amdgpu_device *adev) 1550{ 1551 int ret = 0; 1552 struct cz_power_info *pi = cz_get_pi(adev); 1553 1554 if (pi->caps_sclk_ds) { 1555 cz_send_msg_to_smc_with_parameter(adev, 1556 PPSMC_MSG_SetMinDeepSleepSclk, 1557 CZ_MIN_DEEP_SLEEP_SCLK); 1558 } 1559 1560 return ret; 1561} 1562 1563/* ?? without dal support, is this still needed in setpowerstate list*/ 1564static int cz_dpm_set_watermark_threshold(struct amdgpu_device *adev) 1565{ 1566 int ret = 0; 1567 struct cz_power_info *pi = cz_get_pi(adev); 1568 1569 cz_send_msg_to_smc_with_parameter(adev, 1570 PPSMC_MSG_SetWatermarkFrequency, 1571 pi->sclk_dpm.soft_max_clk); 1572 1573 return ret; 1574} 1575 1576static int cz_dpm_enable_nbdpm(struct amdgpu_device *adev) 1577{ 1578 int ret = 0; 1579 struct cz_power_info *pi = cz_get_pi(adev); 1580 1581 /* also depend on dal NBPStateDisableRequired */ 1582 if (pi->nb_dpm_enabled_by_driver && !pi->nb_dpm_enabled) { 1583 ret = cz_send_msg_to_smc_with_parameter(adev, 1584 PPSMC_MSG_EnableAllSmuFeatures, 1585 NB_DPM_MASK); 1586 if (ret) { 1587 DRM_ERROR("amdgpu: nb dpm enable failed\n"); 1588 return ret; 1589 } 1590 pi->nb_dpm_enabled = true; 1591 } 1592 1593 return ret; 1594} 1595 1596static void cz_dpm_nbdpm_lm_pstate_enable(struct amdgpu_device *adev, 1597 bool enable) 1598{ 1599 if (enable) 1600 cz_send_msg_to_smc(adev, PPSMC_MSG_EnableLowMemoryPstate); 1601 else 1602 cz_send_msg_to_smc(adev, PPSMC_MSG_DisableLowMemoryPstate); 1603 1604} 1605 1606static int cz_dpm_update_low_memory_pstate(struct amdgpu_device *adev) 1607{ 1608 int ret = 0; 1609 struct cz_power_info *pi = cz_get_pi(adev); 1610 struct cz_ps *ps = &pi->requested_ps; 1611 1612 if (pi->sys_info.nb_dpm_enable) { 1613 if (ps->force_high) 1614 cz_dpm_nbdpm_lm_pstate_enable(adev, false); 1615 else 1616 cz_dpm_nbdpm_lm_pstate_enable(adev, true); 1617 } 1618 1619 return ret; 1620} 1621 1622/* with dpm enabled */ 1623static int cz_dpm_set_power_state(struct amdgpu_device *adev) 1624{ 1625 int ret = 0; 1626 1627 cz_dpm_update_sclk_limit(adev); 1628 cz_dpm_set_deep_sleep_sclk_threshold(adev); 1629 cz_dpm_set_watermark_threshold(adev); 1630 cz_dpm_enable_nbdpm(adev); 1631 cz_dpm_update_low_memory_pstate(adev); 1632 1633 return ret; 1634} 1635 1636static void cz_dpm_post_set_power_state(struct amdgpu_device *adev) 1637{ 1638 struct cz_power_info *pi = cz_get_pi(adev); 1639 struct amdgpu_ps *ps = &pi->requested_rps; 1640 1641 cz_update_current_ps(adev, ps); 1642 1643} 1644 1645static int cz_dpm_force_highest(struct amdgpu_device *adev) 1646{ 1647 struct cz_power_info *pi = cz_get_pi(adev); 1648 int ret = 0; 1649 1650 if (pi->sclk_dpm.soft_min_clk != pi->sclk_dpm.soft_max_clk) { 1651 pi->sclk_dpm.soft_min_clk = 1652 pi->sclk_dpm.soft_max_clk; 1653 ret = cz_send_msg_to_smc_with_parameter(adev, 1654 PPSMC_MSG_SetSclkSoftMin, 1655 cz_get_sclk_level(adev, 1656 pi->sclk_dpm.soft_min_clk, 1657 PPSMC_MSG_SetSclkSoftMin)); 1658 if (ret) 1659 return ret; 1660 } 1661 1662 return ret; 1663} 1664 1665static int cz_dpm_force_lowest(struct amdgpu_device *adev) 1666{ 1667 struct cz_power_info *pi = cz_get_pi(adev); 1668 int ret = 0; 1669 1670 if (pi->sclk_dpm.soft_max_clk != pi->sclk_dpm.soft_min_clk) { 1671 pi->sclk_dpm.soft_max_clk = pi->sclk_dpm.soft_min_clk; 1672 ret = cz_send_msg_to_smc_with_parameter(adev, 1673 PPSMC_MSG_SetSclkSoftMax, 1674 cz_get_sclk_level(adev, 1675 pi->sclk_dpm.soft_max_clk, 1676 PPSMC_MSG_SetSclkSoftMax)); 1677 if (ret) 1678 return ret; 1679 } 1680 1681 return ret; 1682} 1683 1684static uint32_t cz_dpm_get_max_sclk_level(struct amdgpu_device *adev) 1685{ 1686 struct cz_power_info *pi = cz_get_pi(adev); 1687 1688 if (!pi->max_sclk_level) { 1689 cz_send_msg_to_smc(adev, PPSMC_MSG_GetMaxSclkLevel); 1690 pi->max_sclk_level = cz_get_argument(adev) + 1; 1691 } 1692 1693 if (pi->max_sclk_level > CZ_MAX_HARDWARE_POWERLEVELS) { 1694 DRM_ERROR("Invalid max sclk level!\n"); 1695 return -EINVAL; 1696 } 1697 1698 return pi->max_sclk_level; 1699} 1700 1701static int cz_dpm_unforce_dpm_levels(struct amdgpu_device *adev) 1702{ 1703 struct cz_power_info *pi = cz_get_pi(adev); 1704 struct amdgpu_clock_voltage_dependency_table *dep_table = 1705 &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; 1706 uint32_t level = 0; 1707 int ret = 0; 1708 1709 pi->sclk_dpm.soft_min_clk = dep_table->entries[0].clk; 1710 level = cz_dpm_get_max_sclk_level(adev) - 1; 1711 if (level < dep_table->count) 1712 pi->sclk_dpm.soft_max_clk = dep_table->entries[level].clk; 1713 else 1714 pi->sclk_dpm.soft_max_clk = 1715 dep_table->entries[dep_table->count - 1].clk; 1716 1717 /* get min/max sclk soft value 1718 * notify SMU to execute */ 1719 ret = cz_send_msg_to_smc_with_parameter(adev, 1720 PPSMC_MSG_SetSclkSoftMin, 1721 cz_get_sclk_level(adev, 1722 pi->sclk_dpm.soft_min_clk, 1723 PPSMC_MSG_SetSclkSoftMin)); 1724 if (ret) 1725 return ret; 1726 1727 ret = cz_send_msg_to_smc_with_parameter(adev, 1728 PPSMC_MSG_SetSclkSoftMax, 1729 cz_get_sclk_level(adev, 1730 pi->sclk_dpm.soft_max_clk, 1731 PPSMC_MSG_SetSclkSoftMax)); 1732 if (ret) 1733 return ret; 1734 1735 DRM_DEBUG("DPM unforce state min=%d, max=%d.\n", 1736 pi->sclk_dpm.soft_min_clk, 1737 pi->sclk_dpm.soft_max_clk); 1738 1739 return 0; 1740} 1741 1742static int cz_dpm_force_dpm_level(struct amdgpu_device *adev, 1743 enum amdgpu_dpm_forced_level level) 1744{ 1745 int ret = 0; 1746 1747 switch (level) { 1748 case AMDGPU_DPM_FORCED_LEVEL_HIGH: 1749 ret = cz_dpm_unforce_dpm_levels(adev); 1750 if (ret) 1751 return ret; 1752 ret = cz_dpm_force_highest(adev); 1753 if (ret) 1754 return ret; 1755 break; 1756 case AMDGPU_DPM_FORCED_LEVEL_LOW: 1757 ret = cz_dpm_unforce_dpm_levels(adev); 1758 if (ret) 1759 return ret; 1760 ret = cz_dpm_force_lowest(adev); 1761 if (ret) 1762 return ret; 1763 break; 1764 case AMDGPU_DPM_FORCED_LEVEL_AUTO: 1765 ret = cz_dpm_unforce_dpm_levels(adev); 1766 if (ret) 1767 return ret; 1768 break; 1769 default: 1770 break; 1771 } 1772 1773 adev->pm.dpm.forced_level = level; 1774 1775 return ret; 1776} 1777 1778/* fix me, display configuration change lists here 1779 * mostly dal related*/ 1780static void cz_dpm_display_configuration_changed(struct amdgpu_device *adev) 1781{ 1782} 1783 1784static uint32_t cz_dpm_get_sclk(struct amdgpu_device *adev, bool low) 1785{ 1786 struct cz_power_info *pi = cz_get_pi(adev); 1787 struct cz_ps *requested_state = cz_get_ps(&pi->requested_rps); 1788 1789 if (low) 1790 return requested_state->levels[0].sclk; 1791 else 1792 return requested_state->levels[requested_state->num_levels - 1].sclk; 1793 1794} 1795 1796static uint32_t cz_dpm_get_mclk(struct amdgpu_device *adev, bool low) 1797{ 1798 struct cz_power_info *pi = cz_get_pi(adev); 1799 1800 return pi->sys_info.bootup_uma_clk; 1801} 1802 1803static int cz_enable_uvd_dpm(struct amdgpu_device *adev, bool enable) 1804{ 1805 struct cz_power_info *pi = cz_get_pi(adev); 1806 int ret = 0; 1807 1808 if (enable && pi->caps_uvd_dpm ) { 1809 pi->dpm_flags |= DPMFlags_UVD_Enabled; 1810 DRM_DEBUG("UVD DPM Enabled.\n"); 1811 1812 ret = cz_send_msg_to_smc_with_parameter(adev, 1813 PPSMC_MSG_EnableAllSmuFeatures, UVD_DPM_MASK); 1814 } else { 1815 pi->dpm_flags &= ~DPMFlags_UVD_Enabled; 1816 DRM_DEBUG("UVD DPM Stopped\n"); 1817 1818 ret = cz_send_msg_to_smc_with_parameter(adev, 1819 PPSMC_MSG_DisableAllSmuFeatures, UVD_DPM_MASK); 1820 } 1821 1822 return ret; 1823} 1824 1825static int cz_update_uvd_dpm(struct amdgpu_device *adev, bool gate) 1826{ 1827 return cz_enable_uvd_dpm(adev, !gate); 1828} 1829 1830 1831static void cz_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) 1832{ 1833 struct cz_power_info *pi = cz_get_pi(adev); 1834 int ret; 1835 1836 if (pi->uvd_power_gated == gate) 1837 return; 1838 1839 pi->uvd_power_gated = gate; 1840 1841 if (gate) { 1842 if (pi->caps_uvd_pg) { 1843 /* disable clockgating so we can properly shut down the block */ 1844 ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, 1845 AMD_CG_STATE_UNGATE); 1846 /* shutdown the UVD block */ 1847 ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, 1848 AMD_PG_STATE_GATE); 1849 /* XXX: check for errors */ 1850 } 1851 cz_update_uvd_dpm(adev, gate); 1852 if (pi->caps_uvd_pg) 1853 /* power off the UVD block */ 1854 cz_send_msg_to_smc(adev, PPSMC_MSG_UVDPowerOFF); 1855 } else { 1856 if (pi->caps_uvd_pg) { 1857 /* power on the UVD block */ 1858 if (pi->uvd_dynamic_pg) 1859 cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 1); 1860 else 1861 cz_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_UVDPowerON, 0); 1862 /* re-init the UVD block */ 1863 ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, 1864 AMD_PG_STATE_UNGATE); 1865 /* enable clockgating. hw will dynamically gate/ungate clocks on the fly */ 1866 ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, 1867 AMD_CG_STATE_GATE); 1868 /* XXX: check for errors */ 1869 } 1870 cz_update_uvd_dpm(adev, gate); 1871 } 1872} 1873 1874static int cz_enable_vce_dpm(struct amdgpu_device *adev, bool enable) 1875{ 1876 struct cz_power_info *pi = cz_get_pi(adev); 1877 int ret = 0; 1878 1879 if (enable && pi->caps_vce_dpm) { 1880 pi->dpm_flags |= DPMFlags_VCE_Enabled; 1881 DRM_DEBUG("VCE DPM Enabled.\n"); 1882 1883 ret = cz_send_msg_to_smc_with_parameter(adev, 1884 PPSMC_MSG_EnableAllSmuFeatures, VCE_DPM_MASK); 1885 1886 } else { 1887 pi->dpm_flags &= ~DPMFlags_VCE_Enabled; 1888 DRM_DEBUG("VCE DPM Stopped\n"); 1889 1890 ret = cz_send_msg_to_smc_with_parameter(adev, 1891 PPSMC_MSG_DisableAllSmuFeatures, VCE_DPM_MASK); 1892 } 1893 1894 return ret; 1895} 1896 1897static int cz_update_vce_dpm(struct amdgpu_device *adev) 1898{ 1899 struct cz_power_info *pi = cz_get_pi(adev); 1900 struct amdgpu_vce_clock_voltage_dependency_table *table = 1901 &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 1902 1903 /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ 1904 if (pi->caps_stable_power_state) { 1905 pi->vce_dpm.hard_min_clk = table->entries[table->count-1].ecclk; 1906 1907 } else { /* non-stable p-state cases. without vce.Arbiter.EcclkHardMin */ 1908 pi->vce_dpm.hard_min_clk = table->entries[0].ecclk; 1909 } 1910 1911 cz_send_msg_to_smc_with_parameter(adev, 1912 PPSMC_MSG_SetEclkHardMin, 1913 cz_get_eclk_level(adev, 1914 pi->vce_dpm.hard_min_clk, 1915 PPSMC_MSG_SetEclkHardMin)); 1916 return 0; 1917} 1918 1919static void cz_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) 1920{ 1921 struct cz_power_info *pi = cz_get_pi(adev); 1922 1923 if (pi->caps_vce_pg) { 1924 if (pi->vce_power_gated != gate) { 1925 if (gate) { 1926 /* disable clockgating so we can properly shut down the block */ 1927 amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 1928 AMD_CG_STATE_UNGATE); 1929 /* shutdown the VCE block */ 1930 amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 1931 AMD_PG_STATE_GATE); 1932 1933 cz_enable_vce_dpm(adev, false); 1934 /* TODO: to figure out why vce can't be poweroff. */ 1935 /* cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerOFF); */ 1936 pi->vce_power_gated = true; 1937 } else { 1938 cz_send_msg_to_smc(adev, PPSMC_MSG_VCEPowerON); 1939 pi->vce_power_gated = false; 1940 1941 /* re-init the VCE block */ 1942 amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 1943 AMD_PG_STATE_UNGATE); 1944 /* enable clockgating. hw will dynamically gate/ungate clocks on the fly */ 1945 amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE, 1946 AMD_CG_STATE_GATE); 1947 1948 cz_update_vce_dpm(adev); 1949 cz_enable_vce_dpm(adev, true); 1950 } 1951 } else { 1952 if (! pi->vce_power_gated) { 1953 cz_update_vce_dpm(adev); 1954 } 1955 } 1956 } else { /*pi->caps_vce_pg*/ 1957 cz_update_vce_dpm(adev); 1958 cz_enable_vce_dpm(adev, true); 1959 } 1960 1961 return; 1962} 1963 1964const struct amd_ip_funcs cz_dpm_ip_funcs = { 1965 .early_init = cz_dpm_early_init, 1966 .late_init = cz_dpm_late_init, 1967 .sw_init = cz_dpm_sw_init, 1968 .sw_fini = cz_dpm_sw_fini, 1969 .hw_init = cz_dpm_hw_init, 1970 .hw_fini = cz_dpm_hw_fini, 1971 .suspend = cz_dpm_suspend, 1972 .resume = cz_dpm_resume, 1973 .is_idle = NULL, 1974 .wait_for_idle = NULL, 1975 .soft_reset = NULL, 1976 .print_status = NULL, 1977 .set_clockgating_state = cz_dpm_set_clockgating_state, 1978 .set_powergating_state = cz_dpm_set_powergating_state, 1979}; 1980 1981static const struct amdgpu_dpm_funcs cz_dpm_funcs = { 1982 .get_temperature = cz_dpm_get_temperature, 1983 .pre_set_power_state = cz_dpm_pre_set_power_state, 1984 .set_power_state = cz_dpm_set_power_state, 1985 .post_set_power_state = cz_dpm_post_set_power_state, 1986 .display_configuration_changed = cz_dpm_display_configuration_changed, 1987 .get_sclk = cz_dpm_get_sclk, 1988 .get_mclk = cz_dpm_get_mclk, 1989 .print_power_state = cz_dpm_print_power_state, 1990 .debugfs_print_current_performance_level = 1991 cz_dpm_debugfs_print_current_performance_level, 1992 .force_performance_level = cz_dpm_force_dpm_level, 1993 .vblank_too_short = NULL, 1994 .powergate_uvd = cz_dpm_powergate_uvd, 1995 .powergate_vce = cz_dpm_powergate_vce, 1996}; 1997 1998static void cz_dpm_set_funcs(struct amdgpu_device *adev) 1999{ 2000 if (NULL == adev->pm.funcs) 2001 adev->pm.funcs = &cz_dpm_funcs; 2002} 2003