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 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 clk_table = kzalloc(struct_size(clk_table, entries, clk_dep_table->ucNumEntries), 581 GFP_KERNEL); 582 if (!clk_table) 583 return -ENOMEM; 584 585 clk_table->count = (uint32_t)clk_dep_table->ucNumEntries; 586 587 for (i = 0; i < clk_dep_table->ucNumEntries; i++) { 588 clk_table->entries[i].vddInd = 589 clk_dep_table->entries[i].ucVddInd; 590 clk_table->entries[i].clk = 591 le32_to_cpu(clk_dep_table->entries[i].ulClk); 592 } 593 594 *pp_vega10_clk_dep_table = clk_table; 595 596 return 0; 597 } 598 599 static int get_mclk_voltage_dependency_table( 600 struct pp_hwmgr *hwmgr, 601 phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table, 602 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table) 603 { 604 uint32_t i; 605 phm_ppt_v1_clock_voltage_dependency_table *mclk_table; 606 607 PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries, 608 "Invalid PowerPlay Table!", return -1); 609 610 mclk_table = kzalloc(struct_size(mclk_table, entries, mclk_dep_table->ucNumEntries), 611 GFP_KERNEL); 612 if (!mclk_table) 613 return -ENOMEM; 614 615 mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; 616 617 for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { 618 mclk_table->entries[i].vddInd = 619 mclk_dep_table->entries[i].ucVddInd; 620 mclk_table->entries[i].vddciInd = 621 mclk_dep_table->entries[i].ucVddciInd; 622 mclk_table->entries[i].mvddInd = 623 mclk_dep_table->entries[i].ucVddMemInd; 624 mclk_table->entries[i].clk = 625 le32_to_cpu(mclk_dep_table->entries[i].ulMemClk); 626 } 627 628 *pp_vega10_mclk_dep_table = mclk_table; 629 630 return 0; 631 } 632 633 static int get_gfxclk_voltage_dependency_table( 634 struct pp_hwmgr *hwmgr, 635 struct phm_ppt_v1_clock_voltage_dependency_table 636 **pp_vega10_clk_dep_table, 637 const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table) 638 { 639 uint32_t i; 640 struct phm_ppt_v1_clock_voltage_dependency_table 641 *clk_table; 642 ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; 643 644 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), 645 "Invalid PowerPlay Table!", return -1); 646 647 clk_table = kzalloc(struct_size(clk_table, entries, clk_dep_table->ucNumEntries), 648 GFP_KERNEL); 649 if (!clk_table) 650 return -ENOMEM; 651 652 clk_table->count = clk_dep_table->ucNumEntries; 653 654 if (clk_dep_table->ucRevId == 0) { 655 for (i = 0; i < clk_table->count; i++) { 656 clk_table->entries[i].vddInd = 657 clk_dep_table->entries[i].ucVddInd; 658 clk_table->entries[i].clk = 659 le32_to_cpu(clk_dep_table->entries[i].ulClk); 660 clk_table->entries[i].cks_enable = 661 (((le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x8000) 662 >> 15) == 0) ? 1 : 0; 663 clk_table->entries[i].cks_voffset = 664 le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x7F; 665 clk_table->entries[i].sclk_offset = 666 le16_to_cpu(clk_dep_table->entries[i].usAVFSOffset); 667 } 668 } else if (clk_dep_table->ucRevId == 1) { 669 patom_record_v2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)clk_dep_table->entries; 670 for (i = 0; i < clk_table->count; i++) { 671 clk_table->entries[i].vddInd = 672 patom_record_v2->ucVddInd; 673 clk_table->entries[i].clk = 674 le32_to_cpu(patom_record_v2->ulClk); 675 clk_table->entries[i].cks_enable = 676 (((le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x8000) 677 >> 15) == 0) ? 1 : 0; 678 clk_table->entries[i].cks_voffset = 679 le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x7F; 680 clk_table->entries[i].sclk_offset = 681 le16_to_cpu(patom_record_v2->usAVFSOffset); 682 patom_record_v2++; 683 } 684 } else { 685 kfree(clk_table); 686 PP_ASSERT_WITH_CODE(false, 687 "Unsupported GFXClockDependencyTable Revision!", 688 return -EINVAL); 689 } 690 691 *pp_vega10_clk_dep_table = clk_table; 692 693 return 0; 694 } 695 696 static int get_pix_clk_voltage_dependency_table( 697 struct pp_hwmgr *hwmgr, 698 struct phm_ppt_v1_clock_voltage_dependency_table 699 **pp_vega10_clk_dep_table, 700 const ATOM_Vega10_PIXCLK_Dependency_Table *clk_dep_table) 701 { 702 uint32_t i; 703 struct phm_ppt_v1_clock_voltage_dependency_table 704 *clk_table; 705 706 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), 707 "Invalid PowerPlay Table!", return -1); 708 709 clk_table = kzalloc(struct_size(clk_table, entries, clk_dep_table->ucNumEntries), 710 GFP_KERNEL); 711 if (!clk_table) 712 return -ENOMEM; 713 714 clk_table->count = clk_dep_table->ucNumEntries; 715 716 for (i = 0; i < clk_table->count; i++) { 717 clk_table->entries[i].vddInd = 718 clk_dep_table->entries[i].ucVddInd; 719 clk_table->entries[i].clk = 720 le32_to_cpu(clk_dep_table->entries[i].ulClk); 721 } 722 723 *pp_vega10_clk_dep_table = clk_table; 724 725 return 0; 726 } 727 728 static int get_dcefclk_voltage_dependency_table( 729 struct pp_hwmgr *hwmgr, 730 struct phm_ppt_v1_clock_voltage_dependency_table 731 **pp_vega10_clk_dep_table, 732 const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table) 733 { 734 uint32_t i; 735 uint8_t num_entries; 736 struct phm_ppt_v1_clock_voltage_dependency_table 737 *clk_table; 738 uint32_t dev_id; 739 uint32_t rev_id; 740 struct amdgpu_device *adev = hwmgr->adev; 741 742 PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), 743 "Invalid PowerPlay Table!", return -1); 744 745 /* 746 * workaround needed to add another DPM level for pioneer cards 747 * as VBIOS is locked down. 748 * This DPM level was added to support 3DPM monitors @ 4K120Hz 749 * 750 */ 751 dev_id = adev->pdev->device; 752 rev_id = adev->pdev->revision; 753 754 if (dev_id == 0x6863 && rev_id == 0 && 755 clk_dep_table->entries[clk_dep_table->ucNumEntries - 1].ulClk < 90000) 756 num_entries = clk_dep_table->ucNumEntries + 1 > NUM_DSPCLK_LEVELS ? 757 NUM_DSPCLK_LEVELS : clk_dep_table->ucNumEntries + 1; 758 else 759 num_entries = clk_dep_table->ucNumEntries; 760 761 762 clk_table = kzalloc(struct_size(clk_table, entries, num_entries), 763 GFP_KERNEL); 764 if (!clk_table) 765 return -ENOMEM; 766 767 clk_table->count = (uint32_t)num_entries; 768 769 for (i = 0; i < clk_dep_table->ucNumEntries; i++) { 770 clk_table->entries[i].vddInd = 771 clk_dep_table->entries[i].ucVddInd; 772 clk_table->entries[i].clk = 773 le32_to_cpu(clk_dep_table->entries[i].ulClk); 774 } 775 776 if (i < num_entries) { 777 clk_table->entries[i].vddInd = clk_dep_table->entries[i-1].ucVddInd; 778 clk_table->entries[i].clk = 90000; 779 } 780 781 *pp_vega10_clk_dep_table = clk_table; 782 783 return 0; 784 } 785 786 static int get_pcie_table(struct pp_hwmgr *hwmgr, 787 struct phm_ppt_v1_pcie_table **vega10_pcie_table, 788 const Vega10_PPTable_Generic_SubTable_Header *table) 789 { 790 uint32_t table_size, i, pcie_count; 791 struct phm_ppt_v1_pcie_table *pcie_table; 792 struct phm_ppt_v2_information *table_info = 793 (struct phm_ppt_v2_information *)(hwmgr->pptable); 794 const ATOM_Vega10_PCIE_Table *atom_pcie_table = 795 (ATOM_Vega10_PCIE_Table *)table; 796 797 PP_ASSERT_WITH_CODE(atom_pcie_table->ucNumEntries, 798 "Invalid PowerPlay Table!", 799 return 0); 800 801 table_size = sizeof(uint32_t) + 802 sizeof(struct phm_ppt_v1_pcie_record) * 803 atom_pcie_table->ucNumEntries; 804 805 pcie_table = kzalloc(table_size, GFP_KERNEL); 806 807 if (!pcie_table) 808 return -ENOMEM; 809 810 pcie_count = table_info->vdd_dep_on_sclk->count; 811 if (atom_pcie_table->ucNumEntries <= pcie_count) 812 pcie_count = atom_pcie_table->ucNumEntries; 813 else 814 pr_info("Number of Pcie Entries exceed the number of" 815 " GFXCLK Dpm Levels!" 816 " Disregarding the excess entries...\n"); 817 818 pcie_table->count = pcie_count; 819 820 for (i = 0; i < pcie_count; i++) { 821 pcie_table->entries[i].gen_speed = 822 atom_pcie_table->entries[i].ucPCIEGenSpeed; 823 pcie_table->entries[i].lane_width = 824 atom_pcie_table->entries[i].ucPCIELaneWidth; 825 pcie_table->entries[i].pcie_sclk = 826 atom_pcie_table->entries[i].ulLCLK; 827 } 828 829 *vega10_pcie_table = pcie_table; 830 831 return 0; 832 } 833 834 static int get_hard_limits( 835 struct pp_hwmgr *hwmgr, 836 struct phm_clock_and_voltage_limits *limits, 837 const ATOM_Vega10_Hard_Limit_Table *limit_table) 838 { 839 PP_ASSERT_WITH_CODE(limit_table->ucNumEntries, 840 "Invalid PowerPlay Table!", return -1); 841 842 /* currently we always take entries[0] parameters */ 843 limits->sclk = le32_to_cpu(limit_table->entries[0].ulSOCCLKLimit); 844 limits->mclk = le32_to_cpu(limit_table->entries[0].ulMCLKLimit); 845 limits->gfxclk = le32_to_cpu(limit_table->entries[0].ulGFXCLKLimit); 846 limits->vddc = le16_to_cpu(limit_table->entries[0].usVddcLimit); 847 limits->vddci = le16_to_cpu(limit_table->entries[0].usVddciLimit); 848 limits->vddmem = le16_to_cpu(limit_table->entries[0].usVddMemLimit); 849 850 return 0; 851 } 852 853 static int get_valid_clk( 854 struct pp_hwmgr *hwmgr, 855 struct phm_clock_array **clk_table, 856 const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table) 857 { 858 uint32_t i; 859 struct phm_clock_array *table; 860 861 PP_ASSERT_WITH_CODE(clk_volt_pp_table->count, 862 "Invalid PowerPlay Table!", return -1); 863 864 table = kzalloc(struct_size(table, values, clk_volt_pp_table->count), 865 GFP_KERNEL); 866 if (!table) 867 return -ENOMEM; 868 869 table->count = (uint32_t)clk_volt_pp_table->count; 870 871 for (i = 0; i < table->count; i++) 872 table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; 873 874 *clk_table = table; 875 876 return 0; 877 } 878 879 static int init_powerplay_extended_tables( 880 struct pp_hwmgr *hwmgr, 881 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 882 { 883 int result = 0; 884 struct phm_ppt_v2_information *pp_table_info = 885 (struct phm_ppt_v2_information *)(hwmgr->pptable); 886 887 const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table = 888 (const ATOM_Vega10_MM_Dependency_Table *) 889 (((unsigned long) powerplay_table) + 890 le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); 891 const Vega10_PPTable_Generic_SubTable_Header *power_tune_table = 892 (const Vega10_PPTable_Generic_SubTable_Header *) 893 (((unsigned long) powerplay_table) + 894 le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); 895 const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = 896 (const ATOM_Vega10_SOCCLK_Dependency_Table *) 897 (((unsigned long) powerplay_table) + 898 le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); 899 const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = 900 (const ATOM_Vega10_GFXCLK_Dependency_Table *) 901 (((unsigned long) powerplay_table) + 902 le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); 903 const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table = 904 (const ATOM_Vega10_DCEFCLK_Dependency_Table *) 905 (((unsigned long) powerplay_table) + 906 le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset)); 907 const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = 908 (const ATOM_Vega10_MCLK_Dependency_Table *) 909 (((unsigned long) powerplay_table) + 910 le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); 911 const ATOM_Vega10_Hard_Limit_Table *hard_limits = 912 (const ATOM_Vega10_Hard_Limit_Table *) 913 (((unsigned long) powerplay_table) + 914 le16_to_cpu(powerplay_table->usHardLimitTableOffset)); 915 const Vega10_PPTable_Generic_SubTable_Header *pcie_table = 916 (const Vega10_PPTable_Generic_SubTable_Header *) 917 (((unsigned long) powerplay_table) + 918 le16_to_cpu(powerplay_table->usPCIETableOffset)); 919 const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table = 920 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 921 (((unsigned long) powerplay_table) + 922 le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset)); 923 const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table = 924 (const ATOM_Vega10_PHYCLK_Dependency_Table *) 925 (((unsigned long) powerplay_table) + 926 le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset)); 927 const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table = 928 (const ATOM_Vega10_DISPCLK_Dependency_Table *) 929 (((unsigned long) powerplay_table) + 930 le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset)); 931 932 pp_table_info->vdd_dep_on_socclk = NULL; 933 pp_table_info->vdd_dep_on_sclk = NULL; 934 pp_table_info->vdd_dep_on_mclk = NULL; 935 pp_table_info->vdd_dep_on_dcefclk = NULL; 936 pp_table_info->mm_dep_table = NULL; 937 pp_table_info->tdp_table = NULL; 938 pp_table_info->vdd_dep_on_pixclk = NULL; 939 pp_table_info->vdd_dep_on_phyclk = NULL; 940 pp_table_info->vdd_dep_on_dispclk = NULL; 941 942 if (powerplay_table->usMMDependencyTableOffset) 943 result = get_mm_clock_voltage_table(hwmgr, 944 &pp_table_info->mm_dep_table, 945 mm_dependency_table); 946 947 if (!result && powerplay_table->usPowerTuneTableOffset) 948 result = get_tdp_table(hwmgr, 949 &pp_table_info->tdp_table, 950 power_tune_table); 951 952 if (!result && powerplay_table->usSocclkDependencyTableOffset) 953 result = get_socclk_voltage_dependency_table(hwmgr, 954 &pp_table_info->vdd_dep_on_socclk, 955 socclk_dep_table); 956 957 if (!result && powerplay_table->usGfxclkDependencyTableOffset) 958 result = get_gfxclk_voltage_dependency_table(hwmgr, 959 &pp_table_info->vdd_dep_on_sclk, 960 gfxclk_dep_table); 961 962 if (!result && powerplay_table->usPixclkDependencyTableOffset) 963 result = get_pix_clk_voltage_dependency_table(hwmgr, 964 &pp_table_info->vdd_dep_on_pixclk, 965 (const ATOM_Vega10_PIXCLK_Dependency_Table*) 966 pixclk_dep_table); 967 968 if (!result && powerplay_table->usPhyClkDependencyTableOffset) 969 result = get_pix_clk_voltage_dependency_table(hwmgr, 970 &pp_table_info->vdd_dep_on_phyclk, 971 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 972 phyclk_dep_table); 973 974 if (!result && powerplay_table->usDispClkDependencyTableOffset) 975 result = get_pix_clk_voltage_dependency_table(hwmgr, 976 &pp_table_info->vdd_dep_on_dispclk, 977 (const ATOM_Vega10_PIXCLK_Dependency_Table *) 978 dispclk_dep_table); 979 980 if (!result && powerplay_table->usDcefclkDependencyTableOffset) 981 result = get_dcefclk_voltage_dependency_table(hwmgr, 982 &pp_table_info->vdd_dep_on_dcefclk, 983 dcefclk_dep_table); 984 985 if (!result && powerplay_table->usMclkDependencyTableOffset) 986 result = get_mclk_voltage_dependency_table(hwmgr, 987 &pp_table_info->vdd_dep_on_mclk, 988 mclk_dep_table); 989 990 if (!result && powerplay_table->usPCIETableOffset) 991 result = get_pcie_table(hwmgr, 992 &pp_table_info->pcie_table, 993 pcie_table); 994 995 if (!result && powerplay_table->usHardLimitTableOffset) 996 result = get_hard_limits(hwmgr, 997 &pp_table_info->max_clock_voltage_on_dc, 998 hard_limits); 999 1000 hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = 1001 pp_table_info->max_clock_voltage_on_dc.sclk; 1002 hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = 1003 pp_table_info->max_clock_voltage_on_dc.mclk; 1004 hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = 1005 pp_table_info->max_clock_voltage_on_dc.vddc; 1006 hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = 1007 pp_table_info->max_clock_voltage_on_dc.vddci; 1008 1009 if (!result && 1010 pp_table_info->vdd_dep_on_socclk && 1011 pp_table_info->vdd_dep_on_socclk->count) 1012 result = get_valid_clk(hwmgr, 1013 &pp_table_info->valid_socclk_values, 1014 pp_table_info->vdd_dep_on_socclk); 1015 1016 if (!result && 1017 pp_table_info->vdd_dep_on_sclk && 1018 pp_table_info->vdd_dep_on_sclk->count) 1019 result = get_valid_clk(hwmgr, 1020 &pp_table_info->valid_sclk_values, 1021 pp_table_info->vdd_dep_on_sclk); 1022 1023 if (!result && 1024 pp_table_info->vdd_dep_on_dcefclk && 1025 pp_table_info->vdd_dep_on_dcefclk->count) 1026 result = get_valid_clk(hwmgr, 1027 &pp_table_info->valid_dcefclk_values, 1028 pp_table_info->vdd_dep_on_dcefclk); 1029 1030 if (!result && 1031 pp_table_info->vdd_dep_on_mclk && 1032 pp_table_info->vdd_dep_on_mclk->count) 1033 result = get_valid_clk(hwmgr, 1034 &pp_table_info->valid_mclk_values, 1035 pp_table_info->vdd_dep_on_mclk); 1036 1037 return result; 1038 } 1039 1040 static int get_vddc_lookup_table( 1041 struct pp_hwmgr *hwmgr, 1042 phm_ppt_v1_voltage_lookup_table **lookup_table, 1043 const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables, 1044 uint32_t max_levels) 1045 { 1046 uint32_t table_size, i; 1047 phm_ppt_v1_voltage_lookup_table *table; 1048 1049 PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0), 1050 "Invalid SOC_VDDD Lookup Table!", return 1); 1051 1052 table_size = sizeof(uint32_t) + 1053 sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; 1054 1055 table = kzalloc(table_size, GFP_KERNEL); 1056 1057 if (table == NULL) 1058 return -ENOMEM; 1059 1060 table->count = vddc_lookup_pp_tables->ucNumEntries; 1061 1062 for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) 1063 table->entries[i].us_vdd = 1064 le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd); 1065 1066 *lookup_table = table; 1067 1068 return 0; 1069 } 1070 1071 static int init_dpm_2_parameters( 1072 struct pp_hwmgr *hwmgr, 1073 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) 1074 { 1075 int result = 0; 1076 struct phm_ppt_v2_information *pp_table_info = 1077 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1078 uint32_t disable_power_control = 0; 1079 1080 pp_table_info->us_ulv_voltage_offset = 1081 le16_to_cpu(powerplay_table->usUlvVoltageOffset); 1082 1083 pp_table_info->us_ulv_smnclk_did = 1084 le16_to_cpu(powerplay_table->usUlvSmnclkDid); 1085 pp_table_info->us_ulv_mp1clk_did = 1086 le16_to_cpu(powerplay_table->usUlvMp1clkDid); 1087 pp_table_info->us_ulv_gfxclk_bypass = 1088 le16_to_cpu(powerplay_table->usUlvGfxclkBypass); 1089 pp_table_info->us_gfxclk_slew_rate = 1090 le16_to_cpu(powerplay_table->usGfxclkSlewRate); 1091 pp_table_info->uc_gfx_dpm_voltage_mode = 1092 le16_to_cpu(powerplay_table->ucGfxVoltageMode); 1093 pp_table_info->uc_soc_dpm_voltage_mode = 1094 le16_to_cpu(powerplay_table->ucSocVoltageMode); 1095 pp_table_info->uc_uclk_dpm_voltage_mode = 1096 le16_to_cpu(powerplay_table->ucUclkVoltageMode); 1097 pp_table_info->uc_uvd_dpm_voltage_mode = 1098 le16_to_cpu(powerplay_table->ucUvdVoltageMode); 1099 pp_table_info->uc_vce_dpm_voltage_mode = 1100 le16_to_cpu(powerplay_table->ucVceVoltageMode); 1101 pp_table_info->uc_mp0_dpm_voltage_mode = 1102 le16_to_cpu(powerplay_table->ucMp0VoltageMode); 1103 pp_table_info->uc_dcef_dpm_voltage_mode = 1104 le16_to_cpu(powerplay_table->ucDcefVoltageMode); 1105 1106 pp_table_info->ppm_parameter_table = NULL; 1107 pp_table_info->vddc_lookup_table = NULL; 1108 pp_table_info->vddmem_lookup_table = NULL; 1109 pp_table_info->vddci_lookup_table = NULL; 1110 1111 /* TDP limits */ 1112 hwmgr->platform_descriptor.TDPODLimit = 1113 le16_to_cpu(powerplay_table->usPowerControlLimit); 1114 hwmgr->platform_descriptor.TDPAdjustment = 0; 1115 hwmgr->platform_descriptor.VidAdjustment = 0; 1116 hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; 1117 hwmgr->platform_descriptor.VidMinLimit = 0; 1118 hwmgr->platform_descriptor.VidMaxLimit = 1500000; 1119 hwmgr->platform_descriptor.VidStep = 6250; 1120 1121 disable_power_control = 0; 1122 if (!disable_power_control) { 1123 /* enable TDP overdrive (PowerControl) feature as well if supported */ 1124 if (hwmgr->platform_descriptor.TDPODLimit) 1125 phm_cap_set(hwmgr->platform_descriptor.platformCaps, 1126 PHM_PlatformCaps_PowerControl); 1127 } 1128 1129 if (powerplay_table->usVddcLookupTableOffset) { 1130 const ATOM_Vega10_Voltage_Lookup_Table *vddc_table = 1131 (ATOM_Vega10_Voltage_Lookup_Table *) 1132 (((unsigned long)powerplay_table) + 1133 le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); 1134 result = get_vddc_lookup_table(hwmgr, 1135 &pp_table_info->vddc_lookup_table, vddc_table, 8); 1136 } 1137 1138 if (powerplay_table->usVddmemLookupTableOffset) { 1139 const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table = 1140 (ATOM_Vega10_Voltage_Lookup_Table *) 1141 (((unsigned long)powerplay_table) + 1142 le16_to_cpu(powerplay_table->usVddmemLookupTableOffset)); 1143 result = get_vddc_lookup_table(hwmgr, 1144 &pp_table_info->vddmem_lookup_table, vdd_mem_table, 4); 1145 } 1146 1147 if (powerplay_table->usVddciLookupTableOffset) { 1148 const ATOM_Vega10_Voltage_Lookup_Table *vddci_table = 1149 (ATOM_Vega10_Voltage_Lookup_Table *) 1150 (((unsigned long)powerplay_table) + 1151 le16_to_cpu(powerplay_table->usVddciLookupTableOffset)); 1152 result = get_vddc_lookup_table(hwmgr, 1153 &pp_table_info->vddci_lookup_table, vddci_table, 4); 1154 } 1155 1156 return result; 1157 } 1158 1159 int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) 1160 { 1161 int result = 0; 1162 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; 1163 1164 hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL); 1165 1166 PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), 1167 "Failed to allocate hwmgr->pptable!", return -ENOMEM); 1168 1169 powerplay_table = get_powerplay_table(hwmgr); 1170 1171 PP_ASSERT_WITH_CODE((powerplay_table != NULL), 1172 "Missing PowerPlay Table!", return -1); 1173 1174 result = check_powerplay_tables(hwmgr, powerplay_table); 1175 1176 PP_ASSERT_WITH_CODE((result == 0), 1177 "check_powerplay_tables failed", return result); 1178 1179 result = set_platform_caps(hwmgr, 1180 le32_to_cpu(powerplay_table->ulPlatformCaps)); 1181 1182 PP_ASSERT_WITH_CODE((result == 0), 1183 "set_platform_caps failed", return result); 1184 1185 result = init_thermal_controller(hwmgr, powerplay_table); 1186 1187 PP_ASSERT_WITH_CODE((result == 0), 1188 "init_thermal_controller failed", return result); 1189 1190 result = init_over_drive_limits(hwmgr, powerplay_table); 1191 1192 PP_ASSERT_WITH_CODE((result == 0), 1193 "init_over_drive_limits failed", return result); 1194 1195 result = init_powerplay_extended_tables(hwmgr, powerplay_table); 1196 1197 PP_ASSERT_WITH_CODE((result == 0), 1198 "init_powerplay_extended_tables failed", return result); 1199 1200 result = init_dpm_2_parameters(hwmgr, powerplay_table); 1201 1202 PP_ASSERT_WITH_CODE((result == 0), 1203 "init_dpm_2_parameters failed", return result); 1204 1205 return result; 1206 } 1207 1208 static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) 1209 { 1210 struct phm_ppt_v2_information *pp_table_info = 1211 (struct phm_ppt_v2_information *)(hwmgr->pptable); 1212 1213 kfree(pp_table_info->vdd_dep_on_sclk); 1214 pp_table_info->vdd_dep_on_sclk = NULL; 1215 1216 kfree(pp_table_info->vdd_dep_on_mclk); 1217 pp_table_info->vdd_dep_on_mclk = NULL; 1218 1219 kfree(pp_table_info->valid_mclk_values); 1220 pp_table_info->valid_mclk_values = NULL; 1221 1222 kfree(pp_table_info->valid_sclk_values); 1223 pp_table_info->valid_sclk_values = NULL; 1224 1225 kfree(pp_table_info->vddc_lookup_table); 1226 pp_table_info->vddc_lookup_table = NULL; 1227 1228 kfree(pp_table_info->vddmem_lookup_table); 1229 pp_table_info->vddmem_lookup_table = NULL; 1230 1231 kfree(pp_table_info->vddci_lookup_table); 1232 pp_table_info->vddci_lookup_table = NULL; 1233 1234 kfree(pp_table_info->ppm_parameter_table); 1235 pp_table_info->ppm_parameter_table = NULL; 1236 1237 kfree(pp_table_info->mm_dep_table); 1238 pp_table_info->mm_dep_table = NULL; 1239 1240 kfree(pp_table_info->cac_dtp_table); 1241 pp_table_info->cac_dtp_table = NULL; 1242 1243 kfree(hwmgr->dyn_state.cac_dtp_table); 1244 hwmgr->dyn_state.cac_dtp_table = NULL; 1245 1246 kfree(pp_table_info->tdp_table); 1247 pp_table_info->tdp_table = NULL; 1248 1249 kfree(hwmgr->pptable); 1250 hwmgr->pptable = NULL; 1251 1252 return 0; 1253 } 1254 1255 const struct pp_table_func vega10_pptable_funcs = { 1256 .pptable_init = vega10_pp_tables_initialize, 1257 .pptable_fini = vega10_pp_tables_uninitialize, 1258 }; 1259 1260 int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) 1261 { 1262 const ATOM_Vega10_State_Array *state_arrays; 1263 const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); 1264 1265 PP_ASSERT_WITH_CODE((pp_table != NULL), 1266 "Missing PowerPlay Table!", return -1); 1267 PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >= 1268 ATOM_Vega10_TABLE_REVISION_VEGA10), 1269 "Incorrect PowerPlay table revision!", return -1); 1270 1271 state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) + 1272 le16_to_cpu(pp_table->usStateArrayOffset)); 1273 1274 return (uint32_t)(state_arrays->ucNumEntries); 1275 } 1276 1277 static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, 1278 uint16_t classification, uint16_t classification2) 1279 { 1280 uint32_t result = 0; 1281 1282 if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) 1283 result |= PP_StateClassificationFlag_Boot; 1284 1285 if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) 1286 result |= PP_StateClassificationFlag_Thermal; 1287 1288 if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) 1289 result |= PP_StateClassificationFlag_LimitedPowerSource; 1290 1291 if (classification & ATOM_PPLIB_CLASSIFICATION_REST) 1292 result |= PP_StateClassificationFlag_Rest; 1293 1294 if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) 1295 result |= PP_StateClassificationFlag_Forced; 1296 1297 if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) 1298 result |= PP_StateClassificationFlag_ACPI; 1299 1300 if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) 1301 result |= PP_StateClassificationFlag_LimitedPowerSource_2; 1302 1303 return result; 1304 } 1305 1306 int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, 1307 uint32_t entry_index, struct pp_power_state *power_state, 1308 int (*call_back_func)(struct pp_hwmgr *, void *, 1309 struct pp_power_state *, void *, uint32_t)) 1310 { 1311 int result = 0; 1312 const ATOM_Vega10_State_Array *state_arrays; 1313 const ATOM_Vega10_State *state_entry; 1314 const ATOM_Vega10_POWERPLAYTABLE *pp_table = 1315 get_powerplay_table(hwmgr); 1316 1317 PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", 1318 return -1;); 1319 power_state->classification.bios_index = entry_index; 1320 1321 if (pp_table->sHeader.format_revision >= 1322 ATOM_Vega10_TABLE_REVISION_VEGA10) { 1323 state_arrays = (ATOM_Vega10_State_Array *) 1324 (((unsigned long)pp_table) + 1325 le16_to_cpu(pp_table->usStateArrayOffset)); 1326 1327 PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, 1328 "Invalid PowerPlay Table State Array Offset.", 1329 return -1); 1330 PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, 1331 "Invalid PowerPlay Table State Array.", 1332 return -1); 1333 PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), 1334 "Invalid PowerPlay Table State Array Entry.", 1335 return -1); 1336 1337 state_entry = &(state_arrays->states[entry_index]); 1338 1339 result = call_back_func(hwmgr, (void *)state_entry, power_state, 1340 (void *)pp_table, 1341 make_classification_flags(hwmgr, 1342 le16_to_cpu(state_entry->usClassification), 1343 le16_to_cpu(state_entry->usClassification2))); 1344 } 1345 1346 if (!result && (power_state->classification.flags & 1347 PP_StateClassificationFlag_Boot)) 1348 result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); 1349 1350 return result; 1351 } 1352 1353 int vega10_baco_set_cap(struct pp_hwmgr *hwmgr) 1354 { 1355 int result = 0; 1356 1357 const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; 1358 1359 powerplay_table = get_powerplay_table(hwmgr); 1360 1361 PP_ASSERT_WITH_CODE((powerplay_table != NULL), 1362 "Missing PowerPlay Table!", return -1); 1363 1364 result = check_powerplay_tables(hwmgr, powerplay_table); 1365 1366 PP_ASSERT_WITH_CODE((result == 0), 1367 "check_powerplay_tables failed", return result); 1368 1369 set_hw_cap( 1370 hwmgr, 1371 0 != (le32_to_cpu(powerplay_table->ulPlatformCaps) & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), 1372 PHM_PlatformCaps_BACO); 1373 return result; 1374 } 1375 1376