Path: blob/master/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c
26552 views
/*1* Copyright 2015 Advanced Micro Devices, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21*/22#include "pp_debug.h"23#include <linux/types.h>24#include <linux/kernel.h>25#include <linux/slab.h>26#include <linux/pci.h>2728#include <drm/amdgpu_drm.h>29#include "processpptables.h"30#include <atom-types.h>31#include <atombios.h>32#include "pptable.h"33#include "power_state.h"34#include "hwmgr.h"35#include "hardwaremanager.h"363738#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 1239#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 1440#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 1641#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 1842#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 2043#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 2244#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 2445#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 264647#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 64849static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr,50const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)51{52uint16_t vce_table_offset = 0;5354if (le16_to_cpu(powerplay_table->usTableSize) >=55sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {56const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =57(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;5859if (powerplay_table3->usExtendendedHeaderOffset > 0) {60const ATOM_PPLIB_EXTENDEDHEADER *extended_header =61(const ATOM_PPLIB_EXTENDEDHEADER *)62(((unsigned long)powerplay_table3) +63le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));64if (le16_to_cpu(extended_header->usSize) >=65SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2)66vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset);67}68}6970return vce_table_offset;71}7273static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr,74const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)75{76uint16_t table_offset = get_vce_table_offset(hwmgr,77powerplay_table);7879if (table_offset > 0)80return table_offset + 1;8182return 0;83}8485static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr,86const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)87{88uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,89powerplay_table);90uint16_t table_size = 0;9192if (table_offset > 0) {93const VCEClockInfoArray *p = (const VCEClockInfoArray *)94(((unsigned long) powerplay_table) + table_offset);95table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo);96}9798return table_size;99}100101static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr,102const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)103{104uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr,105powerplay_table);106107if (table_offset > 0)108return table_offset + get_vce_clock_info_array_size(hwmgr,109powerplay_table);110111return 0;112}113114static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr,115const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)116{117uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);118uint16_t table_size = 0;119120if (table_offset > 0) {121const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable =122(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset);123124table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record);125}126return table_size;127}128129static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)130{131uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table);132133if (table_offset > 0)134return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table);135136return 0;137}138139static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table(140struct pp_hwmgr *hwmgr,141const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)142{143uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table);144145if (table_offset > 0)146return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset);147148return NULL;149}150151static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr,152const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)153{154uint16_t uvd_table_offset = 0;155156if (le16_to_cpu(powerplay_table->usTableSize) >=157sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {158const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =159(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;160if (powerplay_table3->usExtendendedHeaderOffset > 0) {161const ATOM_PPLIB_EXTENDEDHEADER *extended_header =162(const ATOM_PPLIB_EXTENDEDHEADER *)163(((unsigned long)powerplay_table3) +164le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));165if (le16_to_cpu(extended_header->usSize) >=166SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3)167uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset);168}169}170return uvd_table_offset;171}172173static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr,174const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)175{176uint16_t table_offset = get_uvd_table_offset(hwmgr,177powerplay_table);178179if (table_offset > 0)180return table_offset + 1;181return 0;182}183184static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr,185const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)186{187uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,188powerplay_table);189uint16_t table_size = 0;190191if (table_offset > 0) {192const UVDClockInfoArray *p = (const UVDClockInfoArray *)193(((unsigned long) powerplay_table)194+ table_offset);195table_size = sizeof(UCHAR) +196p->ucNumEntries * sizeof(UVDClockInfo);197}198199return table_size;200}201202static uint16_t get_uvd_clock_voltage_limit_table_offset(203struct pp_hwmgr *hwmgr,204const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)205{206uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr,207powerplay_table);208209if (table_offset > 0)210return table_offset +211get_uvd_clock_info_array_size(hwmgr, powerplay_table);212213return 0;214}215216static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr,217const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)218{219uint16_t samu_table_offset = 0;220221if (le16_to_cpu(powerplay_table->usTableSize) >=222sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {223const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =224(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;225if (powerplay_table3->usExtendendedHeaderOffset > 0) {226const ATOM_PPLIB_EXTENDEDHEADER *extended_header =227(const ATOM_PPLIB_EXTENDEDHEADER *)228(((unsigned long)powerplay_table3) +229le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));230if (le16_to_cpu(extended_header->usSize) >=231SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4)232samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset);233}234}235236return samu_table_offset;237}238239static uint16_t get_samu_clock_voltage_limit_table_offset(240struct pp_hwmgr *hwmgr,241const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)242{243uint16_t table_offset = get_samu_table_offset(hwmgr,244powerplay_table);245246if (table_offset > 0)247return table_offset + 1;248249return 0;250}251252static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr,253const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)254{255uint16_t acp_table_offset = 0;256257if (le16_to_cpu(powerplay_table->usTableSize) >=258sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {259const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =260(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;261if (powerplay_table3->usExtendendedHeaderOffset > 0) {262const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =263(const ATOM_PPLIB_EXTENDEDHEADER *)264(((unsigned long)powerplay_table3) +265le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));266if (le16_to_cpu(pExtendedHeader->usSize) >=267SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6)268acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset);269}270}271272return acp_table_offset;273}274275static uint16_t get_acp_clock_voltage_limit_table_offset(276struct pp_hwmgr *hwmgr,277const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)278{279uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table);280281if (tableOffset > 0)282return tableOffset + 1;283284return 0;285}286287static uint16_t get_cacp_tdp_table_offset(288struct pp_hwmgr *hwmgr,289const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)290{291uint16_t cacTdpTableOffset = 0;292293if (le16_to_cpu(powerplay_table->usTableSize) >=294sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {295const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =296(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;297if (powerplay_table3->usExtendendedHeaderOffset > 0) {298const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =299(const ATOM_PPLIB_EXTENDEDHEADER *)300(((unsigned long)powerplay_table3) +301le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));302if (le16_to_cpu(pExtendedHeader->usSize) >=303SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7)304cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset);305}306}307308return cacTdpTableOffset;309}310311static int get_cac_tdp_table(struct pp_hwmgr *hwmgr,312struct phm_cac_tdp_table **ptable,313const ATOM_PowerTune_Table *table,314uint16_t us_maximum_power_delivery_limit)315{316unsigned long table_size;317struct phm_cac_tdp_table *tdp_table;318319table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table);320321tdp_table = kzalloc(table_size, GFP_KERNEL);322if (NULL == tdp_table)323return -ENOMEM;324325tdp_table->usTDP = le16_to_cpu(table->usTDP);326tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP);327tdp_table->usTDC = le16_to_cpu(table->usTDC);328tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit);329tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit);330tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage);331tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage);332tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit;333334*ptable = tdp_table;335336return 0;337}338339static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr,340const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)341{342uint16_t sclk_vdd_gfx_table_offset = 0;343344if (le16_to_cpu(powerplay_table->usTableSize) >=345sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {346const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =347(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;348if (powerplay_table3->usExtendendedHeaderOffset > 0) {349const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader =350(const ATOM_PPLIB_EXTENDEDHEADER *)351(((unsigned long)powerplay_table3) +352le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));353if (le16_to_cpu(pExtendedHeader->usSize) >=354SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8)355sclk_vdd_gfx_table_offset =356le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset);357}358}359360return sclk_vdd_gfx_table_offset;361}362363static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(364struct pp_hwmgr *hwmgr,365const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)366{367uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table);368369if (tableOffset > 0)370return tableOffset;371372return 0;373}374375376static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr,377struct phm_clock_voltage_dependency_table **ptable,378const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table)379{380381unsigned long i;382struct phm_clock_voltage_dependency_table *dep_table;383384dep_table = kzalloc(struct_size(dep_table, entries, table->ucNumEntries),385GFP_KERNEL);386if (NULL == dep_table)387return -ENOMEM;388389dep_table->count = (unsigned long)table->ucNumEntries;390391for (i = 0; i < dep_table->count; i++) {392dep_table->entries[i].clk =393((unsigned long)table->entries[i].ucClockHigh << 16) |394le16_to_cpu(table->entries[i].usClockLow);395dep_table->entries[i].v =396(unsigned long)le16_to_cpu(table->entries[i].usVoltage);397}398399*ptable = dep_table;400401return 0;402}403404static int get_valid_clk(struct pp_hwmgr *hwmgr,405struct phm_clock_array **ptable,406const struct phm_clock_voltage_dependency_table *table)407{408unsigned long i;409struct phm_clock_array *clock_table;410411clock_table = kzalloc(struct_size(clock_table, values, table->count), GFP_KERNEL);412if (!clock_table)413return -ENOMEM;414415clock_table->count = (unsigned long)table->count;416417for (i = 0; i < clock_table->count; i++)418clock_table->values[i] = (unsigned long)table->entries[i].clk;419420*ptable = clock_table;421422return 0;423}424425static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr,426struct phm_clock_and_voltage_limits *limits,427const ATOM_PPLIB_Clock_Voltage_Limit_Table *table)428{429limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) |430le16_to_cpu(table->entries[0].usSclkLow);431limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) |432le16_to_cpu(table->entries[0].usMclkLow);433limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc);434limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci);435436return 0;437}438439440static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,441enum phm_platform_caps cap)442{443if (enable)444phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap);445else446phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap);447}448449static int set_platform_caps(struct pp_hwmgr *hwmgr,450unsigned long powerplay_caps)451{452set_hw_cap(453hwmgr,4540 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY),455PHM_PlatformCaps_PowerPlaySupport456);457458set_hw_cap(459hwmgr,4600 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE),461PHM_PlatformCaps_BiosPowerSourceControl462);463464set_hw_cap(465hwmgr,4660 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s),467PHM_PlatformCaps_EnableASPML0s468);469470set_hw_cap(471hwmgr,4720 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1),473PHM_PlatformCaps_EnableASPML1474);475476set_hw_cap(477hwmgr,4780 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS),479PHM_PlatformCaps_EnableBackbias480);481482set_hw_cap(483hwmgr,4840 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC),485PHM_PlatformCaps_AutomaticDCTransition486);487488set_hw_cap(489hwmgr,4900 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY),491PHM_PlatformCaps_GeminiPrimary492);493494set_hw_cap(495hwmgr,4960 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC),497PHM_PlatformCaps_StepVddc498);499500set_hw_cap(501hwmgr,5020 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL),503PHM_PlatformCaps_EnableVoltageControl504);505506set_hw_cap(507hwmgr,5080 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL),509PHM_PlatformCaps_EnableSideportControl510);511512set_hw_cap(513hwmgr,5140 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1),515PHM_PlatformCaps_TurnOffPll_ASPML1516);517518set_hw_cap(519hwmgr,5200 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL),521PHM_PlatformCaps_EnableHTLinkControl522);523524set_hw_cap(525hwmgr,5260 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL),527PHM_PlatformCaps_EnableMVDDControl528);529530set_hw_cap(531hwmgr,5320 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL),533PHM_PlatformCaps_ControlVDDCI534);535536set_hw_cap(537hwmgr,5380 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT),539PHM_PlatformCaps_RegulatorHot540);541542set_hw_cap(543hwmgr,5440 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT),545PHM_PlatformCaps_BootStateOnAlert546);547548set_hw_cap(549hwmgr,5500 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT),551PHM_PlatformCaps_DontWaitForVBlankOnAlert552);553554set_hw_cap(555hwmgr,5560 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO),557PHM_PlatformCaps_BACO558);559560set_hw_cap(561hwmgr,5620 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE),563PHM_PlatformCaps_NewCACVoltage564);565566set_hw_cap(567hwmgr,5680 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY),569PHM_PlatformCaps_RevertGPIO5Polarity570);571572set_hw_cap(573hwmgr,5740 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17),575PHM_PlatformCaps_Thermal2GPIO17576);577578set_hw_cap(579hwmgr,5800 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE),581PHM_PlatformCaps_VRHotGPIOConfigurable582);583584set_hw_cap(585hwmgr,5860 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION),587PHM_PlatformCaps_TempInversion588);589590set_hw_cap(591hwmgr,5920 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV),593PHM_PlatformCaps_EVV594);595596set_hw_cap(597hwmgr,5980 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL),599PHM_PlatformCaps_CombinePCCWithThermalSignal600);601602set_hw_cap(603hwmgr,6040 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE),605PHM_PlatformCaps_LoadPostProductionFirmware606);607608set_hw_cap(609hwmgr,6100 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC),611PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc612);613614return 0;615}616617static PP_StateClassificationFlags make_classification_flags(618struct pp_hwmgr *hwmgr,619USHORT classification,620USHORT classification2)621{622PP_StateClassificationFlags result = 0;623624if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT)625result |= PP_StateClassificationFlag_Boot;626627if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL)628result |= PP_StateClassificationFlag_Thermal;629630if (classification &631ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE)632result |= PP_StateClassificationFlag_LimitedPowerSource;633634if (classification & ATOM_PPLIB_CLASSIFICATION_REST)635result |= PP_StateClassificationFlag_Rest;636637if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED)638result |= PP_StateClassificationFlag_Forced;639640if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE)641result |= PP_StateClassificationFlag_3DPerformance;642643644if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE)645result |= PP_StateClassificationFlag_ACOverdriveTemplate;646647if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE)648result |= PP_StateClassificationFlag_Uvd;649650if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE)651result |= PP_StateClassificationFlag_UvdHD;652653if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE)654result |= PP_StateClassificationFlag_UvdSD;655656if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE)657result |= PP_StateClassificationFlag_HD2;658659if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI)660result |= PP_StateClassificationFlag_ACPI;661662if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2)663result |= PP_StateClassificationFlag_LimitedPowerSource_2;664665666if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV)667result |= PP_StateClassificationFlag_ULV;668669if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC)670result |= PP_StateClassificationFlag_UvdMVC;671672return result;673}674675static int init_non_clock_fields(struct pp_hwmgr *hwmgr,676struct pp_power_state *ps,677uint8_t version,678const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) {679unsigned long rrr_index;680unsigned long tmp;681682ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) &683ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT;684ps->classification.flags = make_classification_flags(hwmgr,685le16_to_cpu(pnon_clock_info->usClassification),686le16_to_cpu(pnon_clock_info->usClassification2));687688ps->classification.temporary_state = false;689ps->classification.to_be_deleted = false;690tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &691ATOM_PPLIB_SINGLE_DISPLAY_ONLY;692693ps->validation.singleDisplayOnly = (0 != tmp);694695tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &696ATOM_PPLIB_DISALLOW_ON_DC;697698ps->validation.disallowOnDC = (0 != tmp);699700ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &701ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >>702ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1;703704ps->display.disableFrameModulation = false;705706rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &707ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >>708ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT;709710if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) {711static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \712{ 0, 50, 0 };713714ps->display.refreshrateSource = PP_RefreshrateSource_Explicit;715ps->display.explicitRefreshrate = look_up[rrr_index];716ps->display.limitRefreshrate = true;717718if (ps->display.explicitRefreshrate == 0)719ps->display.limitRefreshrate = false;720} else721ps->display.limitRefreshrate = false;722723tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &724ATOM_PPLIB_ENABLE_VARIBRIGHT;725726ps->display.enableVariBright = (0 != tmp);727728tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &729ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF;730731ps->memory.dllOff = (0 != tmp);732733ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &734ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT;735736ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *737pnon_clock_info->ucMinTemperature;738739ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES *740pnon_clock_info->ucMaxTemperature;741742tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &743ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING;744745ps->software.disableLoadBalancing = tmp;746747tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) &748ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS;749750ps->software.enableSleepForTimestamps = (0 != tmp);751752ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower;753754if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) {755ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK);756ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK);757} else {758ps->uvd_clocks.VCLK = 0;759ps->uvd_clocks.DCLK = 0;760}761762return 0;763}764765static ULONG size_of_entry_v2(ULONG num_dpm_levels)766{767return (sizeof(UCHAR) + sizeof(UCHAR) +768(num_dpm_levels * sizeof(UCHAR)));769}770771static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2(772const StateArray * pstate_arrays,773ULONG entry_index)774{775ULONG i;776const ATOM_PPLIB_STATE_V2 *pstate;777778pstate = pstate_arrays->states;779if (entry_index <= pstate_arrays->ucNumEntries) {780for (i = 0; i < entry_index; i++)781pstate = (ATOM_PPLIB_STATE_V2 *)(782(unsigned long)pstate +783size_of_entry_v2(pstate->ucNumDPMLevels));784}785return pstate;786}787788static const unsigned char soft_dummy_pp_table[] = {7890xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00,7900x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,7910x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00,7920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,7930x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,7940x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,7950x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00,7960x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,7970x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,7980x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00,7990x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00,8000x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,8010x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00,8020x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,8030x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59,8040xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28,8050x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01,8060xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01,8070x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a,8080x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03,8090x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c,8100x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01,8110x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e,8120xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70,8130x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08,8140x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70,8150x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00,8160x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c,8170x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00,8180x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a,8190x00820};821822static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table(823struct pp_hwmgr *hwmgr)824{825const void *table_addr = hwmgr->soft_pp_table;826uint8_t frev, crev;827uint16_t size;828829if (!table_addr) {830if (hwmgr->chip_id == CHIP_RAVEN) {831table_addr = &soft_dummy_pp_table[0];832hwmgr->soft_pp_table = &soft_dummy_pp_table[0];833hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table);834} else {835table_addr = smu_atom_get_data_table(hwmgr->adev,836GetIndexIntoMasterTable(DATA, PowerPlayInfo),837&size, &frev, &crev);838hwmgr->soft_pp_table = table_addr;839hwmgr->soft_pp_table_size = size;840}841}842843return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr;844}845846int pp_tables_get_response_times(struct pp_hwmgr *hwmgr,847uint32_t *vol_rep_time, uint32_t *bb_rep_time)848{849const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr);850851PP_ASSERT_WITH_CODE(NULL != powerplay_tab,852"Missing PowerPlay Table!", return -EINVAL);853854*vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime);855*bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime);856857return 0;858}859860int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr,861unsigned long *num_of_entries)862{863const StateArray *pstate_arrays;864const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);865866if (powerplay_table == NULL)867return -1;868869if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {870pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +871le16_to_cpu(powerplay_table->usStateArrayOffset));872873*num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries);874} else875*num_of_entries = (unsigned long)(powerplay_table->ucNumStates);876877return 0;878}879880int pp_tables_get_entry(struct pp_hwmgr *hwmgr,881unsigned long entry_index,882struct pp_power_state *ps,883pp_tables_hw_clock_info_callback func)884{885int i;886const StateArray *pstate_arrays;887const ATOM_PPLIB_STATE_V2 *pstate_entry_v2;888const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info;889const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);890int result = 0;891int res = 0;892893const ClockInfoArray *pclock_arrays;894895const NonClockInfoArray *pnon_clock_arrays;896897const ATOM_PPLIB_STATE *pstate_entry;898899if (powerplay_table == NULL)900return -1;901902ps->classification.bios_index = entry_index;903904if (powerplay_table->sHeader.ucTableFormatRevision >= 6) {905pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) +906le16_to_cpu(powerplay_table->usStateArrayOffset));907908if (entry_index > pstate_arrays->ucNumEntries)909return -1;910911pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index);912pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +913le16_to_cpu(powerplay_table->usClockInfoArrayOffset));914915pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) +916le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset));917918pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) +919(pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize));920921result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info);922923for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) {924const void *pclock_info = (const void *)(925(unsigned long)(pclock_arrays->clockInfo) +926(pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize));927res = func(hwmgr, &ps->hardware, i, pclock_info);928if ((0 == result) && (0 != res))929result = res;930}931} else {932if (entry_index > powerplay_table->ucNumStates)933return -1;934935pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table +936le16_to_cpu(powerplay_table->usStateArrayOffset) +937entry_index * powerplay_table->ucStateEntrySize);938939pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table +940le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) +941pstate_entry->ucNonClockStateIndex *942powerplay_table->ucNonClockSize);943944result = init_non_clock_fields(hwmgr, ps,945powerplay_table->ucNonClockSize,946pnon_clock_info);947948for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) {949const void *pclock_info = (const void *)((unsigned long)powerplay_table +950le16_to_cpu(powerplay_table->usClockInfoArrayOffset) +951pstate_entry->ucClockStateIndices[i] *952powerplay_table->ucClockInfoSize);953954int res = func(hwmgr, &ps->hardware, i, pclock_info);955956if ((0 == result) && (0 != res))957result = res;958}959}960961if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) {962if (hwmgr->chip_family < AMDGPU_FAMILY_RV)963result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware));964}965966return result;967}968969static int init_powerplay_tables(970struct pp_hwmgr *hwmgr,971const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table972)973{974return 0;975}976977978static int init_thermal_controller(979struct pp_hwmgr *hwmgr,980const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)981{982struct amdgpu_device *adev = hwmgr->adev;983984hwmgr->thermal_controller.ucType =985powerplay_table->sThermalController.ucType;986hwmgr->thermal_controller.ucI2cLine =987powerplay_table->sThermalController.ucI2cLine;988hwmgr->thermal_controller.ucI2cAddress =989powerplay_table->sThermalController.ucI2cAddress;990991hwmgr->thermal_controller.fanInfo.bNoFan =992(0 != (powerplay_table->sThermalController.ucFanParameters &993ATOM_PP_FANPARAMETERS_NOFAN));994995hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =996powerplay_table->sThermalController.ucFanParameters &997ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;998999hwmgr->thermal_controller.fanInfo.ulMinRPM1000= powerplay_table->sThermalController.ucFanMinRPM * 100UL;1001hwmgr->thermal_controller.fanInfo.ulMaxRPM1002= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;10031004set_hw_cap(hwmgr,1005ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,1006PHM_PlatformCaps_ThermalController);10071008if (powerplay_table->usTableSize >= sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) {1009const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 =1010(const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;10111012if (0 == le16_to_cpu(powerplay_table3->usFanTableOffset)) {1013hwmgr->thermal_controller.use_hw_fan_control = 1;1014return 0;1015} else {1016const ATOM_PPLIB_FANTABLE *fan_table =1017(const ATOM_PPLIB_FANTABLE *)(((unsigned long)powerplay_table) +1018le16_to_cpu(powerplay_table3->usFanTableOffset));10191020if (1 <= fan_table->ucFanTableFormat) {1021hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst =1022fan_table->ucTHyst;1023hwmgr->thermal_controller.advanceFanControlParameters.usTMin =1024le16_to_cpu(fan_table->usTMin);1025hwmgr->thermal_controller.advanceFanControlParameters.usTMed =1026le16_to_cpu(fan_table->usTMed);1027hwmgr->thermal_controller.advanceFanControlParameters.usTHigh =1028le16_to_cpu(fan_table->usTHigh);1029hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin =1030le16_to_cpu(fan_table->usPWMMin);1031hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed =1032le16_to_cpu(fan_table->usPWMMed);1033hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh =1034le16_to_cpu(fan_table->usPWMHigh);1035hwmgr->thermal_controller.advanceFanControlParameters.usTMax = 10900;1036hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay = 100000;10371038phm_cap_set(hwmgr->platform_descriptor.platformCaps,1039PHM_PlatformCaps_MicrocodeFanControl);1040}10411042if (2 <= fan_table->ucFanTableFormat) {1043const ATOM_PPLIB_FANTABLE2 *fan_table2 =1044(const ATOM_PPLIB_FANTABLE2 *)(((unsigned long)powerplay_table) +1045le16_to_cpu(powerplay_table3->usFanTableOffset));1046hwmgr->thermal_controller.advanceFanControlParameters.usTMax =1047le16_to_cpu(fan_table2->usTMax);1048}10491050if (3 <= fan_table->ucFanTableFormat) {1051const ATOM_PPLIB_FANTABLE3 *fan_table3 =1052(const ATOM_PPLIB_FANTABLE3 *) (((unsigned long)powerplay_table) +1053le16_to_cpu(powerplay_table3->usFanTableOffset));10541055hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode =1056fan_table3->ucFanControlMode;10571058if ((3 == fan_table->ucFanTableFormat) &&1059(0x67B1 == adev->pdev->device))1060hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =106147;1062else1063hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM =1064le16_to_cpu(fan_table3->usFanPWMMax);10651066hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity =10674836;1068hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity =1069le16_to_cpu(fan_table3->usFanOutputSensitivity);1070}10711072if (6 <= fan_table->ucFanTableFormat) {1073const ATOM_PPLIB_FANTABLE4 *fan_table4 =1074(const ATOM_PPLIB_FANTABLE4 *)(((unsigned long)powerplay_table) +1075le16_to_cpu(powerplay_table3->usFanTableOffset));10761077phm_cap_set(hwmgr->platform_descriptor.platformCaps,1078PHM_PlatformCaps_FanSpeedInTableIsRPM);10791080hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM =1081le16_to_cpu(fan_table4->usFanRPMMax);1082}10831084if (7 <= fan_table->ucFanTableFormat) {1085const ATOM_PPLIB_FANTABLE5 *fan_table5 =1086(const ATOM_PPLIB_FANTABLE5 *)(((unsigned long)powerplay_table) +1087le16_to_cpu(powerplay_table3->usFanTableOffset));10881089if (0x67A2 == adev->pdev->device ||10900x67A9 == adev->pdev->device ||10910x67B9 == adev->pdev->device) {1092phm_cap_set(hwmgr->platform_descriptor.platformCaps,1093PHM_PlatformCaps_GeminiRegulatorFanControlSupport);1094hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentLow =1095le16_to_cpu(fan_table5->usFanCurrentLow);1096hwmgr->thermal_controller.advanceFanControlParameters.usFanCurrentHigh =1097le16_to_cpu(fan_table5->usFanCurrentHigh);1098hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMLow =1099le16_to_cpu(fan_table5->usFanRPMLow);1100hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMHigh =1101le16_to_cpu(fan_table5->usFanRPMHigh);1102}1103}1104}1105}11061107return 0;1108}11091110static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr,1111const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,1112const ATOM_FIRMWARE_INFO_V1_4 *fw_info)1113{1114hwmgr->platform_descriptor.overdriveLimit.engineClock =1115le32_to_cpu(fw_info->ulASICMaxEngineClock);11161117hwmgr->platform_descriptor.overdriveLimit.memoryClock =1118le32_to_cpu(fw_info->ulASICMaxMemoryClock);11191120hwmgr->platform_descriptor.maxOverdriveVDDC =1121le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF;11221123hwmgr->platform_descriptor.minOverdriveVDDC =1124le16_to_cpu(fw_info->usBootUpVDDCVoltage);11251126hwmgr->platform_descriptor.maxOverdriveVDDC =1127le16_to_cpu(fw_info->usBootUpVDDCVoltage);11281129hwmgr->platform_descriptor.overdriveVDDCStep = 0;1130return 0;1131}11321133static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr,1134const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table,1135const ATOM_FIRMWARE_INFO_V2_1 *fw_info)1136{1137const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3;1138const ATOM_PPLIB_EXTENDEDHEADER *header;11391140if (le16_to_cpu(powerplay_table->usTableSize) <1141sizeof(ATOM_PPLIB_POWERPLAYTABLE3))1142return 0;11431144powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table;11451146if (0 == powerplay_table3->usExtendendedHeaderOffset)1147return 0;11481149header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) +1150le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset));11511152hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock);1153hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock);115411551156hwmgr->platform_descriptor.minOverdriveVDDC = 0;1157hwmgr->platform_descriptor.maxOverdriveVDDC = 0;1158hwmgr->platform_descriptor.overdriveVDDCStep = 0;11591160return 0;1161}11621163static int init_overdrive_limits(struct pp_hwmgr *hwmgr,1164const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)1165{1166int result = 0;1167uint8_t frev, crev;1168uint16_t size;11691170const ATOM_COMMON_TABLE_HEADER *fw_info = NULL;11711172hwmgr->platform_descriptor.overdriveLimit.engineClock = 0;1173hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0;1174hwmgr->platform_descriptor.minOverdriveVDDC = 0;1175hwmgr->platform_descriptor.maxOverdriveVDDC = 0;1176hwmgr->platform_descriptor.overdriveVDDCStep = 0;11771178if (hwmgr->chip_id == CHIP_RAVEN)1179return 0;11801181/* We assume here that fw_info is unchanged if this call fails.*/1182fw_info = smu_atom_get_data_table(hwmgr->adev,1183GetIndexIntoMasterTable(DATA, FirmwareInfo),1184&size, &frev, &crev);1185PP_ASSERT_WITH_CODE(fw_info != NULL,1186"Missing firmware info!", return -EINVAL);11871188if ((fw_info->ucTableFormatRevision == 1)1189&& (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4)))1190result = init_overdrive_limits_V1_4(hwmgr,1191powerplay_table,1192(const ATOM_FIRMWARE_INFO_V1_4 *)fw_info);11931194else if ((fw_info->ucTableFormatRevision == 2)1195&& (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1)))1196result = init_overdrive_limits_V2_1(hwmgr,1197powerplay_table,1198(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);11991200return result;1201}12021203static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,1204struct phm_uvd_clock_voltage_dependency_table **ptable,1205const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table,1206const UVDClockInfoArray *array)1207{1208unsigned long i;1209struct phm_uvd_clock_voltage_dependency_table *uvd_table;12101211uvd_table = kzalloc(struct_size(uvd_table, entries, table->numEntries),1212GFP_KERNEL);1213if (!uvd_table)1214return -ENOMEM;12151216uvd_table->count = table->numEntries;12171218for (i = 0; i < table->numEntries; i++) {1219const UVDClockInfo *entry =1220&array->entries[table->entries[i].ucUVDClockInfoIndex];1221uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);1222uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16)1223| le16_to_cpu(entry->usVClkLow);1224uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16)1225| le16_to_cpu(entry->usDClkLow);1226}12271228*ptable = uvd_table;12291230return 0;1231}12321233static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,1234struct phm_vce_clock_voltage_dependency_table **ptable,1235const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table,1236const VCEClockInfoArray *array)1237{1238unsigned long i;1239struct phm_vce_clock_voltage_dependency_table *vce_table;12401241vce_table = kzalloc(struct_size(vce_table, entries, table->numEntries),1242GFP_KERNEL);1243if (!vce_table)1244return -ENOMEM;12451246vce_table->count = table->numEntries;1247for (i = 0; i < table->numEntries; i++) {1248const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex];12491250vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);1251vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16)1252| le16_to_cpu(entry->usEVClkLow);1253vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16)1254| le16_to_cpu(entry->usECClkLow);1255}12561257*ptable = vce_table;12581259return 0;1260}12611262static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,1263struct phm_samu_clock_voltage_dependency_table **ptable,1264const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table)1265{1266unsigned long i;1267struct phm_samu_clock_voltage_dependency_table *samu_table;12681269samu_table = kzalloc(struct_size(samu_table, entries, table->numEntries),1270GFP_KERNEL);1271if (!samu_table)1272return -ENOMEM;12731274samu_table->count = table->numEntries;12751276for (i = 0; i < table->numEntries; i++) {1277samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);1278samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16)1279| le16_to_cpu(table->entries[i].usSAMClockLow);1280}12811282*ptable = samu_table;12831284return 0;1285}12861287static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr,1288struct phm_acp_clock_voltage_dependency_table **ptable,1289const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table)1290{1291unsigned long i;1292struct phm_acp_clock_voltage_dependency_table *acp_table;12931294acp_table = kzalloc(struct_size(acp_table, entries, table->numEntries),1295GFP_KERNEL);1296if (!acp_table)1297return -ENOMEM;12981299acp_table->count = (unsigned long)table->numEntries;13001301for (i = 0; i < table->numEntries; i++) {1302acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage);1303acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16)1304| le16_to_cpu(table->entries[i].usACPClockLow);1305}13061307*ptable = acp_table;13081309return 0;1310}13111312static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr,1313const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)1314{1315ATOM_PPLIB_Clock_Voltage_Dependency_Table *table;1316ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table;1317int result = 0;13181319uint16_t vce_clock_info_array_offset;1320uint16_t uvd_clock_info_array_offset;1321uint16_t table_offset;13221323hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;1324hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;1325hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;1326hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL;1327hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;1328hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;1329hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;1330hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;1331hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;1332hwmgr->dyn_state.ppm_parameter_table = NULL;1333hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;13341335vce_clock_info_array_offset = get_vce_clock_info_array_offset(1336hwmgr, powerplay_table);1337table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr,1338powerplay_table);1339if (vce_clock_info_array_offset > 0 && table_offset > 0) {1340const VCEClockInfoArray *array = (const VCEClockInfoArray *)1341(((unsigned long) powerplay_table) +1342vce_clock_info_array_offset);1343const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table =1344(const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)1345(((unsigned long) powerplay_table) + table_offset);1346result = get_vce_clock_voltage_limit_table(hwmgr,1347&hwmgr->dyn_state.vce_clock_voltage_dependency_table,1348table, array);1349}13501351uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table);1352table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table);13531354if (uvd_clock_info_array_offset > 0 && table_offset > 0) {1355const UVDClockInfoArray *array = (const UVDClockInfoArray *)1356(((unsigned long) powerplay_table) +1357uvd_clock_info_array_offset);1358const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable =1359(const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *)1360(((unsigned long) powerplay_table) + table_offset);1361result = get_uvd_clock_voltage_limit_table(hwmgr,1362&hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array);1363}13641365table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr,1366powerplay_table);13671368if (table_offset > 0) {1369const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable =1370(const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *)1371(((unsigned long) powerplay_table) + table_offset);1372result = get_samu_clock_voltage_limit_table(hwmgr,1373&hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable);1374}13751376table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr,1377powerplay_table);13781379if (table_offset > 0) {1380const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable =1381(const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *)1382(((unsigned long) powerplay_table) + table_offset);1383result = get_acp_clock_voltage_limit_table(hwmgr,1384&hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable);1385}13861387table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table);1388if (table_offset > 0) {1389UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset);13901391if (rev_id > 0) {1392const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table =1393(const ATOM_PPLIB_POWERTUNE_Table_V1 *)1394(((unsigned long) powerplay_table) + table_offset);1395result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table,1396&tune_table->power_tune_table,1397le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit));1398hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp =1399le16_to_cpu(tune_table->usTjMax);1400} else {1401const ATOM_PPLIB_POWERTUNE_Table *tune_table =1402(const ATOM_PPLIB_POWERTUNE_Table *)1403(((unsigned long) powerplay_table) + table_offset);1404result = get_cac_tdp_table(hwmgr,1405&hwmgr->dyn_state.cac_dtp_table,1406&tune_table->power_tune_table, 255);1407}1408}14091410if (le16_to_cpu(powerplay_table->usTableSize) >=1411sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {1412const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =1413(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;1414if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) {1415table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)1416(((unsigned long) powerplay_table4) +1417le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset));1418result = get_clock_voltage_dependency_table(hwmgr,1419&hwmgr->dyn_state.vddc_dependency_on_sclk, table);1420}14211422if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) {1423table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)1424(((unsigned long) powerplay_table4) +1425le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset));1426result = get_clock_voltage_dependency_table(hwmgr,1427&hwmgr->dyn_state.vddci_dependency_on_mclk, table);1428}14291430if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) {1431table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)1432(((unsigned long) powerplay_table4) +1433le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset));1434result = get_clock_voltage_dependency_table(hwmgr,1435&hwmgr->dyn_state.vddc_dependency_on_mclk, table);1436}14371438if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) {1439limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *)1440(((unsigned long) powerplay_table4) +1441le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset));1442result = get_clock_voltage_limit(hwmgr,1443&hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table);1444}14451446if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) &&1447(0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count))1448result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values,1449hwmgr->dyn_state.vddc_dependency_on_mclk);14501451if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) &&1452(0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count))1453result = get_valid_clk(hwmgr,1454&hwmgr->dyn_state.valid_sclk_values,1455hwmgr->dyn_state.vddc_dependency_on_sclk);14561457if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) {1458table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)1459(((unsigned long) powerplay_table4) +1460le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset));1461result = get_clock_voltage_dependency_table(hwmgr,1462&hwmgr->dyn_state.mvdd_dependency_on_mclk, table);1463}1464}14651466table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr,1467powerplay_table);14681469if (table_offset > 0) {1470table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *)1471(((unsigned long) powerplay_table) + table_offset);1472result = get_clock_voltage_dependency_table(hwmgr,1473&hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table);1474}14751476return result;1477}14781479static int get_cac_leakage_table(struct pp_hwmgr *hwmgr,1480struct phm_cac_leakage_table **ptable,1481const ATOM_PPLIB_CAC_Leakage_Table *table)1482{1483struct phm_cac_leakage_table *cac_leakage_table;1484unsigned long i;14851486if (!hwmgr || !table || !ptable)1487return -EINVAL;14881489cac_leakage_table = kzalloc(struct_size(cac_leakage_table, entries, table->ucNumEntries),1490GFP_KERNEL);1491if (!cac_leakage_table)1492return -ENOMEM;14931494cac_leakage_table->count = (ULONG)table->ucNumEntries;14951496for (i = 0; i < cac_leakage_table->count; i++) {1497if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,1498PHM_PlatformCaps_EVV)) {1499cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1);1500cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2);1501cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3);1502} else {1503cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc);1504cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue);1505}1506}15071508*ptable = cac_leakage_table;15091510return 0;1511}15121513static int get_platform_power_management_table(struct pp_hwmgr *hwmgr,1514ATOM_PPLIB_PPM_Table *atom_ppm_table)1515{1516struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL);15171518if (NULL == ptr)1519return -ENOMEM;15201521ptr->ppm_design = atom_ppm_table->ucPpmDesign;1522ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber);1523ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP);1524ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP);1525ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC);1526ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC);1527ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP);1528ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP);1529ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower);1530ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax);1531hwmgr->dyn_state.ppm_parameter_table = ptr;15321533return 0;1534}15351536static int init_dpm2_parameters(struct pp_hwmgr *hwmgr,1537const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)1538{1539int result = 0;15401541if (le16_to_cpu(powerplay_table->usTableSize) >=1542sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) {1543const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 =1544(const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table;1545const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 =1546(const ATOM_PPLIB_POWERPLAYTABLE4 *)1547(&ptable5->basicTable4);1548const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 =1549(const ATOM_PPLIB_POWERPLAYTABLE3 *)1550(&ptable4->basicTable3);1551const ATOM_PPLIB_EXTENDEDHEADER *extended_header;1552uint16_t table_offset;1553ATOM_PPLIB_PPM_Table *atom_ppm_table;15541555hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit);1556hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit);15571558hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit);1559hwmgr->platform_descriptor.TDPAdjustment = 0;15601561hwmgr->platform_descriptor.VidAdjustment = 0;1562hwmgr->platform_descriptor.VidAdjustmentPolarity = 0;1563hwmgr->platform_descriptor.VidMinLimit = 0;1564hwmgr->platform_descriptor.VidMaxLimit = 1500000;1565hwmgr->platform_descriptor.VidStep = 6250;15661567hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit);15681569if (hwmgr->platform_descriptor.TDPODLimit != 0)1570phm_cap_set(hwmgr->platform_descriptor.platformCaps,1571PHM_PlatformCaps_PowerControl);15721573hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold);15741575hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage);15761577hwmgr->dyn_state.cac_leakage_table = NULL;15781579if (0 != ptable5->usCACLeakageTableOffset) {1580const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table =1581(ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) +1582le16_to_cpu(ptable5->usCACLeakageTableOffset));1583result = get_cac_leakage_table(hwmgr,1584&hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table);1585}15861587hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope);15881589hwmgr->dyn_state.ppm_parameter_table = NULL;15901591if (0 != ptable3->usExtendendedHeaderOffset) {1592extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *)1593(((unsigned long)powerplay_table) +1594le16_to_cpu(ptable3->usExtendendedHeaderOffset));1595if ((extended_header->usPPMTableOffset > 0) &&1596le16_to_cpu(extended_header->usSize) >=1597SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) {1598table_offset = le16_to_cpu(extended_header->usPPMTableOffset);1599atom_ppm_table = (ATOM_PPLIB_PPM_Table *)1600(((unsigned long)powerplay_table) + table_offset);1601if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table))1602phm_cap_set(hwmgr->platform_descriptor.platformCaps,1603PHM_PlatformCaps_EnablePlatformPowerManagement);1604}1605}1606}1607return result;1608}16091610static int init_phase_shedding_table(struct pp_hwmgr *hwmgr,1611const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)1612{1613if (le16_to_cpu(powerplay_table->usTableSize) >=1614sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) {1615const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 =1616(const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table;16171618if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) {1619const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable =1620(ATOM_PPLIB_PhaseSheddingLimits_Table *)1621(((unsigned long)powerplay_table4) +1622le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset));1623struct phm_phase_shedding_limits_table *table;1624unsigned long i;162516261627table = kzalloc(struct_size(table, entries, ptable->ucNumEntries),1628GFP_KERNEL);1629if (!table)1630return -ENOMEM;16311632table->count = (unsigned long)ptable->ucNumEntries;16331634for (i = 0; i < table->count; i++) {1635table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage);1636table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16)1637| le16_to_cpu(ptable->entries[i].usSclkLow);1638table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16)1639| le16_to_cpu(ptable->entries[i].usMclkLow);1640}1641hwmgr->dyn_state.vddc_phase_shed_limits_table = table;1642}1643}16441645return 0;1646}16471648static int get_number_of_vce_state_table_entries(1649struct pp_hwmgr *hwmgr)1650{1651const ATOM_PPLIB_POWERPLAYTABLE *table =1652get_powerplay_table(hwmgr);1653const ATOM_PPLIB_VCE_State_Table *vce_table =1654get_vce_state_table(hwmgr, table);16551656if (vce_table)1657return vce_table->numEntries;16581659return 0;1660}16611662static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr,1663unsigned long i,1664struct amd_vce_state *vce_state,1665void **clock_info,1666unsigned long *flag)1667{1668const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr);16691670const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table);16711672unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table);16731674const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset);16751676const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) +1677le16_to_cpu(powerplay_table->usClockInfoArrayOffset));16781679const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i];16801681const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex];16821683unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F;16841685*flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX);16861687vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow);1688vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow);16891690*clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize));16911692return 0;1693}169416951696static int pp_tables_initialize(struct pp_hwmgr *hwmgr)1697{1698int result;1699const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table;17001701if (hwmgr->chip_id == CHIP_RAVEN)1702return 0;17031704hwmgr->need_pp_table_upload = true;17051706powerplay_table = get_powerplay_table(hwmgr);17071708result = init_powerplay_tables(hwmgr, powerplay_table);17091710PP_ASSERT_WITH_CODE((result == 0),1711"init_powerplay_tables failed", return result);17121713result = set_platform_caps(hwmgr,1714le32_to_cpu(powerplay_table->ulPlatformCaps));17151716PP_ASSERT_WITH_CODE((result == 0),1717"set_platform_caps failed", return result);17181719result = init_thermal_controller(hwmgr, powerplay_table);17201721PP_ASSERT_WITH_CODE((result == 0),1722"init_thermal_controller failed", return result);17231724result = init_overdrive_limits(hwmgr, powerplay_table);17251726PP_ASSERT_WITH_CODE((result == 0),1727"init_overdrive_limits failed", return result);17281729result = init_clock_voltage_dependency(hwmgr,1730powerplay_table);17311732PP_ASSERT_WITH_CODE((result == 0),1733"init_clock_voltage_dependency failed", return result);17341735result = init_dpm2_parameters(hwmgr, powerplay_table);17361737PP_ASSERT_WITH_CODE((result == 0),1738"init_dpm2_parameters failed", return result);17391740result = init_phase_shedding_table(hwmgr, powerplay_table);17411742PP_ASSERT_WITH_CODE((result == 0),1743"init_phase_shedding_table failed", return result);17441745return result;1746}17471748static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr)1749{1750if (hwmgr->chip_id == CHIP_RAVEN)1751return 0;17521753kfree(hwmgr->dyn_state.vddc_dependency_on_sclk);1754hwmgr->dyn_state.vddc_dependency_on_sclk = NULL;17551756kfree(hwmgr->dyn_state.vddci_dependency_on_mclk);1757hwmgr->dyn_state.vddci_dependency_on_mclk = NULL;17581759kfree(hwmgr->dyn_state.vddc_dependency_on_mclk);1760hwmgr->dyn_state.vddc_dependency_on_mclk = NULL;17611762kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk);1763hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL;17641765kfree(hwmgr->dyn_state.valid_mclk_values);1766hwmgr->dyn_state.valid_mclk_values = NULL;17671768kfree(hwmgr->dyn_state.valid_sclk_values);1769hwmgr->dyn_state.valid_sclk_values = NULL;17701771kfree(hwmgr->dyn_state.cac_leakage_table);1772hwmgr->dyn_state.cac_leakage_table = NULL;17731774kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table);1775hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL;17761777kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table);1778hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL;17791780kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table);1781hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL;17821783kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table);1784hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL;17851786kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table);1787hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL;17881789kfree(hwmgr->dyn_state.cac_dtp_table);1790hwmgr->dyn_state.cac_dtp_table = NULL;17911792kfree(hwmgr->dyn_state.ppm_parameter_table);1793hwmgr->dyn_state.ppm_parameter_table = NULL;17941795kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk);1796hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL;17971798return 0;1799}18001801const struct pp_table_func pptable_funcs = {1802.pptable_init = pp_tables_initialize,1803.pptable_fini = pp_tables_uninitialize,1804.pptable_get_number_of_vce_state_table_entries =1805get_number_of_vce_state_table_entries,1806.pptable_get_vce_state_table_entry =1807get_vce_state_table_entry,1808};1809181018111812