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 table_size, 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_size = sizeof(uint32_t) + 885 sizeof(uint32_t) * clk_volt_pp_table->count; 886 887 table = kzalloc(table_size, GFP_KERNEL); 888 889 if (!table) 890 return -ENOMEM; 891 892 table->count = (uint32_t)clk_volt_pp_table->count; 893 894 for (i = 0; i < table->count; i++) 895 table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; 896 897 *clk_table = table; 898 899 return 0; 900 } 901 902 static int init_powerplay_extended_tables( 903 struct pp_hwmgr *hwmgr, 904 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 905 { 906 int result = 0; 907 struct phm_ppt_v2_information *pp_table_info = 908 (struct phm_ppt_v2_information *)(hwmgr->pptable); 909 910 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table = 911 (const ATOM_Vega10_MM_Dependency_Table *) 912 (((unsigned long) powerplay_table) + 913 le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); 914 const Vega10_PPTable_Generic_SubTable_Header *power_tune_table = 915 (const Vega10_PPTable_Generic_SubTable_Header *) 916 (((unsigned long) powerplay_table) + 917 le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); 918 const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = 919 (const ATOM_Vega10_SOCCLK_Dependency_Table *) 920 (((unsigned long) powerplay_table) + 921 le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); 922 const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = 923 (const ATOM_Vega10_GFXCLK_Dependency_Table *) 924 (((unsigned long) powerplay_table) + 925 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); 926 const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table = 927 (const ATOM_Vega10_DCEFCLK_Dependency_Table *) 928 (((unsigned long) powerplay_table) + 929 le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset)); 930 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = 931 (const ATOM_Vega10_MCLK_Dependency_Table *) 932 (((unsigned long) powerplay_table) + 933 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); 934 const ATOM_Vega10_Hard_Limit_Table *hard_limits = 935 (const ATOM_Vega10_Hard_Limit_Table *) 936 (((unsigned long) powerplay_table) + 937 le16_to_cpu(powerplay_table->usHardLimitTableOffset)); 938 const Vega10_PPTable_Generic_SubTable_Header *pcie_table = 939 (const Vega10_PPTable_Generic_SubTable_Header *) 940 (((unsigned long) powerplay_table) + 941 le16_to_cpu(powerplay_table->usPCIETableOffset)); 942 const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table = 943 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 944 (((unsigned long) powerplay_table) + 945 le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset)); 946 const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table = 947 (const ATOM_Vega10_PHYCLK_Dependency_Table *) 948 (((unsigned long) powerplay_table) + 949 le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset)); 950 const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table = 951 (const ATOM_Vega10_DISPCLK_Dependency_Table *) 952 (((unsigned long) powerplay_table) + 953 le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset)); 954 955 pp_table_info->vdd_dep_on_socclk = NULL; 956 pp_table_info->vdd_dep_on_sclk = NULL; 957 pp_table_info->vdd_dep_on_mclk = NULL; 958 pp_table_info->vdd_dep_on_dcefclk = NULL; 959 pp_table_info->mm_dep_table = NULL; 960 pp_table_info->tdp_table = NULL; 961 pp_table_info->vdd_dep_on_pixclk = NULL; 962 pp_table_info->vdd_dep_on_phyclk = NULL; 963 pp_table_info->vdd_dep_on_dispclk = NULL; 964 965 if (powerplay_table->usMMDependencyTableOffset) 966 result = get_mm_clock_voltage_table(hwmgr, 967 &pp_table_info->mm_dep_table, 968 mm_dependency_table); 969 970 if (!result && powerplay_table->usPowerTuneTableOffset) 971 result = get_tdp_table(hwmgr, 972 &pp_table_info->tdp_table, 973 power_tune_table); 974 975 if (!result && powerplay_table->usSocclkDependencyTableOffset) 976 result = get_socclk_voltage_dependency_table(hwmgr, 977 &pp_table_info->vdd_dep_on_socclk, 978 socclk_dep_table); 979 980 if (!result && powerplay_table->usGfxclkDependencyTableOffset) 981 result = get_gfxclk_voltage_dependency_table(hwmgr, 982 &pp_table_info->vdd_dep_on_sclk, 983 gfxclk_dep_table); 984 985 if (!result && powerplay_table->usPixclkDependencyTableOffset) 986 result = get_pix_clk_voltage_dependency_table(hwmgr, 987 &pp_table_info->vdd_dep_on_pixclk, 988 (const ATOM_Vega10_PIXCLK_Dependency_Table*) 989 pixclk_dep_table); 990 991 if (!result && powerplay_table->usPhyClkDependencyTableOffset) 992 result = get_pix_clk_voltage_dependency_table(hwmgr, 993 &pp_table_info->vdd_dep_on_phyclk, 994 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 995 phyclk_dep_table); 996 997 if (!result && powerplay_table->usDispClkDependencyTableOffset) 998 result = get_pix_clk_voltage_dependency_table(hwmgr, 999 &pp_table_info->vdd_dep_on_dispclk, 1000 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 1001 dispclk_dep_table); 1002 1003 if (!result && powerplay_table->usDcefclkDependencyTableOffset) 1004 result = get_dcefclk_voltage_dependency_table(hwmgr, 1005 &pp_table_info->vdd_dep_on_dcefclk, 1006 dcefclk_dep_table); 1007 1008 if (!result && powerplay_table->usMclkDependencyTableOffset) 1009 result = get_mclk_voltage_dependency_table(hwmgr, 1010 &pp_table_info->vdd_dep_on_mclk, 1011 mclk_dep_table); 1012 1013 if (!result && powerplay_table->usPCIETableOffset) 1014 result = get_pcie_table(hwmgr, 1015 &pp_table_info->pcie_table, 1016 pcie_table); 1017 1018 if (!result && powerplay_table->usHardLimitTableOffset) 1019 result = get_hard_limits(hwmgr, 1020 &pp_table_info->max_clock_voltage_on_dc, 1021 hard_limits); 1022 1023 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = 1024 pp_table_info->max_clock_voltage_on_dc.sclk; 1025 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = 1026 pp_table_info->max_clock_voltage_on_dc.mclk; 1027 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = 1028 pp_table_info->max_clock_voltage_on_dc.vddc; 1029 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = 1030 pp_table_info->max_clock_voltage_on_dc.vddci; 1031 1032 if (!result && 1033 pp_table_info->vdd_dep_on_socclk && 1034 pp_table_info->vdd_dep_on_socclk->count) 1035 result = get_valid_clk(hwmgr, 1036 &pp_table_info->valid_socclk_values, 1037 pp_table_info->vdd_dep_on_socclk); 1038 1039 if (!result && 1040 pp_table_info->vdd_dep_on_sclk && 1041 pp_table_info->vdd_dep_on_sclk->count) 1042 result = get_valid_clk(hwmgr, 1043 &pp_table_info->valid_sclk_values, 1044 pp_table_info->vdd_dep_on_sclk); 1045 1046 if (!result && 1047 pp_table_info->vdd_dep_on_dcefclk && 1048 pp_table_info->vdd_dep_on_dcefclk->count) 1049 result = get_valid_clk(hwmgr, 1050 &pp_table_info->valid_dcefclk_values, 1051 pp_table_info->vdd_dep_on_dcefclk); 1052 1053 if (!result && 1054 pp_table_info->vdd_dep_on_mclk && 1055 pp_table_info->vdd_dep_on_mclk->count) 1056 result = get_valid_clk(hwmgr, 1057 &pp_table_info->valid_mclk_values, 1058 pp_table_info->vdd_dep_on_mclk); 1059 1060 return result; 1061 } 1062 1063 static int get_vddc_lookup_table( 1064 struct pp_hwmgr *hwmgr, 1065 phm_ppt_v1_voltage_lookup_table **lookup_table, 1066 const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables, 1067 uint32_t max_levels) 1068 { 1069 uint32_t table_size, i; 1070 phm_ppt_v1_voltage_lookup_table *table; 1071 1072 PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0), 1073 "Invalid SOC_VDDD Lookup Table!", return 1); 1074 1075 table_size = sizeof(uint32_t) + 1076 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; 1077 1078 table = kzalloc(table_size, GFP_KERNEL); 1079 1080 if (table == NULL) 1081 return -ENOMEM; 1082 1083 table->count = vddc_lookup_pp_tables->ucNumEntries; 1084 1085 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) 1086 table->entries[i].us_vdd = 1087 le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd); 1088 1089 *lookup_table = table; 1090 1091 return 0; 1092 } 1093 1094 static int init_dpm_2_parameters( 1095 struct pp_hwmgr *hwmgr, 1096 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 1097 { 1098 int result = 0; 1099 struct phm_ppt_v2_information *pp_table_info = 1100 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1101 uint32_t disable_power_control = 0; 1102 1103 pp_table_info->us_ulv_voltage_offset = 1104 le16_to_cpu(powerplay_table->usUlvVoltageOffset); 1105 1106 pp_table_info->us_ulv_smnclk_did = 1107 le16_to_cpu(powerplay_table->usUlvSmnclkDid); 1108 pp_table_info->us_ulv_mp1clk_did = 1109 le16_to_cpu(powerplay_table->usUlvMp1clkDid); 1110 pp_table_info->us_ulv_gfxclk_bypass = 1111 le16_to_cpu(powerplay_table->usUlvGfxclkBypass); 1112 pp_table_info->us_gfxclk_slew_rate = 1113 le16_to_cpu(powerplay_table->usGfxclkSlewRate); 1114 pp_table_info->uc_gfx_dpm_voltage_mode = 1115 le16_to_cpu(powerplay_table->ucGfxVoltageMode); 1116 pp_table_info->uc_soc_dpm_voltage_mode = 1117 le16_to_cpu(powerplay_table->ucSocVoltageMode); 1118 pp_table_info->uc_uclk_dpm_voltage_mode = 1119 le16_to_cpu(powerplay_table->ucUclkVoltageMode); 1120 pp_table_info->uc_uvd_dpm_voltage_mode = 1121 le16_to_cpu(powerplay_table->ucUvdVoltageMode); 1122 pp_table_info->uc_vce_dpm_voltage_mode = 1123 le16_to_cpu(powerplay_table->ucVceVoltageMode); 1124 pp_table_info->uc_mp0_dpm_voltage_mode = 1125 le16_to_cpu(powerplay_table->ucMp0VoltageMode); 1126 pp_table_info->uc_dcef_dpm_voltage_mode = 1127 le16_to_cpu(powerplay_table->ucDcefVoltageMode); 1128 1129 pp_table_info->ppm_parameter_table = NULL; 1130 pp_table_info->vddc_lookup_table = NULL; 1131 pp_table_info->vddmem_lookup_table = NULL; 1132 pp_table_info->vddci_lookup_table = NULL; 1133 1134 /* TDP limits */ 1135 hwmgr->platform_descriptor.TDPODLimit = 1136 le16_to_cpu(powerplay_table->usPowerControlLimit); 1137 hwmgr->platform_descriptor.TDPAdjustment = 0; 1138 hwmgr->platform_descriptor.VidAdjustment = 0; 1139 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 1140 hwmgr->platform_descriptor.VidMinLimit = 0; 1141 hwmgr->platform_descriptor.VidMaxLimit = 1500000; 1142 hwmgr->platform_descriptor.VidStep = 6250; 1143 1144 disable_power_control = 0; 1145 if (!disable_power_control) { 1146 /* enable TDP overdrive (PowerControl) feature as well if supported */ 1147 if (hwmgr->platform_descriptor.TDPODLimit) 1148 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1149 PHM_PlatformCaps_PowerControl); 1150 } 1151 1152 if (powerplay_table->usVddcLookupTableOffset) { 1153 const ATOM_Vega10_Voltage_Lookup_Table *vddc_table = 1154 (ATOM_Vega10_Voltage_Lookup_Table *) 1155 (((unsigned long)powerplay_table) + 1156 le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); 1157 result = get_vddc_lookup_table(hwmgr, 1158 &pp_table_info->vddc_lookup_table, vddc_table, 8); 1159 } 1160 1161 if (powerplay_table->usVddmemLookupTableOffset) { 1162 const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table = 1163 (ATOM_Vega10_Voltage_Lookup_Table *) 1164 (((unsigned long)powerplay_table) + 1165 le16_to_cpu(powerplay_table->usVddmemLookupTableOffset)); 1166 result = get_vddc_lookup_table(hwmgr, 1167 &pp_table_info->vddmem_lookup_table, vdd_mem_table, 4); 1168 } 1169 1170 if (powerplay_table->usVddciLookupTableOffset) { 1171 const ATOM_Vega10_Voltage_Lookup_Table *vddci_table = 1172 (ATOM_Vega10_Voltage_Lookup_Table *) 1173 (((unsigned long)powerplay_table) + 1174 le16_to_cpu(powerplay_table->usVddciLookupTableOffset)); 1175 result = get_vddc_lookup_table(hwmgr, 1176 &pp_table_info->vddci_lookup_table, vddci_table, 4); 1177 } 1178 1179 return result; 1180 } 1181 1182 int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) 1183 { 1184 int result = 0; 1185 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; 1186 1187 hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL); 1188 1189 PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), 1190 "Failed to allocate hwmgr->pptable!", return -ENOMEM); 1191 1192 powerplay_table = get_powerplay_table(hwmgr); 1193 1194 PP_ASSERT_WITH_CODE((powerplay_table != NULL), 1195 "Missing PowerPlay Table!", return -1); 1196 1197 result = check_powerplay_tables(hwmgr, powerplay_table); 1198 1199 PP_ASSERT_WITH_CODE((result == 0), 1200 "check_powerplay_tables failed", return result); 1201 1202 result = set_platform_caps(hwmgr, 1203 le32_to_cpu(powerplay_table->ulPlatformCaps)); 1204 1205 PP_ASSERT_WITH_CODE((result == 0), 1206 "set_platform_caps failed", return result); 1207 1208 result = init_thermal_controller(hwmgr, powerplay_table); 1209 1210 PP_ASSERT_WITH_CODE((result == 0), 1211 "init_thermal_controller failed", return result); 1212 1213 result = init_over_drive_limits(hwmgr, powerplay_table); 1214 1215 PP_ASSERT_WITH_CODE((result == 0), 1216 "init_over_drive_limits failed", return result); 1217 1218 result = init_powerplay_extended_tables(hwmgr, powerplay_table); 1219 1220 PP_ASSERT_WITH_CODE((result == 0), 1221 "init_powerplay_extended_tables failed", return result); 1222 1223 result = init_dpm_2_parameters(hwmgr, powerplay_table); 1224 1225 PP_ASSERT_WITH_CODE((result == 0), 1226 "init_dpm_2_parameters failed", return result); 1227 1228 return result; 1229 } 1230 1231 static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) 1232 { 1233 struct phm_ppt_v2_information *pp_table_info = 1234 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1235 1236 kfree(pp_table_info->vdd_dep_on_sclk); 1237 pp_table_info->vdd_dep_on_sclk = NULL; 1238 1239 kfree(pp_table_info->vdd_dep_on_mclk); 1240 pp_table_info->vdd_dep_on_mclk = NULL; 1241 1242 kfree(pp_table_info->valid_mclk_values); 1243 pp_table_info->valid_mclk_values = NULL; 1244 1245 kfree(pp_table_info->valid_sclk_values); 1246 pp_table_info->valid_sclk_values = NULL; 1247 1248 kfree(pp_table_info->vddc_lookup_table); 1249 pp_table_info->vddc_lookup_table = NULL; 1250 1251 kfree(pp_table_info->vddmem_lookup_table); 1252 pp_table_info->vddmem_lookup_table = NULL; 1253 1254 kfree(pp_table_info->vddci_lookup_table); 1255 pp_table_info->vddci_lookup_table = NULL; 1256 1257 kfree(pp_table_info->ppm_parameter_table); 1258 pp_table_info->ppm_parameter_table = NULL; 1259 1260 kfree(pp_table_info->mm_dep_table); 1261 pp_table_info->mm_dep_table = NULL; 1262 1263 kfree(pp_table_info->cac_dtp_table); 1264 pp_table_info->cac_dtp_table = NULL; 1265 1266 kfree(hwmgr->dyn_state.cac_dtp_table); 1267 hwmgr->dyn_state.cac_dtp_table = NULL; 1268 1269 kfree(pp_table_info->tdp_table); 1270 pp_table_info->tdp_table = NULL; 1271 1272 kfree(hwmgr->pptable); 1273 hwmgr->pptable = NULL; 1274 1275 return 0; 1276 } 1277 1278 const struct pp_table_func vega10_pptable_funcs = { 1279 .pptable_init = vega10_pp_tables_initialize, 1280 .pptable_fini = vega10_pp_tables_uninitialize, 1281 }; 1282 1283 int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) 1284 { 1285 const ATOM_Vega10_State_Array *state_arrays; 1286 const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); 1287 1288 PP_ASSERT_WITH_CODE((pp_table != NULL), 1289 "Missing PowerPlay Table!", return -1); 1290 PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >= 1291 ATOM_Vega10_TABLE_REVISION_VEGA10), 1292 "Incorrect PowerPlay table revision!", return -1); 1293 1294 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) + 1295 le16_to_cpu(pp_table->usStateArrayOffset)); 1296 1297 return (uint32_t)(state_arrays->ucNumEntries); 1298 } 1299 1300 static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, 1301 uint16_t classification, uint16_t classification2) 1302 { 1303 uint32_t result = 0; 1304 1305 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) 1306 result |= PP_StateClassificationFlag_Boot; 1307 1308 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) 1309 result |= PP_StateClassificationFlag_Thermal; 1310 1311 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 1312 result |= PP_StateClassificationFlag_LimitedPowerSource; 1313 1314 if (classification & ATOM_PPLIB_CLASSIFICATION_REST) 1315 result |= PP_StateClassificationFlag_Rest; 1316 1317 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) 1318 result |= PP_StateClassificationFlag_Forced; 1319 1320 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) 1321 result |= PP_StateClassificationFlag_ACPI; 1322 1323 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 1324 result |= PP_StateClassificationFlag_LimitedPowerSource_2; 1325 1326 return result; 1327 } 1328 1329 int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, 1330 uint32_t entry_index, struct pp_power_state *power_state, 1331 int (*call_back_func)(struct pp_hwmgr *, void *, 1332 struct pp_power_state *, void *, uint32_t)) 1333 { 1334 int result = 0; 1335 const ATOM_Vega10_State_Array *state_arrays; 1336 const ATOM_Vega10_State *state_entry; 1337 const ATOM_Vega10_POWERPLAYTABLE *pp_table = 1338 get_powerplay_table(hwmgr); 1339 1340 PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", 1341 return -1;); 1342 power_state->classification.bios_index = entry_index; 1343 1344 if (pp_table->sHeader.format_revision >= 1345 ATOM_Vega10_TABLE_REVISION_VEGA10) { 1346 state_arrays = (ATOM_Vega10_State_Array *) 1347 (((unsigned long)pp_table) + 1348 le16_to_cpu(pp_table->usStateArrayOffset)); 1349 1350 PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, 1351 "Invalid PowerPlay Table State Array Offset.", 1352 return -1); 1353 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, 1354 "Invalid PowerPlay Table State Array.", 1355 return -1); 1356 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), 1357 "Invalid PowerPlay Table State Array Entry.", 1358 return -1); 1359 1360 state_entry = &(state_arrays->states[entry_index]); 1361 1362 result = call_back_func(hwmgr, (void *)state_entry, power_state, 1363 (void *)pp_table, 1364 make_classification_flags(hwmgr, 1365 le16_to_cpu(state_entry->usClassification), 1366 le16_to_cpu(state_entry->usClassification2))); 1367 } 1368 1369 if (!result && (power_state->classification.flags & 1370 PP_StateClassificationFlag_Boot)) 1371 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); 1372 1373 return result; 1374 } 1375 1376 int vega10_baco_set_cap(struct pp_hwmgr *hwmgr) 1377 { 1378 int result = 0; 1379 1380 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; 1381 1382 powerplay_table = get_powerplay_table(hwmgr); 1383 1384 PP_ASSERT_WITH_CODE((powerplay_table != NULL), 1385 "Missing PowerPlay Table!", return -1); 1386 1387 result = check_powerplay_tables(hwmgr, powerplay_table); 1388 1389 PP_ASSERT_WITH_CODE((result == 0), 1390 "check_powerplay_tables failed", return result); 1391 1392 set_hw_cap( 1393 hwmgr, 1394 0 != (le32_to_cpu(powerplay_table->ulPlatformCaps) & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), 1395 PHM_PlatformCaps_BACO); 1396 return result; 1397 } 1398 1399