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.vddc_dep_on_dal_pwrl = NULL; 1323 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; 1324 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; 1325 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; 1326 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; 1327 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; 1328 hwmgr->dyn_state.ppm_parameter_table = NULL; 1329 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; 1330 1331 vce_clock_info_array_offset = get_vce_clock_info_array_offset( 1332 hwmgr, powerplay_table); 1333 table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, 1334 powerplay_table); 1335 if (vce_clock_info_array_offset > 0 && table_offset > 0) { 1336 const VCEClockInfoArray *array = (const VCEClockInfoArray *) 1337 (((unsigned long) powerplay_table) + 1338 vce_clock_info_array_offset); 1339 const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table = 1340 (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) 1341 (((unsigned long) powerplay_table) + table_offset); 1342 result = get_vce_clock_voltage_limit_table(hwmgr, 1343 &hwmgr->dyn_state.vce_clock_voltage_dependency_table, 1344 table, array); 1345 } 1346 1347 uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table); 1348 table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table); 1349 1350 if (uvd_clock_info_array_offset > 0 && table_offset > 0) { 1351 const UVDClockInfoArray *array = (const UVDClockInfoArray *) 1352 (((unsigned long) powerplay_table) + 1353 uvd_clock_info_array_offset); 1354 const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable = 1355 (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) 1356 (((unsigned long) powerplay_table) + table_offset); 1357 result = get_uvd_clock_voltage_limit_table(hwmgr, 1358 &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array); 1359 } 1360 1361 table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr, 1362 powerplay_table); 1363 1364 if (table_offset > 0) { 1365 const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable = 1366 (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) 1367 (((unsigned long) powerplay_table) + table_offset); 1368 result = get_samu_clock_voltage_limit_table(hwmgr, 1369 &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable); 1370 } 1371 1372 table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr, 1373 powerplay_table); 1374 1375 if (table_offset > 0) { 1376 const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable = 1377 (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) 1378 (((unsigned long) powerplay_table) + table_offset); 1379 result = get_acp_clock_voltage_limit_table(hwmgr, 1380 &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable); 1381 } 1382 1383 table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table); 1384 if (table_offset > 0) { 1385 UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset); 1386 1387 if (rev_id > 0) { 1388 const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table = 1389 (const ATOM_PPLIB_POWERTUNE_Table_V1 *) 1390 (((unsigned long) powerplay_table) + table_offset); 1391 result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table, 1392 &tune_table->power_tune_table, 1393 le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit)); 1394 hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = 1395 le16_to_cpu(tune_table->usTjMax); 1396 } else { 1397 const ATOM_PPLIB_POWERTUNE_Table *tune_table = 1398 (const ATOM_PPLIB_POWERTUNE_Table *) 1399 (((unsigned long) powerplay_table) + table_offset); 1400 result = get_cac_tdp_table(hwmgr, 1401 &hwmgr->dyn_state.cac_dtp_table, 1402 &tune_table->power_tune_table, 255); 1403 } 1404 } 1405 1406 if (le16_to_cpu(powerplay_table->usTableSize) >= 1407 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { 1408 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = 1409 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; 1410 if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) { 1411 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1412 (((unsigned long) powerplay_table4) + 1413 le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset)); 1414 result = get_clock_voltage_dependency_table(hwmgr, 1415 &hwmgr->dyn_state.vddc_dependency_on_sclk, table); 1416 } 1417 1418 if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) { 1419 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1420 (((unsigned long) powerplay_table4) + 1421 le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset)); 1422 result = get_clock_voltage_dependency_table(hwmgr, 1423 &hwmgr->dyn_state.vddci_dependency_on_mclk, table); 1424 } 1425 1426 if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) { 1427 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1428 (((unsigned long) powerplay_table4) + 1429 le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset)); 1430 result = get_clock_voltage_dependency_table(hwmgr, 1431 &hwmgr->dyn_state.vddc_dependency_on_mclk, table); 1432 } 1433 1434 if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) { 1435 limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) 1436 (((unsigned long) powerplay_table4) + 1437 le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset)); 1438 result = get_clock_voltage_limit(hwmgr, 1439 &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table); 1440 } 1441 1442 if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) && 1443 (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count)) 1444 result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values, 1445 hwmgr->dyn_state.vddc_dependency_on_mclk); 1446 1447 if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) && 1448 (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count)) 1449 result = get_valid_clk(hwmgr, 1450 &hwmgr->dyn_state.valid_sclk_values, 1451 hwmgr->dyn_state.vddc_dependency_on_sclk); 1452 1453 if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) { 1454 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1455 (((unsigned long) powerplay_table4) + 1456 le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset)); 1457 result = get_clock_voltage_dependency_table(hwmgr, 1458 &hwmgr->dyn_state.mvdd_dependency_on_mclk, table); 1459 } 1460 } 1461 1462 table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr, 1463 powerplay_table); 1464 1465 if (table_offset > 0) { 1466 table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) 1467 (((unsigned long) powerplay_table) + table_offset); 1468 result = get_clock_voltage_dependency_table(hwmgr, 1469 &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table); 1470 } 1471 1472 return result; 1473 } 1474 1475 static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, 1476 struct phm_cac_leakage_table **ptable, 1477 const ATOM_PPLIB_CAC_Leakage_Table *table) 1478 { 1479 struct phm_cac_leakage_table *cac_leakage_table; 1480 unsigned long i; 1481 1482 if (!hwmgr || !table || !ptable) 1483 return -EINVAL; 1484 1485 cac_leakage_table = kzalloc_flex(*cac_leakage_table, entries, 1486 table->ucNumEntries); 1487 if (!cac_leakage_table) 1488 return -ENOMEM; 1489 1490 cac_leakage_table->count = (ULONG)table->ucNumEntries; 1491 1492 for (i = 0; i < cac_leakage_table->count; i++) { 1493 if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, 1494 PHM_PlatformCaps_EVV)) { 1495 cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1); 1496 cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2); 1497 cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3); 1498 } else { 1499 cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc); 1500 cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue); 1501 } 1502 } 1503 1504 *ptable = cac_leakage_table; 1505 1506 return 0; 1507 } 1508 1509 static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, 1510 ATOM_PPLIB_PPM_Table *atom_ppm_table) 1511 { 1512 struct phm_ppm_table *ptr = kzalloc_obj(struct phm_ppm_table); 1513 1514 if (NULL == ptr) 1515 return -ENOMEM; 1516 1517 ptr->ppm_design = atom_ppm_table->ucPpmDesign; 1518 ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); 1519 ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP); 1520 ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); 1521 ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC); 1522 ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); 1523 ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP); 1524 ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP); 1525 ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); 1526 ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax); 1527 hwmgr->dyn_state.ppm_parameter_table = ptr; 1528 1529 return 0; 1530 } 1531 1532 static int init_dpm2_parameters(struct pp_hwmgr *hwmgr, 1533 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1534 { 1535 int result = 0; 1536 1537 if (le16_to_cpu(powerplay_table->usTableSize) >= 1538 sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) { 1539 const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 = 1540 (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table; 1541 const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 = 1542 (const ATOM_PPLIB_POWERPLAYTABLE4 *) 1543 (&ptable5->basicTable4); 1544 const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 = 1545 (const ATOM_PPLIB_POWERPLAYTABLE3 *) 1546 (&ptable4->basicTable3); 1547 const ATOM_PPLIB_EXTENDEDHEADER *extended_header; 1548 uint16_t table_offset; 1549 ATOM_PPLIB_PPM_Table *atom_ppm_table; 1550 1551 hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit); 1552 hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit); 1553 1554 hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit); 1555 hwmgr->platform_descriptor.TDPAdjustment = 0; 1556 1557 hwmgr->platform_descriptor.VidAdjustment = 0; 1558 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 1559 hwmgr->platform_descriptor.VidMinLimit = 0; 1560 hwmgr->platform_descriptor.VidMaxLimit = 1500000; 1561 hwmgr->platform_descriptor.VidStep = 6250; 1562 1563 hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit); 1564 1565 if (hwmgr->platform_descriptor.TDPODLimit != 0) 1566 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1567 PHM_PlatformCaps_PowerControl); 1568 1569 hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold); 1570 1571 hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage); 1572 1573 hwmgr->dyn_state.cac_leakage_table = NULL; 1574 1575 if (0 != ptable5->usCACLeakageTableOffset) { 1576 const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table = 1577 (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) + 1578 le16_to_cpu(ptable5->usCACLeakageTableOffset)); 1579 result = get_cac_leakage_table(hwmgr, 1580 &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table); 1581 } 1582 1583 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope); 1584 1585 hwmgr->dyn_state.ppm_parameter_table = NULL; 1586 1587 if (0 != ptable3->usExtendendedHeaderOffset) { 1588 extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) 1589 (((unsigned long)powerplay_table) + 1590 le16_to_cpu(ptable3->usExtendendedHeaderOffset)); 1591 if ((extended_header->usPPMTableOffset > 0) && 1592 le16_to_cpu(extended_header->usSize) >= 1593 SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) { 1594 table_offset = le16_to_cpu(extended_header->usPPMTableOffset); 1595 atom_ppm_table = (ATOM_PPLIB_PPM_Table *) 1596 (((unsigned long)powerplay_table) + table_offset); 1597 if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table)) 1598 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1599 PHM_PlatformCaps_EnablePlatformPowerManagement); 1600 } 1601 } 1602 } 1603 return result; 1604 } 1605 1606 static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, 1607 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) 1608 { 1609 if (le16_to_cpu(powerplay_table->usTableSize) >= 1610 sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { 1611 const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = 1612 (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; 1613 1614 if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) { 1615 const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable = 1616 (ATOM_PPLIB_PhaseSheddingLimits_Table *) 1617 (((unsigned long)powerplay_table4) + 1618 le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); 1619 struct phm_phase_shedding_limits_table *table; 1620 unsigned long i; 1621 1622 1623 table = kzalloc_flex(*table, entries, 1624 ptable->ucNumEntries); 1625 if (!table) 1626 return -ENOMEM; 1627 1628 table->count = (unsigned long)ptable->ucNumEntries; 1629 1630 for (i = 0; i < table->count; i++) { 1631 table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage); 1632 table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16) 1633 | le16_to_cpu(ptable->entries[i].usSclkLow); 1634 table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16) 1635 | le16_to_cpu(ptable->entries[i].usMclkLow); 1636 } 1637 hwmgr->dyn_state.vddc_phase_shed_limits_table = table; 1638 } 1639 } 1640 1641 return 0; 1642 } 1643 1644 static int get_number_of_vce_state_table_entries( 1645 struct pp_hwmgr *hwmgr) 1646 { 1647 const ATOM_PPLIB_POWERPLAYTABLE *table = 1648 get_powerplay_table(hwmgr); 1649 const ATOM_PPLIB_VCE_State_Table *vce_table = 1650 get_vce_state_table(hwmgr, table); 1651 1652 if (vce_table) 1653 return vce_table->numEntries; 1654 1655 return 0; 1656 } 1657 1658 static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, 1659 unsigned long i, 1660 struct amd_vce_state *vce_state, 1661 void **clock_info, 1662 unsigned long *flag) 1663 { 1664 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); 1665 1666 const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table); 1667 1668 unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table); 1669 1670 const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset); 1671 1672 const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + 1673 le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); 1674 1675 const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i]; 1676 1677 const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex]; 1678 1679 unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F; 1680 1681 *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX); 1682 1683 vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow); 1684 vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow); 1685 1686 *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize)); 1687 1688 return 0; 1689 } 1690 1691 1692 static int pp_tables_initialize(struct pp_hwmgr *hwmgr) 1693 { 1694 int result; 1695 const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table; 1696 1697 if (hwmgr->chip_id == CHIP_RAVEN) 1698 return 0; 1699 1700 hwmgr->need_pp_table_upload = true; 1701 1702 powerplay_table = get_powerplay_table(hwmgr); 1703 1704 result = init_powerplay_tables(hwmgr, powerplay_table); 1705 1706 PP_ASSERT_WITH_CODE((result == 0), 1707 "init_powerplay_tables failed", return result); 1708 1709 result = set_platform_caps(hwmgr, 1710 le32_to_cpu(powerplay_table->ulPlatformCaps)); 1711 1712 PP_ASSERT_WITH_CODE((result == 0), 1713 "set_platform_caps failed", return result); 1714 1715 result = init_thermal_controller(hwmgr, powerplay_table); 1716 1717 PP_ASSERT_WITH_CODE((result == 0), 1718 "init_thermal_controller failed", return result); 1719 1720 result = init_overdrive_limits(hwmgr, powerplay_table); 1721 1722 PP_ASSERT_WITH_CODE((result == 0), 1723 "init_overdrive_limits failed", return result); 1724 1725 result = init_clock_voltage_dependency(hwmgr, 1726 powerplay_table); 1727 1728 PP_ASSERT_WITH_CODE((result == 0), 1729 "init_clock_voltage_dependency failed", return result); 1730 1731 result = init_dpm2_parameters(hwmgr, powerplay_table); 1732 1733 PP_ASSERT_WITH_CODE((result == 0), 1734 "init_dpm2_parameters failed", return result); 1735 1736 result = init_phase_shedding_table(hwmgr, powerplay_table); 1737 1738 PP_ASSERT_WITH_CODE((result == 0), 1739 "init_phase_shedding_table failed", return result); 1740 1741 return result; 1742 } 1743 1744 static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) 1745 { 1746 if (hwmgr->chip_id == CHIP_RAVEN) 1747 return 0; 1748 1749 kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); 1750 hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; 1751 1752 kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); 1753 hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; 1754 1755 kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); 1756 hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; 1757 1758 kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); 1759 hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; 1760 1761 kfree(hwmgr->dyn_state.valid_mclk_values); 1762 hwmgr->dyn_state.valid_mclk_values = NULL; 1763 1764 kfree(hwmgr->dyn_state.valid_sclk_values); 1765 hwmgr->dyn_state.valid_sclk_values = NULL; 1766 1767 kfree(hwmgr->dyn_state.cac_leakage_table); 1768 hwmgr->dyn_state.cac_leakage_table = NULL; 1769 1770 kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); 1771 hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; 1772 1773 kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); 1774 hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; 1775 1776 kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); 1777 hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; 1778 1779 kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); 1780 hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; 1781 1782 kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); 1783 hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; 1784 1785 kfree(hwmgr->dyn_state.cac_dtp_table); 1786 hwmgr->dyn_state.cac_dtp_table = NULL; 1787 1788 kfree(hwmgr->dyn_state.ppm_parameter_table); 1789 hwmgr->dyn_state.ppm_parameter_table = NULL; 1790 1791 kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); 1792 hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; 1793 1794 return 0; 1795 } 1796 1797 const struct pp_table_func pptable_funcs = { 1798 .pptable_init = pp_tables_initialize, 1799 .pptable_fini = pp_tables_uninitialize, 1800 .pptable_get_number_of_vce_state_table_entries = 1801 get_number_of_vce_state_table_entries, 1802 .pptable_get_vce_state_table_entry = 1803 get_vce_state_table_entry, 1804 }; 1805 1806