blob: 6642c8a96218cec9ec722a3d646da2d1e292b0e8 [file] [log] [blame]
/* $NoKeywords:$ */
/**
* @file
*
* Service procedure to initialize Integrated Info Table
*
*
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: AGESA
* @e sub-project: GNB
* @e \$Revision: 48452 $ @e \$Date: 2011-03-09 12:50:44 +0800 (Wed, 09 Mar 2011) $
*
*/
/*
*****************************************************************************
*
* Copyright (c) 2011, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Advanced Micro Devices, Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ***************************************************************************
*
*/
/*----------------------------------------------------------------------------------------
* M O D U L E S U S E D
*----------------------------------------------------------------------------------------
*/
#include "AGESA.h"
#include "Ids.h"
#include "amdlib.h"
#include "heapManager.h"
#include "Gnb.h"
#include "GnbFuseTable.h"
#include "GnbPcie.h"
#include "GnbGfx.h"
#include "GnbFuseTable.h"
#include "GnbGfxFamServices.h"
#include "GnbCommonLib.h"
#include "GfxPowerPlayTable.h"
#include "Filecode.h"
#define FILECODE PROC_GNB_MODULES_GNBGFXINITLIBV1_GFXPOWERPLAYTABLE_FILECODE
/*----------------------------------------------------------------------------------------
* D E F I N I T I O N S A N D M A C R O S
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------
* T Y P E D E F S A N D S T R U C T U R E S
*----------------------------------------------------------------------------------------
*/
/// Software state
typedef struct {
BOOLEAN Valid; ///< State valid
UINT16 Classification; ///< State classification
UINT32 CapsAndSettings; ///< State capability and settings
UINT16 Classification2; ///< State classification2
UINT32 Vclk; ///< UVD VCLK
UINT32 Dclk; ///< UVD DCLK
UINT8 NumberOfDpmStates; ///< Number of DPM states
UINT8 DpmSatesArray[MAX_NUM_OF_DPM_STATES]; ///< DPM state index array
} SW_STATE;
/// DPM state
typedef struct {
BOOLEAN Valid; ///< State valid
UINT32 Sclk; ///< Sclk in kHz
UINT8 Vid; ///< VID index
UINT16 Tdp; ///< Tdp limit
} DPM_STATE;
/*----------------------------------------------------------------------------------------
* P R O T O T Y P E S O F L O C A L F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
UINT16
GfxPowerPlayLocateTdp (
IN PP_FUSE_ARRAY *PpFuses,
IN UINT32 Sclk,
IN AMD_CONFIG_PARAMS *StdHeader
);
UINT8
GfxPowerPlayAddDpmState (
IN DPM_STATE *DpmStateArray,
IN UINT32 Sclk,
IN UINT8 Vid,
IN UINT16 Tdp
);
VOID
GfxPowerPlayAddDpmStateToSwState (
IN OUT SW_STATE *SwStateArray,
IN UINT8 DpmStateIndex
);
SW_STATE*
GfxPowerPlayCreateSwState (
IN OUT SW_STATE *SwStateArray
);
UINT8
GfxPowerPlayCreateDpmState (
IN DPM_STATE *DpmStateArray,
IN UINT32 Sclk,
IN UINT8 Vid,
IN UINT16 Tdp
);
UINT32
GfxPowerPlayCopyStateInfo (
IN OUT STATE_ARRAY *StateArray,
IN SW_STATE *SwStateArray,
IN AMD_CONFIG_PARAMS *StdHeader
);
UINT32
GfxPowerPlayCopyClockInfo (
IN CLOCK_INFO_ARRAY *ClockInfoArray,
IN DPM_STATE *DpmStateArray,
IN AMD_CONFIG_PARAMS *StdHeader
);
UINT32
GfxPowerPlayCopyNonClockInfo (
IN NON_CLOCK_INFO_ARRAY *NonClockInfoArray,
IN SW_STATE *SwStateArray,
IN AMD_CONFIG_PARAMS *StdHeader
);
BOOLEAN
GfxPowerPlayIsFusedStateValid (
IN UINT8 Index,
IN PP_FUSE_ARRAY *PpFuses,
IN GFX_PLATFORM_CONFIG *Gfx
);
UINT16
GfxPowerPlayGetClassificationFromFuses (
IN UINT8 Index,
IN PP_FUSE_ARRAY *PpFuses,
IN GFX_PLATFORM_CONFIG *Gfx
);
UINT16
GfxPowerPlayGetClassification2FromFuses (
IN UINT8 Index,
IN PP_FUSE_ARRAY *PpFuses,
IN GFX_PLATFORM_CONFIG *Gfx
);
VOID
GfxIntegratedDebugDumpPpTable (
IN ATOM_PPLIB_POWERPLAYTABLE3 *PpTable,
IN GFX_PLATFORM_CONFIG *Gfx
);
/*----------------------------------------------------------------------------------------*/
/**
* Locate existing tdp
*
*
* @param[in ] PpFuses Pointer to PP_FUSE_ARRAY
* @param[in] Sclk Sclk in 10kHz
* @param[in] StdHeader Standard configuration header
* @retval Tdp limit in DPM state array
*/
UINT16
GfxPowerPlayLocateTdp (
IN PP_FUSE_ARRAY *PpFuses,
IN UINT32 Sclk,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT8 Index;
UINT32 DpmIndex;
UINT32 DpmSclk;
UINT32 DeltaSclk;
UINT32 MinDeltaSclk;
DpmIndex = 0;
MinDeltaSclk = 0xFFFFFFFF;
for (Index = 0; Index < MAX_NUM_OF_FUSED_DPM_STATES; Index++) {
if (PpFuses->SclkDpmDid[Index] != 0) {
DpmSclk = GfxFmCalculateClock (PpFuses->SclkDpmDid[Index], StdHeader);
DeltaSclk = (DpmSclk > Sclk) ? (DpmSclk - Sclk) : (Sclk - DpmSclk);
if (DeltaSclk < MinDeltaSclk) {
MinDeltaSclk = MinDeltaSclk;
DpmIndex = Index;
}
}
}
return PpFuses->SclkDpmTdpLimit[DpmIndex];
}
/*----------------------------------------------------------------------------------------*/
/**
* Create new software state
*
*
* @param[in, out] SwStateArray Pointer to SW state array
* @retval Pointer to state entry in SW state array
*/
SW_STATE*
GfxPowerPlayCreateSwState (
IN OUT SW_STATE *SwStateArray
)
{
UINTN Index;
for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
if (SwStateArray[Index].Valid == FALSE) {
SwStateArray[Index].Valid = TRUE;
return &SwStateArray[Index];
}
}
return NULL;
}
/*----------------------------------------------------------------------------------------*/
/**
* Create new DPM state
*
*
* @param[in, out] DpmStateArray Pointer to DPM state array
* @param[in] Sclk SCLK in kHz
* @param[in] Vid Vid index
* @param[in] Tdp Tdp limit
* @retval Index of state entry in DPM state array
*/
UINT8
GfxPowerPlayCreateDpmState (
IN DPM_STATE *DpmStateArray,
IN UINT32 Sclk,
IN UINT8 Vid,
IN UINT16 Tdp
)
{
UINT8 Index;
for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
if (DpmStateArray[Index].Valid == FALSE) {
DpmStateArray[Index].Sclk = Sclk;
DpmStateArray[Index].Vid = Vid;
DpmStateArray[Index].Valid = TRUE;
DpmStateArray[Index].Tdp = Tdp;
return Index;
}
}
return 0;
}
/*----------------------------------------------------------------------------------------*/
/**
* Locate existing or Create new DPM state
*
*
* @param[in, out] DpmStateArray Pointer to DPM state array
* @param[in] Sclk SCLK in kHz
* @param[in] Vid Vid index
* @param[in] Tdp Tdp limit
* @retval Index of state entry in DPM state array
*/
UINT8
GfxPowerPlayAddDpmState (
IN DPM_STATE *DpmStateArray,
IN UINT32 Sclk,
IN UINT8 Vid,
IN UINT16 Tdp
)
{
UINT8 Index;
for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
if (DpmStateArray[Index].Valid && Sclk == DpmStateArray[Index].Sclk && Vid == DpmStateArray[Index].Vid) {
return Index;
}
}
return GfxPowerPlayCreateDpmState (DpmStateArray, Sclk, Vid, Tdp);
}
/*----------------------------------------------------------------------------------------*/
/**
* Add reference to DPM state for SW state
*
*
* @param[in, out] SwStateArray Pointer to SW state array
* @param[in] DpmStateIndex DPM state index
*/
VOID
GfxPowerPlayAddDpmStateToSwState (
IN OUT SW_STATE *SwStateArray,
IN UINT8 DpmStateIndex
)
{
SwStateArray->DpmSatesArray[SwStateArray->NumberOfDpmStates++] = DpmStateIndex;
}
/*----------------------------------------------------------------------------------------*/
/**
* Copy SW state info to PPTable
*
*
* @param[out] StateArray Pointer to PPtable SW state array
* @param[in] SwStateArray Pointer to SW state array
* @param[in] StdHeader Standard configuration header
*/
UINT32
GfxPowerPlayCopyStateInfo (
IN OUT STATE_ARRAY *StateArray,
IN SW_STATE *SwStateArray,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT8 Index;
UINT8 SwStateIndex;
ATOM_PPLIB_STATE_V2 *States;
States = &StateArray->States[0];
SwStateIndex = 0;
for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
if (SwStateArray[Index].Valid && SwStateArray[Index].NumberOfDpmStates != 0) {
States->nonClockInfoIndex = SwStateIndex;
States->ucNumDPMLevels = SwStateArray[Index].NumberOfDpmStates;
LibAmdMemCopy (
&States->ClockInfoIndex[0],
SwStateArray[Index].DpmSatesArray,
SwStateArray[Index].NumberOfDpmStates,
StdHeader
);
States = (ATOM_PPLIB_STATE_V2*) ((UINT8*) States + sizeof (ATOM_PPLIB_STATE_V2) + sizeof (UINT8) * (States->ucNumDPMLevels - 1));
SwStateIndex++;
}
}
StateArray->ucNumEntries = SwStateIndex;
return (UINT32) ((UINT8*) States - (UINT8*) StateArray);
}
/*----------------------------------------------------------------------------------------*/
/**
* Copy clock info to PPTable
*
*
* @param[out] ClockInfoArray Pointer to clock info array
* @param[in] DpmStateArray Pointer to DPM state array
* @param[in] StdHeader Standard configuration header
*/
UINT32
GfxPowerPlayCopyClockInfo (
IN CLOCK_INFO_ARRAY *ClockInfoArray,
IN DPM_STATE *DpmStateArray,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT8 Index;
UINT8 ClkStateIndex;
ClkStateIndex = 0;
for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
if (DpmStateArray[Index].Valid == TRUE) {
ClockInfoArray->ClockInfo[ClkStateIndex].ucEngineClockHigh = (UINT8) (DpmStateArray[Index].Sclk >> 16);
ClockInfoArray->ClockInfo[ClkStateIndex].usEngineClockLow = (UINT16) (DpmStateArray[Index].Sclk);
ClockInfoArray->ClockInfo[ClkStateIndex].vddcIndex = DpmStateArray[Index].Vid;
ClockInfoArray->ClockInfo[ClkStateIndex].tdpLimit = DpmStateArray[Index].Tdp;
ClkStateIndex++;
}
}
ClockInfoArray->ucNumEntries = ClkStateIndex;
ClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO);
return sizeof (CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO) * (ClkStateIndex) - sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO);
}
/*----------------------------------------------------------------------------------------*/
/**
* Copy non clock info to PPTable
*
*
* @param[out] NonClockInfoArray Pointer to PPtable Non clock array
* @param[in] SwStateArray Pointer to SW state array
* @param[in] StdHeader Standard configuration header
*/
UINT32
GfxPowerPlayCopyNonClockInfo (
IN NON_CLOCK_INFO_ARRAY *NonClockInfoArray,
IN SW_STATE *SwStateArray,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT8 Index;
UINT8 NonClkStateIndex;
NonClkStateIndex = 0;
for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
if (SwStateArray[Index].Valid && SwStateArray[Index].NumberOfDpmStates != 0) {
NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification = SwStateArray[Index].Classification;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulCapsAndSettings = SwStateArray[Index].CapsAndSettings;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification2 = SwStateArray[Index].Classification2;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulDCLK = SwStateArray[Index].Dclk;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulVCLK = SwStateArray[Index].Vclk;
NonClkStateIndex++;
}
}
NonClockInfoArray->ucNumEntries = NonClkStateIndex;
NonClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_NONCLOCK_INFO);
return sizeof (NON_CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_NONCLOCK_INFO) * NonClkStateIndex - sizeof (ATOM_PPLIB_NONCLOCK_INFO);
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if fused state valid
*
*
* @param[out] Index State index
* @param[in] PpFuses Pointer to fuse table
* @param[in] Gfx Gfx configuration info
* @retval TRUE State is valid
*/
BOOLEAN
GfxPowerPlayIsFusedStateValid (
IN UINT8 Index,
IN PP_FUSE_ARRAY *PpFuses,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
BOOLEAN Result;
Result = FALSE;
if (PpFuses->SclkDpmValid[Index] != 0) {
Result = TRUE;
if (PpFuses->PolicyLabel[Index] == POLICY_LABEL_BATTERY && (Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) == 0) {
Result = FALSE;
}
}
return Result;
}
/*----------------------------------------------------------------------------------------*/
/**
* Get SW state calssification from fuses
*
*
* @param[out] Index State index
* @param[in] PpFuses Pointer to fuse table
* @param[in] Gfx Gfx configuration info
* @retval State classification
*/
UINT16
GfxPowerPlayGetClassificationFromFuses (
IN UINT8 Index,
IN PP_FUSE_ARRAY *PpFuses,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
UINT16 Classification;
Classification = 0;
switch (PpFuses->PolicyFlags[Index]) {
case 0x1:
Classification |= ATOM_PPLIB_CLASSIFICATION_NONUVDSTATE;
break;
case 0x2:
Classification |= ATOM_PPLIB_CLASSIFICATION_UVDSTATE;
break;
case 0x4:
//Possible SD + HD state
break;
case 0x8:
Classification |= ATOM_PPLIB_CLASSIFICATION_HDSTATE;
break;
case 0x10:
Classification |= ATOM_PPLIB_CLASSIFICATION_SDSTATE;
break;
default:
break;
}
switch (PpFuses->PolicyLabel[Index]) {
case POLICY_LABEL_BATTERY:
Classification |= ATOM_PPLIB_CLASSIFICATION_UI_BATTERY;
break;
case POLICY_LABEL_PERFORMANCE:
Classification |= ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE;
break;
default:
break;
}
return Classification;
}
/*----------------------------------------------------------------------------------------*/
/**
* Get SW state calssification2 from fuses
*
*
* @param[out] Index State index
* @param[in] PpFuses Pointer to fuse table
* @param[in] Gfx Gfx configuration info
* @retval State classification2
*/
UINT16
GfxPowerPlayGetClassification2FromFuses (
IN UINT8 Index,
IN PP_FUSE_ARRAY *PpFuses,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
UINT16 Classification2;
Classification2 = 0;
switch (PpFuses->PolicyFlags[Index]) {
case 0x4:
Classification2 |= ATOM_PPLIB_CLASSIFICATION2_MVC;
break;
default:
break;
}
return Classification2;
}
/*----------------------------------------------------------------------------------------*/
/**
* Build PP table
*
*
* @param[out] Buffer Buffer to create PP table
* @param[in] Gfx Gfx configuration info
* @retval AGESA_SUCCESS
* @retval AGESA_ERROR
*/
AGESA_STATUS
GfxPowerPlayBuildTable (
OUT VOID *Buffer,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
ATOM_PPLIB_POWERPLAYTABLE3 *PpTable;
SW_STATE SwStateArray [MAX_NUM_OF_SW_STATES];
DPM_STATE DpmStateArray[MAX_NUM_OF_DPM_STATES];
UINT8 ClkStateIndex;
UINT8 DpmFuseIndex;
UINT8 Index;
UINT32 StateArrayLength;
UINT32 ClockArrayLength;
UINT32 NonClockArrayLength;
SW_STATE *State;
PP_FUSE_ARRAY *PpFuses;
UINT32 Sclk;
PpFuses = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, GnbLibGetHeader (Gfx));
ASSERT (PpFuses != NULL);
if (PpFuses == NULL) {
return AGESA_ERROR;
}
PpTable = (ATOM_PPLIB_POWERPLAYTABLE3 *) Buffer;
LibAmdMemFill (SwStateArray, 0x00, sizeof (SwStateArray), GnbLibGetHeader (Gfx));
LibAmdMemFill (DpmStateArray, 0x00, sizeof (DpmStateArray), GnbLibGetHeader (Gfx));
// Create States from Fuses
for (Index = 0; Index < MAX_NUM_OF_FUSED_SW_STATES; Index++) {
if (GfxPowerPlayIsFusedStateValid (Index, PpFuses, Gfx)) {
//Create new SW State;
State = GfxPowerPlayCreateSwState (SwStateArray);
State->Classification = GfxPowerPlayGetClassificationFromFuses (Index, PpFuses, Gfx);
State->Classification2 = GfxPowerPlayGetClassification2FromFuses (Index, PpFuses, Gfx);
if ((State->Classification & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_UVDSTATE)) != 0 ||
(State->Classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) != 0) {
State->Vclk = (PpFuses->VclkDid[PpFuses->VclkDclkSel[Index]] != 0) ? GfxFmCalculateClock (PpFuses->VclkDid[PpFuses->VclkDclkSel[Index]], GnbLibGetHeader (Gfx)) : 0;
State->Dclk = (PpFuses->DclkDid[PpFuses->VclkDclkSel[Index]] != 0) ? GfxFmCalculateClock (PpFuses->DclkDid[PpFuses->VclkDclkSel[Index]], GnbLibGetHeader (Gfx)) : 0;
}
if ((State->Classification & 0x7) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) {
if (Gfx->AbmSupport != 0) {
State->CapsAndSettings |= ATOM_PPLIB_ENABLE_VARIBRIGHT;
}
if (Gfx->DynamicRefreshRate != 0) {
State->CapsAndSettings |= ATOM_PPLIB_ENABLE_DRR;
}
}
for (DpmFuseIndex = 0; DpmFuseIndex < MAX_NUM_OF_FUSED_DPM_STATES; DpmFuseIndex++) {
if ((PpFuses->SclkDpmValid[Index] & (1 << DpmFuseIndex)) != 0 ) {
Sclk = (PpFuses->SclkDpmDid[DpmFuseIndex] != 0) ? GfxFmCalculateClock (PpFuses->SclkDpmDid[DpmFuseIndex], GnbLibGetHeader (Gfx)) : 0;
if (Sclk != 0) {
ClkStateIndex = GfxPowerPlayAddDpmState (DpmStateArray, Sclk, PpFuses->SclkDpmVid[DpmFuseIndex], PpFuses->SclkDpmTdpLimit[DpmFuseIndex]);
GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
}
}
}
}
}
// Create Boot State
State = GfxPowerPlayCreateSwState (SwStateArray);
State->Classification = ATOM_PPLIB_CLASSIFICATION_BOOT;
Sclk = 200 * 100;
ClkStateIndex = GfxPowerPlayAddDpmState (DpmStateArray, Sclk, 0, GfxPowerPlayLocateTdp (PpFuses, Sclk, GnbLibGetHeader (Gfx)));
GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
// Create Thermal State
State = GfxPowerPlayCreateSwState (SwStateArray);
State->Classification = ATOM_PPLIB_CLASSIFICATION_THERMAL;
Sclk = GfxFmCalculateClock (PpFuses->SclkThermDid, GnbLibGetHeader (Gfx));
ClkStateIndex = GfxPowerPlayAddDpmState (DpmStateArray, Sclk, 0, GfxPowerPlayLocateTdp (PpFuses, Sclk, GnbLibGetHeader (Gfx)));
GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
//Copy state info to actual PP table
StateArrayLength = GfxPowerPlayCopyStateInfo (
&PpTable->StateArray,
SwStateArray,
GnbLibGetHeader (Gfx)
);
ClockArrayLength = GfxPowerPlayCopyClockInfo (
(CLOCK_INFO_ARRAY*) ((UINT8 *)&PpTable->StateArray + StateArrayLength),
DpmStateArray,
GnbLibGetHeader (Gfx)
);
NonClockArrayLength = GfxPowerPlayCopyNonClockInfo (
(NON_CLOCK_INFO_ARRAY*) ((UINT8 *)&PpTable->StateArray + StateArrayLength + ClockArrayLength),
SwStateArray,
GnbLibGetHeader (Gfx)
);
//Fill static info
PpTable->sHeader.ucTableFormatRevision = 6;
PpTable->sHeader.ucTableContentRevision = 1;
PpTable->ucDataRevision = PpFuses->PPlayTableRev;
PpTable->sThermalController.ucType = ATOM_PP_THERMALCONTROLLER_SUMO;
PpTable->sThermalController.ucFanParameters = ATOM_PP_FANPARAMETERS_NOFAN;
if ((Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) != 0) {
PpTable->ulPlatformCaps |= ATOM_PP_PLATFORM_CAP_POWERPLAY;
}
PpTable->usStateArrayOffset = offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray);
PpTable->usClockInfoArrayOffset = (USHORT) (offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray) + StateArrayLength);
PpTable->usNonClockInfoArrayOffset = (USHORT) (offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray) + StateArrayLength + ClockArrayLength);
PpTable->sHeader.usStructureSize = (USHORT) (offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray) + StateArrayLength + ClockArrayLength + NonClockArrayLength);
PpTable->usFormatID = 7;
GNB_DEBUG_CODE (
GfxIntegratedDebugDumpPpTable (PpTable, Gfx);
);
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/**
* Dump PP table
*
*
*
* @param[in] PpTable Power Play table
* @param[in] Gfx Gfx configuration info
*/
VOID
GfxIntegratedDebugDumpPpTable (
IN ATOM_PPLIB_POWERPLAYTABLE3 *PpTable,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
UINTN Index;
UINTN DpmIndex;
ATOM_PPLIB_STATE_V2 *StatesPtr;
NON_CLOCK_INFO_ARRAY *NonClockInfoArrayPtr;
CLOCK_INFO_ARRAY *ClockInfoArrayPtr;
IDS_HDT_CONSOLE (GFX_MISC, " < --- Power Play Table ------ > \n");
IDS_HDT_CONSOLE (GFX_MISC, " Table Revision = %d\n", PpTable->ucDataRevision
);
StatesPtr = PpTable->StateArray.States;
NonClockInfoArrayPtr = (NON_CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usNonClockInfoArrayOffset);
ClockInfoArrayPtr = (CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usClockInfoArrayOffset);
for (Index = 0; Index < PpTable->StateArray.ucNumEntries; Index++) {
IDS_HDT_CONSOLE (GFX_MISC, " State #%d\n", Index + 1
);
IDS_HDT_CONSOLE (GFX_MISC, " Classification 0x%x\n",
NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].usClassification
);
IDS_HDT_CONSOLE (GFX_MISC, " Classification2 0x%x\n",
NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].usClassification2
);
IDS_HDT_CONSOLE (GFX_MISC, " VCLK = %dkHz\n",
NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].ulVCLK
);
IDS_HDT_CONSOLE (GFX_MISC, " DCLK = %dkHz\n",
NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].ulDCLK
);
IDS_HDT_CONSOLE (GFX_MISC, " DPM State Index: ");
for (DpmIndex = 0; DpmIndex < StatesPtr->ucNumDPMLevels; DpmIndex++) {
IDS_HDT_CONSOLE (GFX_MISC, "%d ",
StatesPtr->ClockInfoIndex [DpmIndex]
);
}
IDS_HDT_CONSOLE (GFX_MISC, "\n");
StatesPtr = (ATOM_PPLIB_STATE_V2 *) ((UINT8 *) StatesPtr + sizeof (ATOM_PPLIB_STATE_V2) + StatesPtr->ucNumDPMLevels - 1);
}
for (Index = 0; Index < ClockInfoArrayPtr->ucNumEntries; Index++) {
UINT32 Sclk;
Sclk = ClockInfoArrayPtr->ClockInfo[Index].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[Index].ucEngineClockHigh << 16);
IDS_HDT_CONSOLE (GFX_MISC, " DPM State #%d\n",
Index
);
IDS_HDT_CONSOLE (GFX_MISC, " SCLK = %d\n",
ClockInfoArrayPtr->ClockInfo[Index].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[Index].ucEngineClockHigh << 16)
);
IDS_HDT_CONSOLE (GFX_MISC, " VID index = %d\n",
ClockInfoArrayPtr->ClockInfo[Index].vddcIndex
);
IDS_HDT_CONSOLE (GFX_MISC, " tdpLimit = %d\n",
ClockInfoArrayPtr->ClockInfo[Index].tdpLimit
);
}
}