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