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