1/* $NetBSD: amdgpu_vega10_processpptables.c,v 1.3 2021/12/19 12:21:30 riastradh Exp $ */ 2 3/* 4 * Copyright 2016 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25#include <sys/cdefs.h> 26__KERNEL_RCSID(0, "$NetBSD: amdgpu_vega10_processpptables.c,v 1.3 2021/12/19 12:21:30 riastradh Exp $"); 27 28#include <linux/module.h> 29#include <linux/pci.h> 30#include <linux/slab.h> 31#include <linux/fb.h> 32 33#include "vega10_processpptables.h" 34#include "ppatomfwctrl.h" 35#include "atomfirmware.h" 36#include "pp_debug.h" 37#include "cgs_common.h" 38#include "vega10_pptable.h" 39 40#define NUM_DSPCLK_LEVELS 8 41#define VEGA10_ENGINECLOCK_HARDMAX 198000 42 43static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, 44 enum phm_platform_caps cap) 45{ 46 if (enable) 47 phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); 48 else 49 phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); 50} 51 52static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) 53{ 54 int index = GetIndexIntoMasterDataTable(powerplayinfo); 55 56 u16 size; 57 u8 frev, crev; 58 const void *table_address = hwmgr->soft_pp_table; 59 60 if (!table_address) { 61 table_address = (ATOM_Vega10_POWERPLAYTABLE *) 62 smu_atom_get_data_table(hwmgr->adev, index, 63 &size, &frev, &crev); 64 65 hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ 66 hwmgr->soft_pp_table_size = size; 67 } 68 69 return table_address; 70} 71 72static int check_powerplay_tables( 73 struct pp_hwmgr *hwmgr, 74 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 75{ 76 const ATOM_Vega10_State_Array *state_arrays; 77 78 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) + 79 le16_to_cpu(powerplay_table->usStateArrayOffset)); 80 81 PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= 82 ATOM_Vega10_TABLE_REVISION_VEGA10), 83 "Unsupported PPTable format!", return -1); 84 PP_ASSERT_WITH_CODE(powerplay_table->usStateArrayOffset, 85 "State table is not set!", return -1); 86 PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, 87 "Invalid PowerPlay Table!", return -1); 88 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, 89 "Invalid PowerPlay Table!", return -1); 90 91 return 0; 92} 93 94static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) 95{ 96 set_hw_cap( 97 hwmgr, 98 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY), 99 PHM_PlatformCaps_PowerPlaySupport); 100 101 set_hw_cap( 102 hwmgr, 103 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), 104 PHM_PlatformCaps_BiosPowerSourceControl); 105 106 set_hw_cap( 107 hwmgr, 108 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC), 109 PHM_PlatformCaps_AutomaticDCTransition); 110 111 set_hw_cap( 112 hwmgr, 113 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), 114 PHM_PlatformCaps_BACO); 115 116 set_hw_cap( 117 hwmgr, 118 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), 119 PHM_PlatformCaps_CombinePCCWithThermalSignal); 120 121 return 0; 122} 123 124static int init_thermal_controller( 125 struct pp_hwmgr *hwmgr, 126 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 127{ 128 const ATOM_Vega10_Thermal_Controller *thermal_controller; 129 const Vega10_PPTable_Generic_SubTable_Header *header; 130 const ATOM_Vega10_Fan_Table *fan_table_v1; 131 const ATOM_Vega10_Fan_Table_V2 *fan_table_v2; 132 const ATOM_Vega10_Fan_Table_V3 *fan_table_v3; 133 134 thermal_controller = (ATOM_Vega10_Thermal_Controller *) 135 (((unsigned long)powerplay_table) + 136 le16_to_cpu(powerplay_table->usThermalControllerOffset)); 137 138 PP_ASSERT_WITH_CODE((powerplay_table->usThermalControllerOffset != 0), 139 "Thermal controller table not set!", return -EINVAL); 140 141 hwmgr->thermal_controller.ucType = thermal_controller->ucType; 142 hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; 143 hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; 144 145 hwmgr->thermal_controller.fanInfo.bNoFan = 146 (0 != (thermal_controller->ucFanParameters & 147 ATOM_VEGA10_PP_FANPARAMETERS_NOFAN)); 148 149 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = 150 thermal_controller->ucFanParameters & 151 ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 152 153 hwmgr->thermal_controller.fanInfo.ulMinRPM = 154 thermal_controller->ucFanMinRPM * 100UL; 155 hwmgr->thermal_controller.fanInfo.ulMaxRPM = 156 thermal_controller->ucFanMaxRPM * 100UL; 157 158 hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay 159 = 100000; 160 161 set_hw_cap( 162 hwmgr, 163 ATOM_VEGA10_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, 164 PHM_PlatformCaps_ThermalController); 165 166 if (!powerplay_table->usFanTableOffset) 167 return 0; 168 169 header = (const Vega10_PPTable_Generic_SubTable_Header *) 170 (((unsigned long)powerplay_table) + 171 le16_to_cpu(powerplay_table->usFanTableOffset)); 172 173 if (header->ucRevId == 10) { 174 fan_table_v1 = (const ATOM_Vega10_Fan_Table *)header; 175 176 PP_ASSERT_WITH_CODE((fan_table_v1->ucRevId >= 8), 177 "Invalid Input Fan Table!", return -EINVAL); 178 179 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 180 PHM_PlatformCaps_MicrocodeFanControl); 181 182 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = 183 le16_to_cpu(fan_table_v1->usFanOutputSensitivity); 184 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = 185 le16_to_cpu(fan_table_v1->usFanRPMMax); 186 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 187 le16_to_cpu(fan_table_v1->usThrottlingRPM); 188 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = 189 le16_to_cpu(fan_table_v1->usFanAcousticLimit); 190 hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 191 le16_to_cpu(fan_table_v1->usTargetTemperature); 192 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = 193 le16_to_cpu(fan_table_v1->usMinimumPWMLimit); 194 hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = 195 le16_to_cpu(fan_table_v1->usTargetGfxClk); 196 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = 197 le16_to_cpu(fan_table_v1->usFanGainEdge); 198 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = 199 le16_to_cpu(fan_table_v1->usFanGainHotspot); 200 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = 201 le16_to_cpu(fan_table_v1->usFanGainLiquid); 202 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = 203 le16_to_cpu(fan_table_v1->usFanGainVrVddc); 204 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = 205 le16_to_cpu(fan_table_v1->usFanGainVrMvdd); 206 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = 207 le16_to_cpu(fan_table_v1->usFanGainPlx); 208 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = 209 le16_to_cpu(fan_table_v1->usFanGainHbm); 210 211 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = 212 fan_table_v1->ucEnableZeroRPM; 213 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = 214 le16_to_cpu(fan_table_v1->usFanStopTemperature); 215 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = 216 le16_to_cpu(fan_table_v1->usFanStartTemperature); 217 } else if (header->ucRevId == 0xb) { 218 fan_table_v2 = (const ATOM_Vega10_Fan_Table_V2 *)header; 219 220 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = 221 fan_table_v2->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 222 hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v2->ucFanMinRPM * 100UL; 223 hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v2->ucFanMaxRPM * 100UL; 224 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 225 PHM_PlatformCaps_MicrocodeFanControl); 226 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = 227 le16_to_cpu(fan_table_v2->usFanOutputSensitivity); 228 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = 229 fan_table_v2->ucFanMaxRPM * 100UL; 230 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 231 le16_to_cpu(fan_table_v2->usThrottlingRPM); 232 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = 233 le16_to_cpu(fan_table_v2->usFanAcousticLimitRpm); 234 hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 235 le16_to_cpu(fan_table_v2->usTargetTemperature); 236 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = 237 le16_to_cpu(fan_table_v2->usMinimumPWMLimit); 238 hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = 239 le16_to_cpu(fan_table_v2->usTargetGfxClk); 240 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = 241 le16_to_cpu(fan_table_v2->usFanGainEdge); 242 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = 243 le16_to_cpu(fan_table_v2->usFanGainHotspot); 244 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = 245 le16_to_cpu(fan_table_v2->usFanGainLiquid); 246 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = 247 le16_to_cpu(fan_table_v2->usFanGainVrVddc); 248 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = 249 le16_to_cpu(fan_table_v2->usFanGainVrMvdd); 250 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = 251 le16_to_cpu(fan_table_v2->usFanGainPlx); 252 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = 253 le16_to_cpu(fan_table_v2->usFanGainHbm); 254 255 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = 256 fan_table_v2->ucEnableZeroRPM; 257 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = 258 le16_to_cpu(fan_table_v2->usFanStopTemperature); 259 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = 260 le16_to_cpu(fan_table_v2->usFanStartTemperature); 261 } else if (header->ucRevId > 0xb) { 262 fan_table_v3 = (const ATOM_Vega10_Fan_Table_V3 *)header; 263 264 hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = 265 fan_table_v3->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; 266 hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v3->ucFanMinRPM * 100UL; 267 hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v3->ucFanMaxRPM * 100UL; 268 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 269 PHM_PlatformCaps_MicrocodeFanControl); 270 hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = 271 le16_to_cpu(fan_table_v3->usFanOutputSensitivity); 272 hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = 273 fan_table_v3->ucFanMaxRPM * 100UL; 274 hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 275 le16_to_cpu(fan_table_v3->usThrottlingRPM); 276 hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = 277 le16_to_cpu(fan_table_v3->usFanAcousticLimitRpm); 278 hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 279 le16_to_cpu(fan_table_v3->usTargetTemperature); 280 hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = 281 le16_to_cpu(fan_table_v3->usMinimumPWMLimit); 282 hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = 283 le16_to_cpu(fan_table_v3->usTargetGfxClk); 284 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = 285 le16_to_cpu(fan_table_v3->usFanGainEdge); 286 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = 287 le16_to_cpu(fan_table_v3->usFanGainHotspot); 288 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = 289 le16_to_cpu(fan_table_v3->usFanGainLiquid); 290 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = 291 le16_to_cpu(fan_table_v3->usFanGainVrVddc); 292 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = 293 le16_to_cpu(fan_table_v3->usFanGainVrMvdd); 294 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = 295 le16_to_cpu(fan_table_v3->usFanGainPlx); 296 hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = 297 le16_to_cpu(fan_table_v3->usFanGainHbm); 298 299 hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = 300 fan_table_v3->ucEnableZeroRPM; 301 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = 302 le16_to_cpu(fan_table_v3->usFanStopTemperature); 303 hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = 304 le16_to_cpu(fan_table_v3->usFanStartTemperature); 305 hwmgr->thermal_controller.advanceFanControlParameters.usMGpuThrottlingRPMLimit = 306 le16_to_cpu(fan_table_v3->usMGpuThrottlingRPM); 307 } 308 309 return 0; 310} 311 312static int init_over_drive_limits( 313 struct pp_hwmgr *hwmgr, 314 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 315{ 316 const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = 317 (const ATOM_Vega10_GFXCLK_Dependency_Table *) 318 (((unsigned long) powerplay_table) + 319 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); 320 bool is_acg_enabled = false; 321 const ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; 322 323 if (gfxclk_dep_table->ucRevId == 1) { 324 patom_record_v2 = 325 (const ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; 326 is_acg_enabled = 327 (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable; 328 } 329 330 if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX && 331 !is_acg_enabled) 332 hwmgr->platform_descriptor.overdriveLimit.engineClock = 333 VEGA10_ENGINECLOCK_HARDMAX; 334 else 335 hwmgr->platform_descriptor.overdriveLimit.engineClock = 336 le32_to_cpu(powerplay_table->ulMaxODEngineClock); 337 hwmgr->platform_descriptor.overdriveLimit.memoryClock = 338 le32_to_cpu(powerplay_table->ulMaxODMemoryClock); 339 340 hwmgr->platform_descriptor.minOverdriveVDDC = 0; 341 hwmgr->platform_descriptor.maxOverdriveVDDC = 0; 342 hwmgr->platform_descriptor.overdriveVDDCStep = 0; 343 344 return 0; 345} 346 347static int get_mm_clock_voltage_table( 348 struct pp_hwmgr *hwmgr, 349 phm_ppt_v1_mm_clock_voltage_dependency_table **vega10_mm_table, 350 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table) 351{ 352 uint32_t table_size, i; 353 const ATOM_Vega10_MM_Dependency_Record *mm_dependency_record; 354 phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; 355 356 PP_ASSERT_WITH_CODE((mm_dependency_table->ucNumEntries != 0), 357 "Invalid PowerPlay Table!", return -1); 358 359 table_size = sizeof(uint32_t) + 360 sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) * 361 mm_dependency_table->ucNumEntries; 362 mm_table = kzalloc(table_size, GFP_KERNEL); 363 364 if (!mm_table) 365 return -ENOMEM; 366 367 mm_table->count = mm_dependency_table->ucNumEntries; 368 369 for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { 370 mm_dependency_record = &mm_dependency_table->entries[i]; 371 mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd; 372 mm_table->entries[i].samclock = 373 le32_to_cpu(mm_dependency_record->ulPSPClk); 374 mm_table->entries[i].eclk = le32_to_cpu(mm_dependency_record->ulEClk); 375 mm_table->entries[i].vclk = le32_to_cpu(mm_dependency_record->ulVClk); 376 mm_table->entries[i].dclk = le32_to_cpu(mm_dependency_record->ulDClk); 377 } 378 379 *vega10_mm_table = mm_table; 380 381 return 0; 382} 383 384static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda) 385{ 386 switch(line){ 387 case Vega10_I2CLineID_DDC1: 388 *scl = Vega10_I2C_DDC1CLK; 389 *sda = Vega10_I2C_DDC1DATA; 390 break; 391 case Vega10_I2CLineID_DDC2: 392 *scl = Vega10_I2C_DDC2CLK; 393 *sda = Vega10_I2C_DDC2DATA; 394 break; 395 case Vega10_I2CLineID_DDC3: 396 *scl = Vega10_I2C_DDC3CLK; 397 *sda = Vega10_I2C_DDC3DATA; 398 break; 399 case Vega10_I2CLineID_DDC4: 400 *scl = Vega10_I2C_DDC4CLK; 401 *sda = Vega10_I2C_DDC4DATA; 402 break; 403 case Vega10_I2CLineID_DDC5: 404 *scl = Vega10_I2C_DDC5CLK; 405 *sda = Vega10_I2C_DDC5DATA; 406 break; 407 case Vega10_I2CLineID_DDC6: 408 *scl = Vega10_I2C_DDC6CLK; 409 *sda = Vega10_I2C_DDC6DATA; 410 break; 411 case Vega10_I2CLineID_SCLSDA: 412 *scl = Vega10_I2C_SCL; 413 *sda = Vega10_I2C_SDA; 414 break; 415 case Vega10_I2CLineID_DDCVGA: 416 *scl = Vega10_I2C_DDCVGACLK; 417 *sda = Vega10_I2C_DDCVGADATA; 418 break; 419 default: 420 *scl = 0; 421 *sda = 0; 422 break; 423 } 424} 425 426static int get_tdp_table( 427 struct pp_hwmgr *hwmgr, 428 struct phm_tdp_table **info_tdp_table, 429 const Vega10_PPTable_Generic_SubTable_Header *table) 430{ 431 uint32_t table_size; 432 struct phm_tdp_table *tdp_table; 433 uint8_t scl; 434 uint8_t sda; 435 const ATOM_Vega10_PowerTune_Table *power_tune_table; 436 const ATOM_Vega10_PowerTune_Table_V2 *power_tune_table_v2; 437 const ATOM_Vega10_PowerTune_Table_V3 *power_tune_table_v3; 438 439 table_size = sizeof(uint32_t) + sizeof(struct phm_tdp_table); 440 441 tdp_table = kzalloc(table_size, GFP_KERNEL); 442 443 if (!tdp_table) 444 return -ENOMEM; 445 446 if (table->ucRevId == 5) { 447 power_tune_table = (const ATOM_Vega10_PowerTune_Table *)table; 448 tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table->usSocketPowerLimit); 449 tdp_table->usTDC = le16_to_cpu(power_tune_table->usTdcLimit); 450 tdp_table->usEDCLimit = le16_to_cpu(power_tune_table->usEdcLimit); 451 tdp_table->usSoftwareShutdownTemp = 452 le16_to_cpu(power_tune_table->usSoftwareShutdownTemp); 453 tdp_table->usTemperatureLimitTedge = 454 le16_to_cpu(power_tune_table->usTemperatureLimitTedge); 455 tdp_table->usTemperatureLimitHotspot = 456 le16_to_cpu(power_tune_table->usTemperatureLimitHotSpot); 457 tdp_table->usTemperatureLimitLiquid1 = 458 le16_to_cpu(power_tune_table->usTemperatureLimitLiquid1); 459 tdp_table->usTemperatureLimitLiquid2 = 460 le16_to_cpu(power_tune_table->usTemperatureLimitLiquid2); 461 tdp_table->usTemperatureLimitHBM = 462 le16_to_cpu(power_tune_table->usTemperatureLimitHBM); 463 tdp_table->usTemperatureLimitVrVddc = 464 le16_to_cpu(power_tune_table->usTemperatureLimitVrSoc); 465 tdp_table->usTemperatureLimitVrMvdd = 466 le16_to_cpu(power_tune_table->usTemperatureLimitVrMem); 467 tdp_table->usTemperatureLimitPlx = 468 le16_to_cpu(power_tune_table->usTemperatureLimitPlx); 469 tdp_table->ucLiquid1_I2C_address = power_tune_table->ucLiquid1_I2C_address; 470 tdp_table->ucLiquid2_I2C_address = power_tune_table->ucLiquid2_I2C_address; 471 tdp_table->ucLiquid_I2C_Line = power_tune_table->ucLiquid_I2C_LineSCL; 472 tdp_table->ucLiquid_I2C_LineSDA = power_tune_table->ucLiquid_I2C_LineSDA; 473 tdp_table->ucVr_I2C_address = power_tune_table->ucVr_I2C_address; 474 tdp_table->ucVr_I2C_Line = power_tune_table->ucVr_I2C_LineSCL; 475 tdp_table->ucVr_I2C_LineSDA = power_tune_table->ucVr_I2C_LineSDA; 476 tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address; 477 tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL; 478 tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA; 479 hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(power_tune_table->usLoadLineResistance); 480 } else if (table->ucRevId == 6) { 481 power_tune_table_v2 = (const ATOM_Vega10_PowerTune_Table_V2 *)table; 482 tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v2->usSocketPowerLimit); 483 tdp_table->usTDC = le16_to_cpu(power_tune_table_v2->usTdcLimit); 484 tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v2->usEdcLimit); 485 tdp_table->usSoftwareShutdownTemp = 486 le16_to_cpu(power_tune_table_v2->usSoftwareShutdownTemp); 487 tdp_table->usTemperatureLimitTedge = 488 le16_to_cpu(power_tune_table_v2->usTemperatureLimitTedge); 489 tdp_table->usTemperatureLimitHotspot = 490 le16_to_cpu(power_tune_table_v2->usTemperatureLimitHotSpot); 491 tdp_table->usTemperatureLimitLiquid1 = 492 le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid1); 493 tdp_table->usTemperatureLimitLiquid2 = 494 le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid2); 495 tdp_table->usTemperatureLimitHBM = 496 le16_to_cpu(power_tune_table_v2->usTemperatureLimitHBM); 497 tdp_table->usTemperatureLimitVrVddc = 498 le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrSoc); 499 tdp_table->usTemperatureLimitVrMvdd = 500 le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrMem); 501 tdp_table->usTemperatureLimitPlx = 502 le16_to_cpu(power_tune_table_v2->usTemperatureLimitPlx); 503 tdp_table->ucLiquid1_I2C_address = power_tune_table_v2->ucLiquid1_I2C_address; 504 tdp_table->ucLiquid2_I2C_address = power_tune_table_v2->ucLiquid2_I2C_address; 505 506 get_scl_sda_value(power_tune_table_v2->ucLiquid_I2C_Line, &scl, &sda); 507 508 tdp_table->ucLiquid_I2C_Line = scl; 509 tdp_table->ucLiquid_I2C_LineSDA = sda; 510 511 tdp_table->ucVr_I2C_address = power_tune_table_v2->ucVr_I2C_address; 512 513 get_scl_sda_value(power_tune_table_v2->ucVr_I2C_Line, &scl, &sda); 514 515 tdp_table->ucVr_I2C_Line = scl; 516 tdp_table->ucVr_I2C_LineSDA = sda; 517 tdp_table->ucPlx_I2C_address = power_tune_table_v2->ucPlx_I2C_address; 518 519 get_scl_sda_value(power_tune_table_v2->ucPlx_I2C_Line, &scl, &sda); 520 521 tdp_table->ucPlx_I2C_Line = scl; 522 tdp_table->ucPlx_I2C_LineSDA = sda; 523 524 hwmgr->platform_descriptor.LoadLineSlope = 525 le16_to_cpu(power_tune_table_v2->usLoadLineResistance); 526 } else { 527 power_tune_table_v3 = (const ATOM_Vega10_PowerTune_Table_V3 *)table; 528 tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v3->usSocketPowerLimit); 529 tdp_table->usTDC = le16_to_cpu(power_tune_table_v3->usTdcLimit); 530 tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v3->usEdcLimit); 531 tdp_table->usSoftwareShutdownTemp = le16_to_cpu(power_tune_table_v3->usSoftwareShutdownTemp); 532 tdp_table->usTemperatureLimitTedge = le16_to_cpu(power_tune_table_v3->usTemperatureLimitTedge); 533 tdp_table->usTemperatureLimitHotspot = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHotSpot); 534 tdp_table->usTemperatureLimitLiquid1 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid1); 535 tdp_table->usTemperatureLimitLiquid2 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid2); 536 tdp_table->usTemperatureLimitHBM = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHBM); 537 tdp_table->usTemperatureLimitVrVddc = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrSoc); 538 tdp_table->usTemperatureLimitVrMvdd = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrMem); 539 tdp_table->usTemperatureLimitPlx = le16_to_cpu(power_tune_table_v3->usTemperatureLimitPlx); 540 tdp_table->ucLiquid1_I2C_address = power_tune_table_v3->ucLiquid1_I2C_address; 541 tdp_table->ucLiquid2_I2C_address = power_tune_table_v3->ucLiquid2_I2C_address; 542 tdp_table->usBoostStartTemperature = le16_to_cpu(power_tune_table_v3->usBoostStartTemperature); 543 tdp_table->usBoostStopTemperature = le16_to_cpu(power_tune_table_v3->usBoostStopTemperature); 544 tdp_table->ulBoostClock = le32_to_cpu(power_tune_table_v3->ulBoostClock); 545 546 get_scl_sda_value(power_tune_table_v3->ucLiquid_I2C_Line, &scl, &sda); 547 548 tdp_table->ucLiquid_I2C_Line = scl; 549 tdp_table->ucLiquid_I2C_LineSDA = sda; 550 551 tdp_table->ucVr_I2C_address = power_tune_table_v3->ucVr_I2C_address; 552 553 get_scl_sda_value(power_tune_table_v3->ucVr_I2C_Line, &scl, &sda); 554 555 tdp_table->ucVr_I2C_Line = scl; 556 tdp_table->ucVr_I2C_LineSDA = sda; 557 558 tdp_table->ucPlx_I2C_address = power_tune_table_v3->ucPlx_I2C_address; 559 560 get_scl_sda_value(power_tune_table_v3->ucPlx_I2C_Line, &scl, &sda); 561 562 tdp_table->ucPlx_I2C_Line = scl; 563 tdp_table->ucPlx_I2C_LineSDA = sda; 564 565 hwmgr->platform_descriptor.LoadLineSlope = 566 le16_to_cpu(power_tune_table_v3->usLoadLineResistance); 567 } 568 569 *info_tdp_table = tdp_table; 570 571 return 0; 572} 573 574static int get_socclk_voltage_dependency_table( 575 struct pp_hwmgr *hwmgr, 576 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_clk_dep_table, 577 const ATOM_Vega10_SOCCLK_Dependency_Table *clk_dep_table) 578{ 579 uint32_t table_size, i; 580 phm_ppt_v1_clock_voltage_dependency_table *clk_table; 581 582 PP_ASSERT_WITH_CODE(clk_dep_table->ucNumEntries, 583 "Invalid PowerPlay Table!", return -1); 584 585 table_size = sizeof(uint32_t) + 586 sizeof(phm_ppt_v1_clock_voltage_dependency_record) * 587 clk_dep_table->ucNumEntries; 588 589 clk_table = kzalloc(table_size, GFP_KERNEL); 590 591 if (!clk_table) 592 return -ENOMEM; 593 594 clk_table->count = (uint32_t)clk_dep_table->ucNumEntries; 595 596 for (i = 0; i < clk_dep_table->ucNumEntries; i++) { 597 clk_table->entries[i].vddInd = 598 clk_dep_table->entries[i].ucVddInd; 599 clk_table->entries[i].clk = 600 le32_to_cpu(clk_dep_table->entries[i].ulClk); 601 } 602 603 *pp_vega10_clk_dep_table = clk_table; 604 605 return 0; 606} 607 608static int get_mclk_voltage_dependency_table( 609 struct pp_hwmgr *hwmgr, 610 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table, 611 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table) 612{ 613 uint32_t table_size, i; 614 phm_ppt_v1_clock_voltage_dependency_table *mclk_table; 615 616 PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries, 617 "Invalid PowerPlay Table!", return -1); 618 619 table_size = sizeof(uint32_t) + 620 sizeof(phm_ppt_v1_clock_voltage_dependency_record) * 621 mclk_dep_table->ucNumEntries; 622 623 mclk_table = kzalloc(table_size, GFP_KERNEL); 624 625 if (!mclk_table) 626 return -ENOMEM; 627 628 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; 629 630 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { 631 mclk_table->entries[i].vddInd = 632 mclk_dep_table->entries[i].ucVddInd; 633 mclk_table->entries[i].vddciInd = 634 mclk_dep_table->entries[i].ucVddciInd; 635 mclk_table->entries[i].mvddInd = 636 mclk_dep_table->entries[i].ucVddMemInd; 637 mclk_table->entries[i].clk = 638 le32_to_cpu(mclk_dep_table->entries[i].ulMemClk); 639 } 640 641 *pp_vega10_mclk_dep_table = mclk_table; 642 643 return 0; 644} 645 646static int get_gfxclk_voltage_dependency_table( 647 struct pp_hwmgr *hwmgr, 648 struct phm_ppt_v1_clock_voltage_dependency_table 649 **pp_vega10_clk_dep_table, 650 const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table) 651{ 652 uint32_t table_size, i; 653 struct phm_ppt_v1_clock_voltage_dependency_table 654 *clk_table; 655 const ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; 656 657 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), 658 "Invalid PowerPlay Table!", return -1); 659 660 table_size = sizeof(uint32_t) + 661 sizeof(phm_ppt_v1_clock_voltage_dependency_record) * 662 clk_dep_table->ucNumEntries; 663 664 clk_table = kzalloc(table_size, GFP_KERNEL); 665 666 if (!clk_table) 667 return -ENOMEM; 668 669 clk_table->count = clk_dep_table->ucNumEntries; 670 671 if (clk_dep_table->ucRevId == 0) { 672 for (i = 0; i < clk_table->count; i++) { 673 clk_table->entries[i].vddInd = 674 clk_dep_table->entries[i].ucVddInd; 675 clk_table->entries[i].clk = 676 le32_to_cpu(clk_dep_table->entries[i].ulClk); 677 clk_table->entries[i].cks_enable = 678 (((le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x8000) 679 >> 15) == 0) ? 1 : 0; 680 clk_table->entries[i].cks_voffset = 681 le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x7F; 682 clk_table->entries[i].sclk_offset = 683 le16_to_cpu(clk_dep_table->entries[i].usAVFSOffset); 684 } 685 } else if (clk_dep_table->ucRevId == 1) { 686 patom_record_v2 = (const ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)clk_dep_table->entries; 687 for (i = 0; i < clk_table->count; i++) { 688 clk_table->entries[i].vddInd = 689 patom_record_v2->ucVddInd; 690 clk_table->entries[i].clk = 691 le32_to_cpu(patom_record_v2->ulClk); 692 clk_table->entries[i].cks_enable = 693 (((le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x8000) 694 >> 15) == 0) ? 1 : 0; 695 clk_table->entries[i].cks_voffset = 696 le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x7F; 697 clk_table->entries[i].sclk_offset = 698 le16_to_cpu(patom_record_v2->usAVFSOffset); 699 patom_record_v2++; 700 } 701 } else { 702 kfree(clk_table); 703 PP_ASSERT_WITH_CODE(false, 704 "Unsupported GFXClockDependencyTable Revision!", 705 return -EINVAL); 706 } 707 708 *pp_vega10_clk_dep_table = clk_table; 709 710 return 0; 711} 712 713static int get_pix_clk_voltage_dependency_table( 714 struct pp_hwmgr *hwmgr, 715 struct phm_ppt_v1_clock_voltage_dependency_table 716 **pp_vega10_clk_dep_table, 717 const ATOM_Vega10_PIXCLK_Dependency_Table *clk_dep_table) 718{ 719 uint32_t table_size, i; 720 struct phm_ppt_v1_clock_voltage_dependency_table 721 *clk_table; 722 723 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), 724 "Invalid PowerPlay Table!", return -1); 725 726 table_size = sizeof(uint32_t) + 727 sizeof(phm_ppt_v1_clock_voltage_dependency_record) * 728 clk_dep_table->ucNumEntries; 729 730 clk_table = kzalloc(table_size, GFP_KERNEL); 731 732 if (!clk_table) 733 return -ENOMEM; 734 735 clk_table->count = clk_dep_table->ucNumEntries; 736 737 for (i = 0; i < clk_table->count; i++) { 738 clk_table->entries[i].vddInd = 739 clk_dep_table->entries[i].ucVddInd; 740 clk_table->entries[i].clk = 741 le32_to_cpu(clk_dep_table->entries[i].ulClk); 742 } 743 744 *pp_vega10_clk_dep_table = clk_table; 745 746 return 0; 747} 748 749static int get_dcefclk_voltage_dependency_table( 750 struct pp_hwmgr *hwmgr, 751 struct phm_ppt_v1_clock_voltage_dependency_table 752 **pp_vega10_clk_dep_table, 753 const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table) 754{ 755 uint32_t table_size, i; 756 uint8_t num_entries; 757 struct phm_ppt_v1_clock_voltage_dependency_table 758 *clk_table; 759 uint32_t dev_id; 760 uint32_t rev_id; 761 struct amdgpu_device *adev = hwmgr->adev; 762 763 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), 764 "Invalid PowerPlay Table!", return -1); 765 766/* 767 * workaround needed to add another DPM level for pioneer cards 768 * as VBIOS is locked down. 769 * This DPM level was added to support 3DPM monitors @ 4K120Hz 770 * 771 */ 772 dev_id = adev->pdev->device; 773 rev_id = adev->pdev->revision; 774 775 if (dev_id == 0x6863 && rev_id == 0 && 776 clk_dep_table->entries[clk_dep_table->ucNumEntries - 1].ulClk < 90000) 777 num_entries = clk_dep_table->ucNumEntries + 1 > NUM_DSPCLK_LEVELS ? 778 NUM_DSPCLK_LEVELS : clk_dep_table->ucNumEntries + 1; 779 else 780 num_entries = clk_dep_table->ucNumEntries; 781 782 783 table_size = sizeof(uint32_t) + 784 sizeof(phm_ppt_v1_clock_voltage_dependency_record) * 785 num_entries; 786 787 clk_table = kzalloc(table_size, GFP_KERNEL); 788 789 if (!clk_table) 790 return -ENOMEM; 791 792 clk_table->count = (uint32_t)num_entries; 793 794 for (i = 0; i < clk_dep_table->ucNumEntries; i++) { 795 clk_table->entries[i].vddInd = 796 clk_dep_table->entries[i].ucVddInd; 797 clk_table->entries[i].clk = 798 le32_to_cpu(clk_dep_table->entries[i].ulClk); 799 } 800 801 if (i < num_entries) { 802 clk_table->entries[i].vddInd = clk_dep_table->entries[i-1].ucVddInd; 803 clk_table->entries[i].clk = 90000; 804 } 805 806 *pp_vega10_clk_dep_table = clk_table; 807 808 return 0; 809} 810 811static int get_pcie_table(struct pp_hwmgr *hwmgr, 812 struct phm_ppt_v1_pcie_table **vega10_pcie_table, 813 const Vega10_PPTable_Generic_SubTable_Header *table) 814{ 815 uint32_t table_size, i, pcie_count; 816 struct phm_ppt_v1_pcie_table *pcie_table; 817 struct phm_ppt_v2_information *table_info = 818 (struct phm_ppt_v2_information *)(hwmgr->pptable); 819 const ATOM_Vega10_PCIE_Table *atom_pcie_table = 820 (const ATOM_Vega10_PCIE_Table *)table; 821 822 PP_ASSERT_WITH_CODE(atom_pcie_table->ucNumEntries, 823 "Invalid PowerPlay Table!", 824 return 0); 825 826 table_size = sizeof(uint32_t) + 827 sizeof(struct phm_ppt_v1_pcie_record) * 828 atom_pcie_table->ucNumEntries; 829 830 pcie_table = kzalloc(table_size, GFP_KERNEL); 831 832 if (!pcie_table) 833 return -ENOMEM; 834 835 pcie_count = table_info->vdd_dep_on_sclk->count; 836 if (atom_pcie_table->ucNumEntries <= pcie_count) 837 pcie_count = atom_pcie_table->ucNumEntries; 838 else 839 pr_info("Number of Pcie Entries exceed the number of" 840 " GFXCLK Dpm Levels!" 841 " Disregarding the excess entries...\n"); 842 843 pcie_table->count = pcie_count; 844 845 for (i = 0; i < pcie_count; i++) { 846 pcie_table->entries[i].gen_speed = 847 atom_pcie_table->entries[i].ucPCIEGenSpeed; 848 pcie_table->entries[i].lane_width = 849 atom_pcie_table->entries[i].ucPCIELaneWidth; 850 pcie_table->entries[i].pcie_sclk = 851 atom_pcie_table->entries[i].ulLCLK; 852 } 853 854 *vega10_pcie_table = pcie_table; 855 856 return 0; 857} 858 859static int get_hard_limits( 860 struct pp_hwmgr *hwmgr, 861 struct phm_clock_and_voltage_limits *limits, 862 const ATOM_Vega10_Hard_Limit_Table *limit_table) 863{ 864 PP_ASSERT_WITH_CODE(limit_table->ucNumEntries, 865 "Invalid PowerPlay Table!", return -1); 866 867 /* currently we always take entries[0] parameters */ 868 limits->sclk = le32_to_cpu(limit_table->entries[0].ulSOCCLKLimit); 869 limits->mclk = le32_to_cpu(limit_table->entries[0].ulMCLKLimit); 870 limits->gfxclk = le32_to_cpu(limit_table->entries[0].ulGFXCLKLimit); 871 limits->vddc = le16_to_cpu(limit_table->entries[0].usVddcLimit); 872 limits->vddci = le16_to_cpu(limit_table->entries[0].usVddciLimit); 873 limits->vddmem = le16_to_cpu(limit_table->entries[0].usVddMemLimit); 874 875 return 0; 876} 877 878static int get_valid_clk( 879 struct pp_hwmgr *hwmgr, 880 struct phm_clock_array **clk_table, 881 const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table) 882{ 883 uint32_t table_size, i; 884 struct phm_clock_array *table; 885 886 PP_ASSERT_WITH_CODE(clk_volt_pp_table->count, 887 "Invalid PowerPlay Table!", return -1); 888 889 table_size = sizeof(uint32_t) + 890 sizeof(uint32_t) * clk_volt_pp_table->count; 891 892 table = kzalloc(table_size, GFP_KERNEL); 893 894 if (!table) 895 return -ENOMEM; 896 897 table->count = (uint32_t)clk_volt_pp_table->count; 898 899 for (i = 0; i < table->count; i++) 900 table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; 901 902 *clk_table = table; 903 904 return 0; 905} 906 907static int init_powerplay_extended_tables( 908 struct pp_hwmgr *hwmgr, 909 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 910{ 911 int result = 0; 912 struct phm_ppt_v2_information *pp_table_info = 913 (struct phm_ppt_v2_information *)(hwmgr->pptable); 914 915 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table = 916 (const ATOM_Vega10_MM_Dependency_Table *) 917 (((unsigned long) powerplay_table) + 918 le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); 919 const Vega10_PPTable_Generic_SubTable_Header *power_tune_table = 920 (const Vega10_PPTable_Generic_SubTable_Header *) 921 (((unsigned long) powerplay_table) + 922 le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); 923 const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = 924 (const ATOM_Vega10_SOCCLK_Dependency_Table *) 925 (((unsigned long) powerplay_table) + 926 le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); 927 const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = 928 (const ATOM_Vega10_GFXCLK_Dependency_Table *) 929 (((unsigned long) powerplay_table) + 930 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); 931 const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table = 932 (const ATOM_Vega10_DCEFCLK_Dependency_Table *) 933 (((unsigned long) powerplay_table) + 934 le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset)); 935 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = 936 (const ATOM_Vega10_MCLK_Dependency_Table *) 937 (((unsigned long) powerplay_table) + 938 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); 939 const ATOM_Vega10_Hard_Limit_Table *hard_limits = 940 (const ATOM_Vega10_Hard_Limit_Table *) 941 (((unsigned long) powerplay_table) + 942 le16_to_cpu(powerplay_table->usHardLimitTableOffset)); 943 const Vega10_PPTable_Generic_SubTable_Header *pcie_table = 944 (const Vega10_PPTable_Generic_SubTable_Header *) 945 (((unsigned long) powerplay_table) + 946 le16_to_cpu(powerplay_table->usPCIETableOffset)); 947 const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table = 948 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 949 (((unsigned long) powerplay_table) + 950 le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset)); 951 const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table = 952 (const ATOM_Vega10_PHYCLK_Dependency_Table *) 953 (((unsigned long) powerplay_table) + 954 le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset)); 955 const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table = 956 (const ATOM_Vega10_DISPCLK_Dependency_Table *) 957 (((unsigned long) powerplay_table) + 958 le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset)); 959 960 pp_table_info->vdd_dep_on_socclk = NULL; 961 pp_table_info->vdd_dep_on_sclk = NULL; 962 pp_table_info->vdd_dep_on_mclk = NULL; 963 pp_table_info->vdd_dep_on_dcefclk = NULL; 964 pp_table_info->mm_dep_table = NULL; 965 pp_table_info->tdp_table = NULL; 966 pp_table_info->vdd_dep_on_pixclk = NULL; 967 pp_table_info->vdd_dep_on_phyclk = NULL; 968 pp_table_info->vdd_dep_on_dispclk = NULL; 969 970 if (powerplay_table->usMMDependencyTableOffset) 971 result = get_mm_clock_voltage_table(hwmgr, 972 &pp_table_info->mm_dep_table, 973 mm_dependency_table); 974 975 if (!result && powerplay_table->usPowerTuneTableOffset) 976 result = get_tdp_table(hwmgr, 977 &pp_table_info->tdp_table, 978 power_tune_table); 979 980 if (!result && powerplay_table->usSocclkDependencyTableOffset) 981 result = get_socclk_voltage_dependency_table(hwmgr, 982 &pp_table_info->vdd_dep_on_socclk, 983 socclk_dep_table); 984 985 if (!result && powerplay_table->usGfxclkDependencyTableOffset) 986 result = get_gfxclk_voltage_dependency_table(hwmgr, 987 &pp_table_info->vdd_dep_on_sclk, 988 gfxclk_dep_table); 989 990 if (!result && powerplay_table->usPixclkDependencyTableOffset) 991 result = get_pix_clk_voltage_dependency_table(hwmgr, 992 &pp_table_info->vdd_dep_on_pixclk, 993 (const ATOM_Vega10_PIXCLK_Dependency_Table*) 994 pixclk_dep_table); 995 996 if (!result && powerplay_table->usPhyClkDependencyTableOffset) 997 result = get_pix_clk_voltage_dependency_table(hwmgr, 998 &pp_table_info->vdd_dep_on_phyclk, 999 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 1000 phyclk_dep_table); 1001 1002 if (!result && powerplay_table->usDispClkDependencyTableOffset) 1003 result = get_pix_clk_voltage_dependency_table(hwmgr, 1004 &pp_table_info->vdd_dep_on_dispclk, 1005 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 1006 dispclk_dep_table); 1007 1008 if (!result && powerplay_table->usDcefclkDependencyTableOffset) 1009 result = get_dcefclk_voltage_dependency_table(hwmgr, 1010 &pp_table_info->vdd_dep_on_dcefclk, 1011 dcefclk_dep_table); 1012 1013 if (!result && powerplay_table->usMclkDependencyTableOffset) 1014 result = get_mclk_voltage_dependency_table(hwmgr, 1015 &pp_table_info->vdd_dep_on_mclk, 1016 mclk_dep_table); 1017 1018 if (!result && powerplay_table->usPCIETableOffset) 1019 result = get_pcie_table(hwmgr, 1020 &pp_table_info->pcie_table, 1021 pcie_table); 1022 1023 if (!result && powerplay_table->usHardLimitTableOffset) 1024 result = get_hard_limits(hwmgr, 1025 &pp_table_info->max_clock_voltage_on_dc, 1026 hard_limits); 1027 1028 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = 1029 pp_table_info->max_clock_voltage_on_dc.sclk; 1030 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = 1031 pp_table_info->max_clock_voltage_on_dc.mclk; 1032 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = 1033 pp_table_info->max_clock_voltage_on_dc.vddc; 1034 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = 1035 pp_table_info->max_clock_voltage_on_dc.vddci; 1036 1037 if (!result && 1038 pp_table_info->vdd_dep_on_socclk && 1039 pp_table_info->vdd_dep_on_socclk->count) 1040 result = get_valid_clk(hwmgr, 1041 &pp_table_info->valid_socclk_values, 1042 pp_table_info->vdd_dep_on_socclk); 1043 1044 if (!result && 1045 pp_table_info->vdd_dep_on_sclk && 1046 pp_table_info->vdd_dep_on_sclk->count) 1047 result = get_valid_clk(hwmgr, 1048 &pp_table_info->valid_sclk_values, 1049 pp_table_info->vdd_dep_on_sclk); 1050 1051 if (!result && 1052 pp_table_info->vdd_dep_on_dcefclk && 1053 pp_table_info->vdd_dep_on_dcefclk->count) 1054 result = get_valid_clk(hwmgr, 1055 &pp_table_info->valid_dcefclk_values, 1056 pp_table_info->vdd_dep_on_dcefclk); 1057 1058 if (!result && 1059 pp_table_info->vdd_dep_on_mclk && 1060 pp_table_info->vdd_dep_on_mclk->count) 1061 result = get_valid_clk(hwmgr, 1062 &pp_table_info->valid_mclk_values, 1063 pp_table_info->vdd_dep_on_mclk); 1064 1065 return result; 1066} 1067 1068static int get_vddc_lookup_table( 1069 struct pp_hwmgr *hwmgr, 1070 phm_ppt_v1_voltage_lookup_table **lookup_table, 1071 const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables, 1072 uint32_t max_levels) 1073{ 1074 uint32_t table_size, i; 1075 phm_ppt_v1_voltage_lookup_table *table; 1076 1077 PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0), 1078 "Invalid SOC_VDDD Lookup Table!", return 1); 1079 1080 table_size = sizeof(uint32_t) + 1081 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; 1082 1083 table = kzalloc(table_size, GFP_KERNEL); 1084 1085 if (table == NULL) 1086 return -ENOMEM; 1087 1088 table->count = vddc_lookup_pp_tables->ucNumEntries; 1089 1090 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) 1091 table->entries[i].us_vdd = 1092 le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd); 1093 1094 *lookup_table = table; 1095 1096 return 0; 1097} 1098 1099static int init_dpm_2_parameters( 1100 struct pp_hwmgr *hwmgr, 1101 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 1102{ 1103 int result = 0; 1104 struct phm_ppt_v2_information *pp_table_info = 1105 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1106 uint32_t disable_power_control = 0; 1107 1108 pp_table_info->us_ulv_voltage_offset = 1109 le16_to_cpu(powerplay_table->usUlvVoltageOffset); 1110 1111 pp_table_info->us_ulv_smnclk_did = 1112 le16_to_cpu(powerplay_table->usUlvSmnclkDid); 1113 pp_table_info->us_ulv_mp1clk_did = 1114 le16_to_cpu(powerplay_table->usUlvMp1clkDid); 1115 pp_table_info->us_ulv_gfxclk_bypass = 1116 le16_to_cpu(powerplay_table->usUlvGfxclkBypass); 1117 pp_table_info->us_gfxclk_slew_rate = 1118 le16_to_cpu(powerplay_table->usGfxclkSlewRate); 1119 pp_table_info->uc_gfx_dpm_voltage_mode = 1120 le16_to_cpu(powerplay_table->ucGfxVoltageMode); 1121 pp_table_info->uc_soc_dpm_voltage_mode = 1122 le16_to_cpu(powerplay_table->ucSocVoltageMode); 1123 pp_table_info->uc_uclk_dpm_voltage_mode = 1124 le16_to_cpu(powerplay_table->ucUclkVoltageMode); 1125 pp_table_info->uc_uvd_dpm_voltage_mode = 1126 le16_to_cpu(powerplay_table->ucUvdVoltageMode); 1127 pp_table_info->uc_vce_dpm_voltage_mode = 1128 le16_to_cpu(powerplay_table->ucVceVoltageMode); 1129 pp_table_info->uc_mp0_dpm_voltage_mode = 1130 le16_to_cpu(powerplay_table->ucMp0VoltageMode); 1131 pp_table_info->uc_dcef_dpm_voltage_mode = 1132 le16_to_cpu(powerplay_table->ucDcefVoltageMode); 1133 1134 pp_table_info->ppm_parameter_table = NULL; 1135 pp_table_info->vddc_lookup_table = NULL; 1136 pp_table_info->vddmem_lookup_table = NULL; 1137 pp_table_info->vddci_lookup_table = NULL; 1138 1139 /* TDP limits */ 1140 hwmgr->platform_descriptor.TDPODLimit = 1141 le16_to_cpu(powerplay_table->usPowerControlLimit); 1142 hwmgr->platform_descriptor.TDPAdjustment = 0; 1143 hwmgr->platform_descriptor.VidAdjustment = 0; 1144 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 1145 hwmgr->platform_descriptor.VidMinLimit = 0; 1146 hwmgr->platform_descriptor.VidMaxLimit = 1500000; 1147 hwmgr->platform_descriptor.VidStep = 6250; 1148 1149 disable_power_control = 0; 1150 if (!disable_power_control) { 1151 /* enable TDP overdrive (PowerControl) feature as well if supported */ 1152 if (hwmgr->platform_descriptor.TDPODLimit) 1153 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1154 PHM_PlatformCaps_PowerControl); 1155 } 1156 1157 if (powerplay_table->usVddcLookupTableOffset) { 1158 const ATOM_Vega10_Voltage_Lookup_Table *vddc_table = 1159 (ATOM_Vega10_Voltage_Lookup_Table *) 1160 (((unsigned long)powerplay_table) + 1161 le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); 1162 result = get_vddc_lookup_table(hwmgr, 1163 &pp_table_info->vddc_lookup_table, vddc_table, 8); 1164 } 1165 1166 if (powerplay_table->usVddmemLookupTableOffset) { 1167 const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table = 1168 (ATOM_Vega10_Voltage_Lookup_Table *) 1169 (((unsigned long)powerplay_table) + 1170 le16_to_cpu(powerplay_table->usVddmemLookupTableOffset)); 1171 result = get_vddc_lookup_table(hwmgr, 1172 &pp_table_info->vddmem_lookup_table, vdd_mem_table, 4); 1173 } 1174 1175 if (powerplay_table->usVddciLookupTableOffset) { 1176 const ATOM_Vega10_Voltage_Lookup_Table *vddci_table = 1177 (ATOM_Vega10_Voltage_Lookup_Table *) 1178 (((unsigned long)powerplay_table) + 1179 le16_to_cpu(powerplay_table->usVddciLookupTableOffset)); 1180 result = get_vddc_lookup_table(hwmgr, 1181 &pp_table_info->vddci_lookup_table, vddci_table, 4); 1182 } 1183 1184 return result; 1185} 1186 1187int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) 1188{ 1189 int result = 0; 1190 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; 1191 1192 hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL); 1193 1194 PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), 1195 "Failed to allocate hwmgr->pptable!", return -ENOMEM); 1196 1197 powerplay_table = get_powerplay_table(hwmgr); 1198 1199 PP_ASSERT_WITH_CODE((powerplay_table != NULL), 1200 "Missing PowerPlay Table!", return -1); 1201 1202 result = check_powerplay_tables(hwmgr, powerplay_table); 1203 1204 PP_ASSERT_WITH_CODE((result == 0), 1205 "check_powerplay_tables failed", return result); 1206 1207 result = set_platform_caps(hwmgr, 1208 le32_to_cpu(powerplay_table->ulPlatformCaps)); 1209 1210 PP_ASSERT_WITH_CODE((result == 0), 1211 "set_platform_caps failed", return result); 1212 1213 result = init_thermal_controller(hwmgr, powerplay_table); 1214 1215 PP_ASSERT_WITH_CODE((result == 0), 1216 "init_thermal_controller failed", return result); 1217 1218 result = init_over_drive_limits(hwmgr, powerplay_table); 1219 1220 PP_ASSERT_WITH_CODE((result == 0), 1221 "init_over_drive_limits failed", return result); 1222 1223 result = init_powerplay_extended_tables(hwmgr, powerplay_table); 1224 1225 PP_ASSERT_WITH_CODE((result == 0), 1226 "init_powerplay_extended_tables failed", return result); 1227 1228 result = init_dpm_2_parameters(hwmgr, powerplay_table); 1229 1230 PP_ASSERT_WITH_CODE((result == 0), 1231 "init_dpm_2_parameters failed", return result); 1232 1233 return result; 1234} 1235 1236static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) 1237{ 1238 struct phm_ppt_v2_information *pp_table_info = 1239 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1240 1241 kfree(pp_table_info->vdd_dep_on_sclk); 1242 pp_table_info->vdd_dep_on_sclk = NULL; 1243 1244 kfree(pp_table_info->vdd_dep_on_mclk); 1245 pp_table_info->vdd_dep_on_mclk = NULL; 1246 1247 kfree(pp_table_info->valid_mclk_values); 1248 pp_table_info->valid_mclk_values = NULL; 1249 1250 kfree(pp_table_info->valid_sclk_values); 1251 pp_table_info->valid_sclk_values = NULL; 1252 1253 kfree(pp_table_info->vddc_lookup_table); 1254 pp_table_info->vddc_lookup_table = NULL; 1255 1256 kfree(pp_table_info->vddmem_lookup_table); 1257 pp_table_info->vddmem_lookup_table = NULL; 1258 1259 kfree(pp_table_info->vddci_lookup_table); 1260 pp_table_info->vddci_lookup_table = NULL; 1261 1262 kfree(pp_table_info->ppm_parameter_table); 1263 pp_table_info->ppm_parameter_table = NULL; 1264 1265 kfree(pp_table_info->mm_dep_table); 1266 pp_table_info->mm_dep_table = NULL; 1267 1268 kfree(pp_table_info->cac_dtp_table); 1269 pp_table_info->cac_dtp_table = NULL; 1270 1271 kfree(hwmgr->dyn_state.cac_dtp_table); 1272 hwmgr->dyn_state.cac_dtp_table = NULL; 1273 1274 kfree(pp_table_info->tdp_table); 1275 pp_table_info->tdp_table = NULL; 1276 1277 kfree(hwmgr->pptable); 1278 hwmgr->pptable = NULL; 1279 1280 return 0; 1281} 1282 1283const struct pp_table_func vega10_pptable_funcs = { 1284 .pptable_init = vega10_pp_tables_initialize, 1285 .pptable_fini = vega10_pp_tables_uninitialize, 1286}; 1287 1288int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) 1289{ 1290 const ATOM_Vega10_State_Array *state_arrays; 1291 const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); 1292 1293 PP_ASSERT_WITH_CODE((pp_table != NULL), 1294 "Missing PowerPlay Table!", return -1); 1295 PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >= 1296 ATOM_Vega10_TABLE_REVISION_VEGA10), 1297 "Incorrect PowerPlay table revision!", return -1); 1298 1299 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) + 1300 le16_to_cpu(pp_table->usStateArrayOffset)); 1301 1302 return (uint32_t)(state_arrays->ucNumEntries); 1303} 1304 1305static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, 1306 uint16_t classification, uint16_t classification2) 1307{ 1308 uint32_t result = 0; 1309 1310 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) 1311 result |= PP_StateClassificationFlag_Boot; 1312 1313 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) 1314 result |= PP_StateClassificationFlag_Thermal; 1315 1316 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 1317 result |= PP_StateClassificationFlag_LimitedPowerSource; 1318 1319 if (classification & ATOM_PPLIB_CLASSIFICATION_REST) 1320 result |= PP_StateClassificationFlag_Rest; 1321 1322 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) 1323 result |= PP_StateClassificationFlag_Forced; 1324 1325 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) 1326 result |= PP_StateClassificationFlag_ACPI; 1327 1328 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 1329 result |= PP_StateClassificationFlag_LimitedPowerSource_2; 1330 1331 return result; 1332} 1333 1334int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, 1335 uint32_t entry_index, struct pp_power_state *power_state, 1336 int (*call_back_func)(struct pp_hwmgr *, void *, 1337 struct pp_power_state *, void *, uint32_t)) 1338{ 1339 int result = 0; 1340 const ATOM_Vega10_State_Array *state_arrays; 1341 const ATOM_Vega10_State *state_entry; 1342 const ATOM_Vega10_POWERPLAYTABLE *pp_table = 1343 get_powerplay_table(hwmgr); 1344 1345 PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", 1346 return -1;); 1347 power_state->classification.bios_index = entry_index; 1348 1349 if (pp_table->sHeader.format_revision >= 1350 ATOM_Vega10_TABLE_REVISION_VEGA10) { 1351 state_arrays = (ATOM_Vega10_State_Array *) 1352 (((unsigned long)pp_table) + 1353 le16_to_cpu(pp_table->usStateArrayOffset)); 1354 1355 PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, 1356 "Invalid PowerPlay Table State Array Offset.", 1357 return -1); 1358 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, 1359 "Invalid PowerPlay Table State Array.", 1360 return -1); 1361 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), 1362 "Invalid PowerPlay Table State Array Entry.", 1363 return -1); 1364 1365 state_entry = &(state_arrays->states[entry_index]); 1366 1367 result = call_back_func(hwmgr, __UNCONST(state_entry), power_state, 1368 __UNCONST(pp_table), 1369 make_classification_flags(hwmgr, 1370 le16_to_cpu(state_entry->usClassification), 1371 le16_to_cpu(state_entry->usClassification2))); 1372 } 1373 1374 if (!result && (power_state->classification.flags & 1375 PP_StateClassificationFlag_Boot)) 1376 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); 1377 1378 return result; 1379} 1380 1381int vega10_baco_set_cap(struct pp_hwmgr *hwmgr) 1382{ 1383 int result = 0; 1384 1385 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; 1386 1387 powerplay_table = get_powerplay_table(hwmgr); 1388 1389 PP_ASSERT_WITH_CODE((powerplay_table != NULL), 1390 "Missing PowerPlay Table!", return -1); 1391 1392 result = check_powerplay_tables(hwmgr, powerplay_table); 1393 1394 PP_ASSERT_WITH_CODE((result == 0), 1395 "check_powerplay_tables failed", return result); 1396 1397 set_hw_cap( 1398 hwmgr, 1399 0 != (le32_to_cpu(powerplay_table->ulPlatformCaps) & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), 1400 PHM_PlatformCaps_BACO); 1401 return result; 1402} 1403 1404