1 /* 2 * Copyright 2015 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 "pp_debug.h" 24 #include <linux/types.h> 25 #include <linux/kernel.h> 26 #include <linux/slab.h> 27 #include <linux/pci.h> 28 29 #include <drm/amdgpu_drm.h> 30 #include "processpptables.h" 31 #include <atom-types.h> 32 #include <atombios.h> 33 #include "pptable.h" 34 #include "power_state.h" 35 #include "hwmgr.h" 36 #include "hardwaremanager.h" 37 38 39 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 40 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 41 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 42 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 43 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 44 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 45 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 46 #define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 47 48 #define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6 49 50 static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr, 51 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 52 { 53 uint16_t vce_table_offset = 0; 54 55 if (le16_to_cpu(powerplay_table->usTableSize) >= 56 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 57 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 58 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 59 60 if (powerplay_table3->usExtendendedHeaderOffset > 0) { 61 const ATOM_PPLIB_EXTENDEDHEADER *extended_header = 62 (const ATOM_PPLIB_EXTENDEDHEADER *) 63 (((unsigned long)powerplay_table3) + 64 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 65 if (le16_to_cpu(extended_header->usSize) >= 66 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) 67 vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset); 68 } 69 } 70 71 return vce_table_offset; 72 } 73 74 static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr, 75 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 76 { 77 uint16_t table_offset = get_vce_table_offset(hwmgr, 78 powerplay_table); 79 80 if (table_offset > 0) 81 return table_offset + 1; 82 83 return 0; 84 } 85 86 static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr, 87 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 88 { 89 uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, 90 powerplay_table); 91 uint16_t table_size = 0; 92 93 if (table_offset > 0) { 94 const VCEClockInfoArray *p = (const VCEClockInfoArray *) 95 (((unsigned long) powerplay_table) + table_offset); 96 table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo); 97 } 98 99 return table_size; 100 } 101 102 static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr, 103 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 104 { 105 uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, 106 powerplay_table); 107 108 if (table_offset > 0) 109 return table_offset + get_vce_clock_info_array_size(hwmgr, 110 powerplay_table); 111 112 return 0; 113 } 114 115 static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr, 116 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 117 { 118 uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 119 uint16_t table_size = 0; 120 121 if (table_offset > 0) { 122 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable = 123 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset); 124 125 table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record); 126 } 127 return table_size; 128 } 129 130 static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 131 { 132 uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 133 134 if (table_offset > 0) 135 return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table); 136 137 return 0; 138 } 139 140 static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table( 141 struct pp_hwmgr *hwmgr, 142 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 143 { 144 uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table); 145 146 if (table_offset > 0) 147 return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset); 148 149 return NULL; 150 } 151 152 static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr, 153 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 154 { 155 uint16_t uvd_table_offset = 0; 156 157 if (le16_to_cpu(powerplay_table->usTableSize) >= 158 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 159 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 160 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 161 if (powerplay_table3->usExtendendedHeaderOffset > 0) { 162 const ATOM_PPLIB_EXTENDEDHEADER *extended_header = 163 (const ATOM_PPLIB_EXTENDEDHEADER *) 164 (((unsigned long)powerplay_table3) + 165 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 166 if (le16_to_cpu(extended_header->usSize) >= 167 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) 168 uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset); 169 } 170 } 171 return uvd_table_offset; 172 } 173 174 static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr, 175 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 176 { 177 uint16_t table_offset = get_uvd_table_offset(hwmgr, 178 powerplay_table); 179 180 if (table_offset > 0) 181 return table_offset + 1; 182 return 0; 183 } 184 185 static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr, 186 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 187 { 188 uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, 189 powerplay_table); 190 uint16_t table_size = 0; 191 192 if (table_offset > 0) { 193 const UVDClockInfoArray *p = (const UVDClockInfoArray *) 194 (((unsigned long) powerplay_table) 195 + table_offset); 196 table_size = sizeof(UCHAR) + 197 p->ucNumEntries * sizeof(UVDClockInfo); 198 } 199 200 return table_size; 201 } 202 203 static uint16_t get_uvd_clock_voltage_limit_table_offset( 204 struct pp_hwmgr *hwmgr, 205 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 206 { 207 uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, 208 powerplay_table); 209 210 if (table_offset > 0) 211 return table_offset + 212 get_uvd_clock_info_array_size(hwmgr, powerplay_table); 213 214 return 0; 215 } 216 217 static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr, 218 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 219 { 220 uint16_t samu_table_offset = 0; 221 222 if (le16_to_cpu(powerplay_table->usTableSize) >= 223 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 224 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 225 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 226 if (powerplay_table3->usExtendendedHeaderOffset > 0) { 227 const ATOM_PPLIB_EXTENDEDHEADER *extended_header = 228 (const ATOM_PPLIB_EXTENDEDHEADER *) 229 (((unsigned long)powerplay_table3) + 230 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 231 if (le16_to_cpu(extended_header->usSize) >= 232 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) 233 samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset); 234 } 235 } 236 237 return samu_table_offset; 238 } 239 240 static uint16_t get_samu_clock_voltage_limit_table_offset( 241 struct pp_hwmgr *hwmgr, 242 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 243 { 244 uint16_t table_offset = get_samu_table_offset(hwmgr, 245 powerplay_table); 246 247 if (table_offset > 0) 248 return table_offset + 1; 249 250 return 0; 251 } 252 253 static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr, 254 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 255 { 256 uint16_t acp_table_offset = 0; 257 258 if (le16_to_cpu(powerplay_table->usTableSize) >= 259 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 260 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 261 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 262 if (powerplay_table3->usExtendendedHeaderOffset > 0) { 263 const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = 264 (const ATOM_PPLIB_EXTENDEDHEADER *) 265 (((unsigned long)powerplay_table3) + 266 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 267 if (le16_to_cpu(pExtendedHeader->usSize) >= 268 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) 269 acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset); 270 } 271 } 272 273 return acp_table_offset; 274 } 275 276 static uint16_t get_acp_clock_voltage_limit_table_offset( 277 struct pp_hwmgr *hwmgr, 278 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 279 { 280 uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table); 281 282 if (tableOffset > 0) 283 return tableOffset + 1; 284 285 return 0; 286 } 287 288 static uint16_t get_cacp_tdp_table_offset( 289 struct pp_hwmgr *hwmgr, 290 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 291 { 292 uint16_t cacTdpTableOffset = 0; 293 294 if (le16_to_cpu(powerplay_table->usTableSize) >= 295 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 296 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 297 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 298 if (powerplay_table3->usExtendendedHeaderOffset > 0) { 299 const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = 300 (const ATOM_PPLIB_EXTENDEDHEADER *) 301 (((unsigned long)powerplay_table3) + 302 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 303 if (le16_to_cpu(pExtendedHeader->usSize) >= 304 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) 305 cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset); 306 } 307 } 308 309 return cacTdpTableOffset; 310 } 311 312 static int get_cac_tdp_table(struct pp_hwmgr *hwmgr, 313 struct phm_cac_tdp_table **ptable, 314 const ATOM_PowerTune_Table *table, 315 uint16_t us_maximum_power_delivery_limit) 316 { 317 unsigned long table_size; 318 struct phm_cac_tdp_table *tdp_table; 319 320 table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table); 321 322 tdp_table = kzalloc(table_size, GFP_KERNEL); 323 if (NULL == tdp_table) 324 return -ENOMEM; 325 326 tdp_table->usTDP = le16_to_cpu(table->usTDP); 327 tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP); 328 tdp_table->usTDC = le16_to_cpu(table->usTDC); 329 tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit); 330 tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit); 331 tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage); 332 tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage); 333 tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit; 334 335 *ptable = tdp_table; 336 337 return 0; 338 } 339 340 static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr, 341 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 342 { 343 uint16_t sclk_vdd_gfx_table_offset = 0; 344 345 if (le16_to_cpu(powerplay_table->usTableSize) >= 346 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 347 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 348 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 349 if (powerplay_table3->usExtendendedHeaderOffset > 0) { 350 const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = 351 (const ATOM_PPLIB_EXTENDEDHEADER *) 352 (((unsigned long)powerplay_table3) + 353 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 354 if (le16_to_cpu(pExtendedHeader->usSize) >= 355 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) 356 sclk_vdd_gfx_table_offset = 357 le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset); 358 } 359 } 360 361 return sclk_vdd_gfx_table_offset; 362 } 363 364 static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset( 365 struct pp_hwmgr *hwmgr, 366 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 367 { 368 uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table); 369 370 if (tableOffset > 0) 371 return tableOffset; 372 373 return 0; 374 } 375 376 377 static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, 378 struct phm_clock_voltage_dependency_table **ptable, 379 const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table) 380 { 381 382 unsigned long i; 383 struct phm_clock_voltage_dependency_table *dep_table; 384 385 dep_table = kzalloc_flex(*dep_table, entries, table->ucNumEntries); 386 if (NULL == dep_table) 387 return -ENOMEM; 388 389 dep_table->count = (unsigned long)table->ucNumEntries; 390 391 for (i = 0; i < dep_table->count; i++) { 392 dep_table->entries[i].clk = 393 ((unsigned long)table->entries[i].ucClockHigh << 16) | 394 le16_to_cpu(table->entries[i].usClockLow); 395 dep_table->entries[i].v = 396 (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 397 } 398 399 *ptable = dep_table; 400 401 return 0; 402 } 403 404 static int get_valid_clk(struct pp_hwmgr *hwmgr, 405 struct phm_clock_array **ptable, 406 const struct phm_clock_voltage_dependency_table *table) 407 { 408 unsigned long i; 409 struct phm_clock_array *clock_table; 410 411 clock_table = kzalloc_flex(*clock_table, values, table->count); 412 if (!clock_table) 413 return -ENOMEM; 414 415 clock_table->count = (unsigned long)table->count; 416 417 for (i = 0; i < clock_table->count; i++) 418 clock_table->values[i] = (unsigned long)table->entries[i].clk; 419 420 *ptable = clock_table; 421 422 return 0; 423 } 424 425 static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr, 426 struct phm_clock_and_voltage_limits *limits, 427 const ATOM_PPLIB_Clock_Voltage_Limit_Table *table) 428 { 429 limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) | 430 le16_to_cpu(table->entries[0].usSclkLow); 431 limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) | 432 le16_to_cpu(table->entries[0].usMclkLow); 433 limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc); 434 limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci); 435 436 return 0; 437 } 438 439 440 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, 441 enum phm_platform_caps cap) 442 { 443 if (enable) 444 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); 445 else 446 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); 447 } 448 449 static int set_platform_caps(struct pp_hwmgr *hwmgr, 450 unsigned long powerplay_caps) 451 { 452 set_hw_cap( 453 hwmgr, 454 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY), 455 PHM_PlatformCaps_PowerPlaySupport 456 ); 457 458 set_hw_cap( 459 hwmgr, 460 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), 461 PHM_PlatformCaps_BiosPowerSourceControl 462 ); 463 464 set_hw_cap( 465 hwmgr, 466 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s), 467 PHM_PlatformCaps_EnableASPML0s 468 ); 469 470 set_hw_cap( 471 hwmgr, 472 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1), 473 PHM_PlatformCaps_EnableASPML1 474 ); 475 476 set_hw_cap( 477 hwmgr, 478 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS), 479 PHM_PlatformCaps_EnableBackbias 480 ); 481 482 set_hw_cap( 483 hwmgr, 484 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC), 485 PHM_PlatformCaps_AutomaticDCTransition 486 ); 487 488 set_hw_cap( 489 hwmgr, 490 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY), 491 PHM_PlatformCaps_GeminiPrimary 492 ); 493 494 set_hw_cap( 495 hwmgr, 496 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC), 497 PHM_PlatformCaps_StepVddc 498 ); 499 500 set_hw_cap( 501 hwmgr, 502 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL), 503 PHM_PlatformCaps_EnableVoltageControl 504 ); 505 506 set_hw_cap( 507 hwmgr, 508 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL), 509 PHM_PlatformCaps_EnableSideportControl 510 ); 511 512 set_hw_cap( 513 hwmgr, 514 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1), 515 PHM_PlatformCaps_TurnOffPll_ASPML1 516 ); 517 518 set_hw_cap( 519 hwmgr, 520 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL), 521 PHM_PlatformCaps_EnableHTLinkControl 522 ); 523 524 set_hw_cap( 525 hwmgr, 526 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL), 527 PHM_PlatformCaps_EnableMVDDControl 528 ); 529 530 set_hw_cap( 531 hwmgr, 532 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL), 533 PHM_PlatformCaps_ControlVDDCI 534 ); 535 536 set_hw_cap( 537 hwmgr, 538 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT), 539 PHM_PlatformCaps_RegulatorHot 540 ); 541 542 set_hw_cap( 543 hwmgr, 544 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT), 545 PHM_PlatformCaps_BootStateOnAlert 546 ); 547 548 set_hw_cap( 549 hwmgr, 550 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT), 551 PHM_PlatformCaps_DontWaitForVBlankOnAlert 552 ); 553 554 set_hw_cap( 555 hwmgr, 556 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO), 557 PHM_PlatformCaps_BACO 558 ); 559 560 set_hw_cap( 561 hwmgr, 562 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE), 563 PHM_PlatformCaps_NewCACVoltage 564 ); 565 566 set_hw_cap( 567 hwmgr, 568 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY), 569 PHM_PlatformCaps_RevertGPIO5Polarity 570 ); 571 572 set_hw_cap( 573 hwmgr, 574 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17), 575 PHM_PlatformCaps_Thermal2GPIO17 576 ); 577 578 set_hw_cap( 579 hwmgr, 580 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE), 581 PHM_PlatformCaps_VRHotGPIOConfigurable 582 ); 583 584 set_hw_cap( 585 hwmgr, 586 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION), 587 PHM_PlatformCaps_TempInversion 588 ); 589 590 set_hw_cap( 591 hwmgr, 592 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV), 593 PHM_PlatformCaps_EVV 594 ); 595 596 set_hw_cap( 597 hwmgr, 598 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), 599 PHM_PlatformCaps_CombinePCCWithThermalSignal 600 ); 601 602 set_hw_cap( 603 hwmgr, 604 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), 605 PHM_PlatformCaps_LoadPostProductionFirmware 606 ); 607 608 set_hw_cap( 609 hwmgr, 610 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC), 611 PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc 612 ); 613 614 return 0; 615 } 616 617 static PP_StateClassificationFlags make_classification_flags( 618 struct pp_hwmgr *hwmgr, 619 USHORT classification, 620 USHORT classification2) 621 { 622 PP_StateClassificationFlags result = 0; 623 624 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) 625 result |= PP_StateClassificationFlag_Boot; 626 627 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) 628 result |= PP_StateClassificationFlag_Thermal; 629 630 if (classification & 631 ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 632 result |= PP_StateClassificationFlag_LimitedPowerSource; 633 634 if (classification & ATOM_PPLIB_CLASSIFICATION_REST) 635 result |= PP_StateClassificationFlag_Rest; 636 637 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) 638 result |= PP_StateClassificationFlag_Forced; 639 640 if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) 641 result |= PP_StateClassificationFlag_3DPerformance; 642 643 644 if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) 645 result |= PP_StateClassificationFlag_ACOverdriveTemplate; 646 647 if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 648 result |= PP_StateClassificationFlag_Uvd; 649 650 if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE) 651 result |= PP_StateClassificationFlag_UvdHD; 652 653 if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE) 654 result |= PP_StateClassificationFlag_UvdSD; 655 656 if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE) 657 result |= PP_StateClassificationFlag_HD2; 658 659 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) 660 result |= PP_StateClassificationFlag_ACPI; 661 662 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 663 result |= PP_StateClassificationFlag_LimitedPowerSource_2; 664 665 666 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV) 667 result |= PP_StateClassificationFlag_ULV; 668 669 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) 670 result |= PP_StateClassificationFlag_UvdMVC; 671 672 return result; 673 } 674 675 static int init_non_clock_fields(struct pp_hwmgr *hwmgr, 676 struct pp_power_state *ps, 677 uint8_t version, 678 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) { 679 unsigned long rrr_index; 680 unsigned long tmp; 681 682 ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) & 683 ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; 684 ps->classification.flags = make_classification_flags(hwmgr, 685 le16_to_cpu(pnon_clock_info->usClassification), 686 le16_to_cpu(pnon_clock_info->usClassification2)); 687 688 ps->classification.temporary_state = false; 689 ps->classification.to_be_deleted = false; 690 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 691 ATOM_PPLIB_SINGLE_DISPLAY_ONLY; 692 693 ps->validation.singleDisplayOnly = (0 != tmp); 694 695 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 696 ATOM_PPLIB_DISALLOW_ON_DC; 697 698 ps->validation.disallowOnDC = (0 != tmp); 699 700 ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 701 ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> 702 ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; 703 704 ps->display.disableFrameModulation = false; 705 706 rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 707 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >> 708 ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT; 709 710 if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) { 711 static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \ 712 { 0, 50, 0 }; 713 714 ps->display.refreshrateSource = PP_RefreshrateSource_Explicit; 715 ps->display.explicitRefreshrate = look_up[rrr_index]; 716 ps->display.limitRefreshrate = true; 717 718 if (ps->display.explicitRefreshrate == 0) 719 ps->display.limitRefreshrate = false; 720 } else 721 ps->display.limitRefreshrate = false; 722 723 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 724 ATOM_PPLIB_ENABLE_VARIBRIGHT; 725 726 ps->display.enableVariBright = (0 != tmp); 727 728 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 729 ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF; 730 731 ps->memory.dllOff = (0 != tmp); 732 733 ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 734 ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT; 735 736 ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * 737 pnon_clock_info->ucMinTemperature; 738 739 ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * 740 pnon_clock_info->ucMaxTemperature; 741 742 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 743 ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING; 744 745 ps->software.disableLoadBalancing = tmp; 746 747 tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & 748 ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS; 749 750 ps->software.enableSleepForTimestamps = (0 != tmp); 751 752 ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower; 753 754 if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) { 755 ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK); 756 ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK); 757 } else { 758 ps->uvd_clocks.VCLK = 0; 759 ps->uvd_clocks.DCLK = 0; 760 } 761 762 return 0; 763 } 764 765 static ULONG size_of_entry_v2(ULONG num_dpm_levels) 766 { 767 return (sizeof(UCHAR) + sizeof(UCHAR) + 768 (num_dpm_levels * sizeof(UCHAR))); 769 } 770 771 static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( 772 const StateArray * pstate_arrays, 773 ULONG entry_index) 774 { 775 ULONG i; 776 const ATOM_PPLIB_STATE_V2 *pstate; 777 778 pstate = pstate_arrays->states; 779 if (entry_index <= pstate_arrays->ucNumEntries) { 780 for (i = 0; i < entry_index; i++) 781 pstate = (ATOM_PPLIB_STATE_V2 *)( 782 (unsigned long)pstate + 783 size_of_entry_v2(pstate->ucNumDPMLevels)); 784 } 785 return pstate; 786 } 787 788 static const unsigned char soft_dummy_pp_table[] = { 789 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00, 790 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 791 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, 792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 793 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 794 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 795 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00, 796 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 797 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 798 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 799 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 800 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, 801 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00, 802 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, 803 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59, 804 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28, 805 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01, 806 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 807 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 808 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, 809 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c, 810 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01, 811 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e, 812 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70, 813 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08, 814 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70, 815 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00, 816 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, 817 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00, 818 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, 819 0x00 820 }; 821 822 static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( 823 struct pp_hwmgr *hwmgr) 824 { 825 const void *table_addr = hwmgr->soft_pp_table; 826 uint8_t frev, crev; 827 uint16_t size; 828 829 if (!table_addr) { 830 if (hwmgr->chip_id == CHIP_RAVEN) { 831 table_addr = &soft_dummy_pp_table[0]; 832 hwmgr->soft_pp_table = &soft_dummy_pp_table[0]; 833 hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table); 834 } else { 835 table_addr = smu_atom_get_data_table(hwmgr->adev, 836 GetIndexIntoMasterTable(DATA, PowerPlayInfo), 837 &size, &frev, &crev); 838 hwmgr->soft_pp_table = table_addr; 839 hwmgr->soft_pp_table_size = size; 840 } 841 } 842 843 return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; 844 } 845 846 int pp_tables_get_response_times(struct pp_hwmgr *hwmgr, 847 uint32_t *vol_rep_time, uint32_t *bb_rep_time) 848 { 849 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr); 850 851 PP_ASSERT_WITH_CODE(NULL != powerplay_tab, 852 "Missing PowerPlay Table!", return -EINVAL); 853 854 *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime); 855 *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime); 856 857 return 0; 858 } 859 860 int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, 861 unsigned long *num_of_entries) 862 { 863 const StateArray *pstate_arrays; 864 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 865 866 if (powerplay_table == NULL) 867 return -1; 868 869 if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { 870 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + 871 le16_to_cpu(powerplay_table->usStateArrayOffset)); 872 873 *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries); 874 } else 875 *num_of_entries = (unsigned long)(powerplay_table->ucNumStates); 876 877 return 0; 878 } 879 880 int pp_tables_get_entry(struct pp_hwmgr *hwmgr, 881 unsigned long entry_index, 882 struct pp_power_state *ps, 883 pp_tables_hw_clock_info_callback func) 884 { 885 int i; 886 const StateArray *pstate_arrays; 887 const ATOM_PPLIB_STATE_V2 *pstate_entry_v2; 888 const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info; 889 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 890 int result = 0; 891 int res = 0; 892 893 const ClockInfoArray *pclock_arrays; 894 895 const NonClockInfoArray *pnon_clock_arrays; 896 897 const ATOM_PPLIB_STATE *pstate_entry; 898 899 if (powerplay_table == NULL) 900 return -1; 901 902 ps->classification.bios_index = entry_index; 903 904 if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { 905 pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + 906 le16_to_cpu(powerplay_table->usStateArrayOffset)); 907 908 if (entry_index > pstate_arrays->ucNumEntries) 909 return -1; 910 911 pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index); 912 pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + 913 le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); 914 915 pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) + 916 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset)); 917 918 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) + 919 (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize)); 920 921 result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info); 922 923 for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) { 924 const void *pclock_info = (const void *)( 925 (unsigned long)(pclock_arrays->clockInfo) + 926 (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize)); 927 res = func(hwmgr, &ps->hardware, i, pclock_info); 928 if ((0 == result) && (0 != res)) 929 result = res; 930 } 931 } else { 932 if (entry_index > powerplay_table->ucNumStates) 933 return -1; 934 935 pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + 936 le16_to_cpu(powerplay_table->usStateArrayOffset) + 937 entry_index * powerplay_table->ucStateEntrySize); 938 939 pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table + 940 le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) + 941 pstate_entry->ucNonClockStateIndex * 942 powerplay_table->ucNonClockSize); 943 944 result = init_non_clock_fields(hwmgr, ps, 945 powerplay_table->ucNonClockSize, 946 pnon_clock_info); 947 948 for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) { 949 const void *pclock_info = (const void *)((unsigned long)powerplay_table + 950 le16_to_cpu(powerplay_table->usClockInfoArrayOffset) + 951 pstate_entry->ucClockStateIndices[i] * 952 powerplay_table->ucClockInfoSize); 953 954 int res = func(hwmgr, &ps->hardware, i, pclock_info); 955 956 if ((0 == result) && (0 != res)) 957 result = res; 958 } 959 } 960 961 if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) { 962 if (hwmgr->chip_family < AMDGPU_FAMILY_RV) 963 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); 964 } 965 966 return result; 967 } 968 969 static int init_powerplay_tables( 970 struct pp_hwmgr *hwmgr, 971 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table 972 ) 973 { 974 return 0; 975 } 976 977 978 static int init_thermal_controller( 979 struct pp_hwmgr *hwmgr, 980 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 981 { 982 struct amdgpu_device *adev = hwmgr->adev; 983 984 hwmgr->thermal_controller.ucType = 985 powerplay_table->sThermalController.ucType; 986 hwmgr->thermal_controller.ucI2cLine = 987 powerplay_table->sThermalController.ucI2cLine; 988 hwmgr->thermal_controller.ucI2cAddress = 989 powerplay_table->sThermalController.ucI2cAddress; 990 991 hwmgr->thermal_controller.fanInfo.bNoFan = 992 (0 != (powerplay_table->sThermalController.ucFanParameters & 993 ATOM_PP_FANPARAMETERS_NOFAN)); 994 995 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = 996 powerplay_table->sThermalController.ucFanParameters & 997 ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 998 999 hwmgr->thermal_controller.fanInfo.ulMinRPM 1000 = powerplay_table->sThermalController.ucFanMinRPM * 100UL; 1001 hwmgr->thermal_controller.fanInfo.ulMaxRPM 1002 = powerplay_table->sThermalController.ucFanMaxRPM * 100UL; 1003 1004 set_hw_cap(hwmgr, 1005 ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, 1006 PHM_PlatformCaps_ThermalController); 1007 1008 if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { 1009 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = 1010 (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 1011 1012 if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) { 1013 hwmgr->thermal_controller.use_hw_fan_control = 1; 1014 return 0; 1015 } else { 1016 const ATOM_PPLIB_FANTABLE *fan_table = 1017 (const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) + 1018 le16_to_cpu(powerplay_table3->usFanTableOffset)); 1019 1020 if (1 <= fan_table->ucFanTableFormat) { 1021 hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst = 1022 fan_table->ucTHyst; 1023 hwmgr->thermal_controller.advanceFanControlParameters.usTMin = 1024 le16_to_cpu(fan_table->usTMin); 1025 hwmgr->thermal_controller.advanceFanControlParameters.usTMed = 1026 le16_to_cpu(fan_table->usTMed); 1027 hwmgr->thermal_controller.advanceFanControlParameters.usTHigh = 1028 le16_to_cpu(fan_table->usTHigh); 1029 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = 1030 le16_to_cpu(fan_table->usPWMMin); 1031 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed = 1032 le16_to_cpu(fan_table->usPWMMed); 1033 hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh = 1034 le16_to_cpu(fan_table->usPWMHigh); 1035 hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900; 1036 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000; 1037 1038 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1039 PHM_PlatformCaps_MicrocodeFanControl); 1040 } 1041 1042 if (2 <= fan_table->ucFanTableFormat) { 1043 const ATOM_PPLIB_FANTABLE2 *fan_table2 = 1044 (const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) + 1045 le16_to_cpu(powerplay_table3->usFanTableOffset)); 1046 hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 1047 le16_to_cpu(fan_table2->usTMax); 1048 } 1049 1050 if (3 <= fan_table->ucFanTableFormat) { 1051 const ATOM_PPLIB_FANTABLE3 *fan_table3 = 1052 (const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) + 1053 le16_to_cpu(powerplay_table3->usFanTableOffset)); 1054 1055 hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode = 1056 fan_table3->ucFanControlMode; 1057 1058 if ((3 == fan_table->ucFanTableFormat) && 1059 (0x67B1 == adev->pdev->device)) 1060 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM = 1061 47; 1062 else 1063 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM = 1064 le16_to_cpu(fan_table3->usFanPWMMax); 1065 1066 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity = 1067 4836; 1068 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = 1069 le16_to_cpu(fan_table3->usFanOutputSensitivity); 1070 } 1071 1072 if (6 <= fan_table->ucFanTableFormat) { 1073 const ATOM_PPLIB_FANTABLE4 *fan_table4 = 1074 (const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) + 1075 le16_to_cpu(powerplay_table3->usFanTableOffset)); 1076 1077 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1078 PHM_PlatformCaps_FanSpeedInTableIsRPM); 1079 1080 hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM = 1081 le16_to_cpu(fan_table4->usFanRPMMax); 1082 } 1083 1084 if (7 <= fan_table->ucFanTableFormat) { 1085 const ATOM_PPLIB_FANTABLE5 *fan_table5 = 1086 (const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) + 1087 le16_to_cpu(powerplay_table3->usFanTableOffset)); 1088 1089 if (0x67A2 == adev->pdev->device || 1090 0x67A9 == adev->pdev->device || 1091 0x67B9 == adev->pdev->device) { 1092 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1093 PHM_PlatformCaps_GeminiRegulatorFanControlSupport); 1094 hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow = 1095 le16_to_cpu(fan_table5->usFanCurrentLow); 1096 hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh = 1097 le16_to_cpu(fan_table5->usFanCurrentHigh); 1098 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow = 1099 le16_to_cpu(fan_table5->usFanRPMLow); 1100 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh = 1101 le16_to_cpu(fan_table5->usFanRPMHigh); 1102 } 1103 } 1104 } 1105 } 1106 1107 return 0; 1108 } 1109 1110 static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr, 1111 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, 1112 const ATOM_FIRMWARE_INFO_V1_4 *fw_info) 1113 { 1114 hwmgr->platform_descriptor.overdriveLimit.engineClock = 1115 le32_to_cpu(fw_info->ulASICMaxEngineClock); 1116 1117 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 1118 le32_to_cpu(fw_info->ulASICMaxMemoryClock); 1119 1120 hwmgr->platform_descriptor.maxOverdriveVDDC = 1121 le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF; 1122 1123 hwmgr->platform_descriptor.minOverdriveVDDC = 1124 le16_to_cpu(fw_info->usBootUpVDDCVoltage); 1125 1126 hwmgr->platform_descriptor.maxOverdriveVDDC = 1127 le16_to_cpu(fw_info->usBootUpVDDCVoltage); 1128 1129 hwmgr->platform_descriptor.overdriveVDDCStep = 0; 1130 return 0; 1131 } 1132 1133 static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr, 1134 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, 1135 const ATOM_FIRMWARE_INFO_V2_1 *fw_info) 1136 { 1137 const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3; 1138 const ATOM_PPLIB_EXTENDEDHEADER *header; 1139 1140 if (le16_to_cpu(powerplay_table->usTableSize) < 1141 sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) 1142 return 0; 1143 1144 powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; 1145 1146 if (0 == powerplay_table3->usExtendendedHeaderOffset) 1147 return 0; 1148 1149 header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) + 1150 le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); 1151 1152 hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock); 1153 hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock); 1154 1155 1156 hwmgr->platform_descriptor.minOverdriveVDDC = 0; 1157 hwmgr->platform_descriptor.maxOverdriveVDDC = 0; 1158 hwmgr->platform_descriptor.overdriveVDDCStep = 0; 1159 1160 return 0; 1161 } 1162 1163 static int init_overdrive_limits(struct pp_hwmgr *hwmgr, 1164 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1165 { 1166 int result = 0; 1167 uint8_t frev, crev; 1168 uint16_t size; 1169 1170 const ATOM_COMMON_TABLE_HEADER *fw_info = NULL; 1171 1172 hwmgr->platform_descriptor.overdriveLimit.engineClock = 0; 1173 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0; 1174 hwmgr->platform_descriptor.minOverdriveVDDC = 0; 1175 hwmgr->platform_descriptor.maxOverdriveVDDC = 0; 1176 hwmgr->platform_descriptor.overdriveVDDCStep = 0; 1177 1178 if (hwmgr->chip_id == CHIP_RAVEN) 1179 return 0; 1180 1181 /* We assume here that fw_info is unchanged if this call fails.*/ 1182 fw_info = smu_atom_get_data_table(hwmgr->adev, 1183 GetIndexIntoMasterTable(DATA, FirmwareInfo), 1184 &size, &frev, &crev); 1185 PP_ASSERT_WITH_CODE(fw_info != NULL, 1186 "Missing firmware info!", return -EINVAL); 1187 1188 if ((fw_info->ucTableFormatRevision == 1) 1189 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4))) 1190 result = init_overdrive_limits_V1_4(hwmgr, 1191 powerplay_table, 1192 (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info); 1193 1194 else if ((fw_info->ucTableFormatRevision == 2) 1195 && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) 1196 result = init_overdrive_limits_V2_1(hwmgr, 1197 powerplay_table, 1198 (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info); 1199 1200 return result; 1201 } 1202 1203 static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1204 struct phm_uvd_clock_voltage_dependency_table **ptable, 1205 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table, 1206 const UVDClockInfoArray *array) 1207 { 1208 unsigned long i; 1209 struct phm_uvd_clock_voltage_dependency_table *uvd_table; 1210 1211 uvd_table = kzalloc_flex(*uvd_table, entries, table->numEntries); 1212 if (!uvd_table) 1213 return -ENOMEM; 1214 1215 uvd_table->count = table->numEntries; 1216 1217 for (i = 0; i < table->numEntries; i++) { 1218 const UVDClockInfo *entry = 1219 &array->entries[table->entries[i].ucUVDClockInfoIndex]; 1220 uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1221 uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16) 1222 | le16_to_cpu(entry->usVClkLow); 1223 uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16) 1224 | le16_to_cpu(entry->usDClkLow); 1225 } 1226 1227 *ptable = uvd_table; 1228 1229 return 0; 1230 } 1231 1232 static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1233 struct phm_vce_clock_voltage_dependency_table **ptable, 1234 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table, 1235 const VCEClockInfoArray *array) 1236 { 1237 unsigned long i; 1238 struct phm_vce_clock_voltage_dependency_table *vce_table; 1239 1240 vce_table = kzalloc_flex(*vce_table, entries, table->numEntries); 1241 if (!vce_table) 1242 return -ENOMEM; 1243 1244 vce_table->count = table->numEntries; 1245 for (i = 0; i < table->numEntries; i++) { 1246 const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex]; 1247 1248 vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1249 vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16) 1250 | le16_to_cpu(entry->usEVClkLow); 1251 vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16) 1252 | le16_to_cpu(entry->usECClkLow); 1253 } 1254 1255 *ptable = vce_table; 1256 1257 return 0; 1258 } 1259 1260 static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1261 struct phm_samu_clock_voltage_dependency_table **ptable, 1262 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table) 1263 { 1264 unsigned long i; 1265 struct phm_samu_clock_voltage_dependency_table *samu_table; 1266 1267 samu_table = kzalloc_flex(*samu_table, entries, table->numEntries); 1268 if (!samu_table) 1269 return -ENOMEM; 1270 1271 samu_table->count = table->numEntries; 1272 1273 for (i = 0; i < table->numEntries; i++) { 1274 samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1275 samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16) 1276 | le16_to_cpu(table->entries[i].usSAMClockLow); 1277 } 1278 1279 *ptable = samu_table; 1280 1281 return 0; 1282 } 1283 1284 static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, 1285 struct phm_acp_clock_voltage_dependency_table **ptable, 1286 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table) 1287 { 1288 unsigned long i; 1289 struct phm_acp_clock_voltage_dependency_table *acp_table; 1290 1291 acp_table = kzalloc_flex(*acp_table, entries, table->numEntries); 1292 if (!acp_table) 1293 return -ENOMEM; 1294 1295 acp_table->count = (unsigned long)table->numEntries; 1296 1297 for (i = 0; i < table->numEntries; i++) { 1298 acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); 1299 acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16) 1300 | le16_to_cpu(table->entries[i].usACPClockLow); 1301 } 1302 1303 *ptable = acp_table; 1304 1305 return 0; 1306 } 1307 1308 static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr, 1309 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1310 { 1311 ATOM_PPLIB_Clock_Voltage_Dependency_Table *table; 1312 ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table; 1313 int result = 0; 1314 1315 uint16_t vce_clock_info_array_offset; 1316 uint16_t uvd_clock_info_array_offset; 1317 uint16_t table_offset; 1318 1319 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; 1320 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; 1321 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; 1322 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; 1323 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; 1324 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; 1325 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; 1326 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; 1327 hwmgr->dyn_state.ppm_parameter_table = NULL; 1328 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; 1329 1330 vce_clock_info_array_offset = get_vce_clock_info_array_offset( 1331 hwmgr, powerplay_table); 1332 table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, 1333 powerplay_table); 1334 if (vce_clock_info_array_offset > 0 && table_offset > 0) { 1335 const VCEClockInfoArray *array = (const VCEClockInfoArray *) 1336 (((unsigned long) powerplay_table) + 1337 vce_clock_info_array_offset); 1338 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table = 1339 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 1340 (((unsigned long) powerplay_table) + table_offset); 1341 result = get_vce_clock_voltage_limit_table(hwmgr, 1342 &hwmgr->dyn_state.vce_clock_voltage_dependency_table, 1343 table, array); 1344 } 1345 1346 uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table); 1347 table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 1348 1349 if (uvd_clock_info_array_offset > 0 && table_offset > 0) { 1350 const UVDClockInfoArray *array = (const UVDClockInfoArray *) 1351 (((unsigned long) powerplay_table) + 1352 uvd_clock_info_array_offset); 1353 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable = 1354 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 1355 (((unsigned long) powerplay_table) + table_offset); 1356 result = get_uvd_clock_voltage_limit_table(hwmgr, 1357 &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array); 1358 } 1359 1360 table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr, 1361 powerplay_table); 1362 1363 if (table_offset > 0) { 1364 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable = 1365 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 1366 (((unsigned long) powerplay_table) + table_offset); 1367 result = get_samu_clock_voltage_limit_table(hwmgr, 1368 &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable); 1369 } 1370 1371 table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr, 1372 powerplay_table); 1373 1374 if (table_offset > 0) { 1375 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable = 1376 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 1377 (((unsigned long) powerplay_table) + table_offset); 1378 result = get_acp_clock_voltage_limit_table(hwmgr, 1379 &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable); 1380 } 1381 1382 table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table); 1383 if (table_offset > 0) { 1384 UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset); 1385 1386 if (rev_id > 0) { 1387 const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table = 1388 (const ATOM_PPLIB_POWERTUNE_Table_V1 *) 1389 (((unsigned long) powerplay_table) + table_offset); 1390 result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table, 1391 &tune_table->power_tune_table, 1392 le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit)); 1393 hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = 1394 le16_to_cpu(tune_table->usTjMax); 1395 } else { 1396 const ATOM_PPLIB_POWERTUNE_Table *tune_table = 1397 (const ATOM_PPLIB_POWERTUNE_Table *) 1398 (((unsigned long) powerplay_table) + table_offset); 1399 result = get_cac_tdp_table(hwmgr, 1400 &hwmgr->dyn_state.cac_dtp_table, 1401 &tune_table->power_tune_table, 255); 1402 } 1403 } 1404 1405 if (le16_to_cpu(powerplay_table->usTableSize) >= 1406 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { 1407 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = 1408 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; 1409 if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) { 1410 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1411 (((unsigned long) powerplay_table4) + 1412 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset)); 1413 result = get_clock_voltage_dependency_table(hwmgr, 1414 &hwmgr->dyn_state.vddc_dependency_on_sclk, table); 1415 } 1416 1417 if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) { 1418 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1419 (((unsigned long) powerplay_table4) + 1420 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset)); 1421 result = get_clock_voltage_dependency_table(hwmgr, 1422 &hwmgr->dyn_state.vddci_dependency_on_mclk, table); 1423 } 1424 1425 if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) { 1426 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1427 (((unsigned long) powerplay_table4) + 1428 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset)); 1429 result = get_clock_voltage_dependency_table(hwmgr, 1430 &hwmgr->dyn_state.vddc_dependency_on_mclk, table); 1431 } 1432 1433 if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) { 1434 limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 1435 (((unsigned long) powerplay_table4) + 1436 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset)); 1437 result = get_clock_voltage_limit(hwmgr, 1438 &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table); 1439 } 1440 1441 if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) && 1442 (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count)) 1443 result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values, 1444 hwmgr->dyn_state.vddc_dependency_on_mclk); 1445 1446 if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) && 1447 (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count)) 1448 result = get_valid_clk(hwmgr, 1449 &hwmgr->dyn_state.valid_sclk_values, 1450 hwmgr->dyn_state.vddc_dependency_on_sclk); 1451 1452 if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) { 1453 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1454 (((unsigned long) powerplay_table4) + 1455 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset)); 1456 result = get_clock_voltage_dependency_table(hwmgr, 1457 &hwmgr->dyn_state.mvdd_dependency_on_mclk, table); 1458 } 1459 } 1460 1461 table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr, 1462 powerplay_table); 1463 1464 if (table_offset > 0) { 1465 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1466 (((unsigned long) powerplay_table) + table_offset); 1467 result = get_clock_voltage_dependency_table(hwmgr, 1468 &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table); 1469 } 1470 1471 return result; 1472 } 1473 1474 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, 1475 struct phm_cac_leakage_table **ptable, 1476 const ATOM_PPLIB_CAC_Leakage_Table *table) 1477 { 1478 struct phm_cac_leakage_table *cac_leakage_table; 1479 unsigned long i; 1480 1481 if (!hwmgr || !table || !ptable) 1482 return -EINVAL; 1483 1484 cac_leakage_table = kzalloc_flex(*cac_leakage_table, entries, 1485 table->ucNumEntries); 1486 if (!cac_leakage_table) 1487 return -ENOMEM; 1488 1489 cac_leakage_table->count = (ULONG)table->ucNumEntries; 1490 1491 for (i = 0; i < cac_leakage_table->count; i++) { 1492 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1493 PHM_PlatformCaps_EVV)) { 1494 cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1); 1495 cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2); 1496 cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3); 1497 } else { 1498 cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc); 1499 cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue); 1500 } 1501 } 1502 1503 *ptable = cac_leakage_table; 1504 1505 return 0; 1506 } 1507 1508 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, 1509 ATOM_PPLIB_PPM_Table *atom_ppm_table) 1510 { 1511 struct phm_ppm_table *ptr = kzalloc_obj(struct phm_ppm_table); 1512 1513 if (NULL == ptr) 1514 return -ENOMEM; 1515 1516 ptr->ppm_design = atom_ppm_table->ucPpmDesign; 1517 ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); 1518 ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP); 1519 ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); 1520 ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC); 1521 ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); 1522 ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP); 1523 ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP); 1524 ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); 1525 ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax); 1526 hwmgr->dyn_state.ppm_parameter_table = ptr; 1527 1528 return 0; 1529 } 1530 1531 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr, 1532 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1533 { 1534 int result = 0; 1535 1536 if (le16_to_cpu(powerplay_table->usTableSize) >= 1537 sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) { 1538 const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 = 1539 (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table; 1540 const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 = 1541 (const ATOM_PPLIB_POWERPLAYTABLE4 *) 1542 (&ptable5->basicTable4); 1543 const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 = 1544 (const ATOM_PPLIB_POWERPLAYTABLE3 *) 1545 (&ptable4->basicTable3); 1546 const ATOM_PPLIB_EXTENDEDHEADER *extended_header; 1547 uint16_t table_offset; 1548 ATOM_PPLIB_PPM_Table *atom_ppm_table; 1549 1550 hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit); 1551 hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit); 1552 1553 hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit); 1554 hwmgr->platform_descriptor.TDPAdjustment = 0; 1555 1556 hwmgr->platform_descriptor.VidAdjustment = 0; 1557 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 1558 hwmgr->platform_descriptor.VidMinLimit = 0; 1559 hwmgr->platform_descriptor.VidMaxLimit = 1500000; 1560 hwmgr->platform_descriptor.VidStep = 6250; 1561 1562 hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit); 1563 1564 if (hwmgr->platform_descriptor.TDPODLimit != 0) 1565 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1566 PHM_PlatformCaps_PowerControl); 1567 1568 hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold); 1569 1570 hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage); 1571 1572 hwmgr->dyn_state.cac_leakage_table = NULL; 1573 1574 if (0 != ptable5->usCACLeakageTableOffset) { 1575 const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table = 1576 (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) + 1577 le16_to_cpu(ptable5->usCACLeakageTableOffset)); 1578 result = get_cac_leakage_table(hwmgr, 1579 &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table); 1580 } 1581 1582 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope); 1583 1584 hwmgr->dyn_state.ppm_parameter_table = NULL; 1585 1586 if (0 != ptable3->usExtendendedHeaderOffset) { 1587 extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) 1588 (((unsigned long)powerplay_table) + 1589 le16_to_cpu(ptable3->usExtendendedHeaderOffset)); 1590 if ((extended_header->usPPMTableOffset > 0) && 1591 le16_to_cpu(extended_header->usSize) >= 1592 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) { 1593 table_offset = le16_to_cpu(extended_header->usPPMTableOffset); 1594 atom_ppm_table = (ATOM_PPLIB_PPM_Table *) 1595 (((unsigned long)powerplay_table) + table_offset); 1596 if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table)) 1597 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1598 PHM_PlatformCaps_EnablePlatformPowerManagement); 1599 } 1600 } 1601 } 1602 return result; 1603 } 1604 1605 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, 1606 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1607 { 1608 if (le16_to_cpu(powerplay_table->usTableSize) >= 1609 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { 1610 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = 1611 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; 1612 1613 if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) { 1614 const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable = 1615 (ATOM_PPLIB_PhaseSheddingLimits_Table *) 1616 (((unsigned long)powerplay_table4) + 1617 le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); 1618 struct phm_phase_shedding_limits_table *table; 1619 unsigned long i; 1620 1621 1622 table = kzalloc_flex(*table, entries, 1623 ptable->ucNumEntries); 1624 if (!table) 1625 return -ENOMEM; 1626 1627 table->count = (unsigned long)ptable->ucNumEntries; 1628 1629 for (i = 0; i < table->count; i++) { 1630 table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage); 1631 table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16) 1632 | le16_to_cpu(ptable->entries[i].usSclkLow); 1633 table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16) 1634 | le16_to_cpu(ptable->entries[i].usMclkLow); 1635 } 1636 hwmgr->dyn_state.vddc_phase_shed_limits_table = table; 1637 } 1638 } 1639 1640 return 0; 1641 } 1642 1643 static int get_number_of_vce_state_table_entries( 1644 struct pp_hwmgr *hwmgr) 1645 { 1646 const ATOM_PPLIB_POWERPLAYTABLE *table = 1647 get_powerplay_table(hwmgr); 1648 const ATOM_PPLIB_VCE_State_Table *vce_table = 1649 get_vce_state_table(hwmgr, table); 1650 1651 if (vce_table) 1652 return vce_table->numEntries; 1653 1654 return 0; 1655 } 1656 1657 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, 1658 unsigned long i, 1659 struct amd_vce_state *vce_state, 1660 void **clock_info, 1661 unsigned long *flag) 1662 { 1663 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 1664 1665 const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table); 1666 1667 unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table); 1668 1669 const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset); 1670 1671 const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + 1672 le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); 1673 1674 const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i]; 1675 1676 const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex]; 1677 1678 unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F; 1679 1680 *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX); 1681 1682 vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow); 1683 vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow); 1684 1685 *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize)); 1686 1687 return 0; 1688 } 1689 1690 1691 static int pp_tables_initialize(struct pp_hwmgr *hwmgr) 1692 { 1693 int result; 1694 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table; 1695 1696 if (hwmgr->chip_id == CHIP_RAVEN) 1697 return 0; 1698 1699 hwmgr->need_pp_table_upload = true; 1700 1701 powerplay_table = get_powerplay_table(hwmgr); 1702 1703 result = init_powerplay_tables(hwmgr, powerplay_table); 1704 1705 PP_ASSERT_WITH_CODE((result == 0), 1706 "init_powerplay_tables failed", return result); 1707 1708 result = set_platform_caps(hwmgr, 1709 le32_to_cpu(powerplay_table->ulPlatformCaps)); 1710 1711 PP_ASSERT_WITH_CODE((result == 0), 1712 "set_platform_caps failed", return result); 1713 1714 result = init_thermal_controller(hwmgr, powerplay_table); 1715 1716 PP_ASSERT_WITH_CODE((result == 0), 1717 "init_thermal_controller failed", return result); 1718 1719 result = init_overdrive_limits(hwmgr, powerplay_table); 1720 1721 PP_ASSERT_WITH_CODE((result == 0), 1722 "init_overdrive_limits failed", return result); 1723 1724 result = init_clock_voltage_dependency(hwmgr, 1725 powerplay_table); 1726 1727 PP_ASSERT_WITH_CODE((result == 0), 1728 "init_clock_voltage_dependency failed", return result); 1729 1730 result = init_dpm2_parameters(hwmgr, powerplay_table); 1731 1732 PP_ASSERT_WITH_CODE((result == 0), 1733 "init_dpm2_parameters failed", return result); 1734 1735 result = init_phase_shedding_table(hwmgr, powerplay_table); 1736 1737 PP_ASSERT_WITH_CODE((result == 0), 1738 "init_phase_shedding_table failed", return result); 1739 1740 return result; 1741 } 1742 1743 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) 1744 { 1745 if (hwmgr->chip_id == CHIP_RAVEN) 1746 return 0; 1747 1748 kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); 1749 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; 1750 1751 kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); 1752 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; 1753 1754 kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); 1755 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; 1756 1757 kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); 1758 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; 1759 1760 kfree(hwmgr->dyn_state.valid_mclk_values); 1761 hwmgr->dyn_state.valid_mclk_values = NULL; 1762 1763 kfree(hwmgr->dyn_state.valid_sclk_values); 1764 hwmgr->dyn_state.valid_sclk_values = NULL; 1765 1766 kfree(hwmgr->dyn_state.cac_leakage_table); 1767 hwmgr->dyn_state.cac_leakage_table = NULL; 1768 1769 kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); 1770 hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; 1771 1772 kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); 1773 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; 1774 1775 kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); 1776 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; 1777 1778 kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); 1779 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; 1780 1781 kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); 1782 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; 1783 1784 kfree(hwmgr->dyn_state.cac_dtp_table); 1785 hwmgr->dyn_state.cac_dtp_table = NULL; 1786 1787 kfree(hwmgr->dyn_state.ppm_parameter_table); 1788 hwmgr->dyn_state.ppm_parameter_table = NULL; 1789 1790 kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); 1791 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; 1792 1793 return 0; 1794 } 1795 1796 const struct pp_table_func pptable_funcs = { 1797 .pptable_init = pp_tables_initialize, 1798 .pptable_fini = pp_tables_uninitialize, 1799 .pptable_get_number_of_vce_state_table_entries = 1800 get_number_of_vce_state_table_entries, 1801 .pptable_get_vce_state_table_entry = 1802 get_vce_state_table_entry, 1803 }; 1804 1805