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