coreboot/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbGfxIntTableV3/GfxPwrPlayTable.c

1232 lines
46 KiB
C

/* $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: 67269 $ @e \$Date: 2012-03-26 02:53:08 -0500 (Mon, 26 Mar 2012) $
*
*/
/*
*****************************************************************************
*
* Copyright (c) 2008 - 2013, 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 "GnbF1Table.h"
#include "GnbPcie.h"
#include "GnbGfx.h"
#include "GnbGfxFamServices.h"
#include "GnbCommonLib.h"
#include "GfxPwrPlayTable.h"
#include "Filecode.h"
#define FILECODE PROC_GNB_MODULES_GNBGFXINTTABLEV3_GFXPWRPLAYTABLE_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 SW_STATE_fld4;
UINT32 SW_STATE_fld5;
UINT8 SW_STATE_fld6;
UINT8 SW_STATE_fld7[10];
} SW_STATE;
typedef struct {
BOOLEAN Valid;
UINT32 GfxPwrPlayTable120_STRUCT_fld1;
UINT8 Vid;
UINT16 Tdp;
} GfxPwrPlayTable120_STRUCT;
typedef struct {
GFX_PLATFORM_CONFIG *Gfx;
ATOM_PPLIB_POWERPLAYTABLE4 *PpTable;
PP_F1_ARRAY_V2 *PpF1s;
SW_STATE SwStateArray [MAX_NUM_OF_SW_STATES]; ///< SW state array
GfxPwrPlayTable120_STRUCT PP_WORKSPACE_V2_fld4[10];
UINT8 NumOfClockVoltageLimitEnties; ///
ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD VceClockVoltageLimitArray[MAX_NUM_OF_VCE_CLK_STATES];
UINT8 NumOfVceClockEnties;
GfxPwrPlayTable204_STRUCT VceClockInfoArray[MAX_NUM_OF_VCE_CLK_STATES];
UINT8 NumOfVceStateEntries;
ATOM_PPLIB_VCE_STATE_RECORD VceStateArray[MAX_NUM_OF_VCE_STATES]; ///< VCE state array
UINT8 NumOfUvdClkVoltLimitEntries; ///
ATOM_PPLIB_UVD_CLK_VOLT_LIMIT_RECORD UvdClkVoltLimitArray[MAX_NUM_OF_UVD_CLK_STATES];
UINT8 NumOfUvdClockEntries;
GfxPwrPlayTable261_STRUCT UvdClockInfoArray[MAX_NUM_OF_UVD_CLK_STATES];
UINT8 PP_WORKSPACE_V2_fld15; ///
ATOM_PPLIB_SAMCLK_VOLT_LIMIT_RECORD PP_WORKSPACE_V2_fld16[MAX_NUM_OF_SAMCLK_STATES];
UINT8 PP_WORKSPACE_V2_fld17; ///
GfxPwrPlayTable310_STRUCT PP_WORKSPACE_V2_fld18[5];
} PP_WORKSPACE_V2;
/*----------------------------------------------------------------------------------------
* 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
*----------------------------------------------------------------------------------------
*/
VOID
GfxIntDebugDumpPpTable (
IN ATOM_PPLIB_POWERPLAYTABLE4 *PpTable,
IN GFX_PLATFORM_CONFIG *Gfx
);
/*----------------------------------------------------------------------------------------*/
/**
* Create new software state
*
*
* @param[in, out] PpWorkspace PP workspace
* @retval Pointer to state entry in SW state array
*/
STATIC SW_STATE *
GfxPwrPlayCreateSwState (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINTN Index;
for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
if (PpWorkspace->SwStateArray[Index].Valid == FALSE) {
PpWorkspace->SwStateArray[Index].Valid = TRUE;
return &(PpWorkspace->SwStateArray[Index]);
}
}
return NULL;
}
/*----------------------------------------------------------------------------------------*/
STATIC UINT8
GfxPwrPlayTable192_fun (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT32 fv1,
IN UINT8 Vid
)
{
UINT8 Index;
for (Index = 0; Index < 10; Index++) {
if (PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Valid == FALSE) {
PpWorkspace->PP_WORKSPACE_V2_fld4[Index].GfxPwrPlayTable120_STRUCT_fld1 = fv1;
PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Vid = Vid;
PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Valid = TRUE;
PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Tdp = 0;
return Index;
}
}
return 0;
}
/*----------------------------------------------------------------------------------------*/
STATIC UINT8
GfxPwrPlayTable224_fun (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT32 fv1,
IN UINT8 Vid
)
{
UINT8 Index;
for (Index = 0; Index < 10; Index++) {
if (PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Valid &&
fv1 == PpWorkspace->PP_WORKSPACE_V2_fld4[Index].GfxPwrPlayTable120_STRUCT_fld1 &&
Vid == PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Vid) {
return Index;
}
}
Index = GfxPwrPlayTable192_fun (PpWorkspace, fv1, Vid);
return Index;
}
STATIC VOID
GfxPwrPlayTable256_fun (
IN OUT SW_STATE *SwStateArray,
IN UINT8 DpmStateIndex
)
{
SwStateArray->SW_STATE_fld7[SwStateArray->SW_STATE_fld6++] = DpmStateIndex;
}
/*----------------------------------------------------------------------------------------*/
/**
* Copy SW state info to PPTable
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachStateInfoBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINT8 Index;
UINT8 SwStateIndex;
STATE_ARRAY *StateArray;
ATOM_PPLIB_STATE_V2 *States;
StateArray = (STATE_ARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
States = &StateArray->States[0];
SwStateIndex = 0;
for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
if (PpWorkspace->SwStateArray[Index].Valid && PpWorkspace->SwStateArray[Index].SW_STATE_fld6 != 0) {
States->nonClockInfoIndex = SwStateIndex;
States->ATOM_PPLIB_STATE_V2_fld0 = PpWorkspace->SwStateArray[Index].SW_STATE_fld6;
LibAmdMemCopy (
&States->ClockInfoIndex[0],
PpWorkspace->SwStateArray[Index].SW_STATE_fld7,
PpWorkspace->SwStateArray[Index].SW_STATE_fld6,
GnbLibGetHeader (PpWorkspace->Gfx)
);
States = (ATOM_PPLIB_STATE_V2*) ((UINT8*) States + sizeof (ATOM_PPLIB_STATE_V2) + sizeof (UINT8) * (States->ATOM_PPLIB_STATE_V2_fld0 - 1));
SwStateIndex++;
}
}
StateArray->ucNumEntries = SwStateIndex;
PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize + (USHORT) ((UINT8 *) States - (UINT8 *) StateArray);
return StateArray;
}
/*----------------------------------------------------------------------------------------*/
/**
* Copy clock info to PPTable
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachClockInfoBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
CLOCK_INFO_ARRAY *ClockInfoArray;
UINT8 Index;
UINT8 ClkStateIndex;
ClkStateIndex = 0;
ClockInfoArray = (CLOCK_INFO_ARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
for (Index = 0; Index < 10; Index++) {
if (PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Valid == TRUE) {
ClockInfoArray->ClockInfo[ClkStateIndex].ucEngineClockHigh = (UINT8) (PpWorkspace->PP_WORKSPACE_V2_fld4[Index].GfxPwrPlayTable120_STRUCT_fld1 >> 16);
ClockInfoArray->ClockInfo[ClkStateIndex].usEngineClockLow = (UINT16) (PpWorkspace->PP_WORKSPACE_V2_fld4[Index].GfxPwrPlayTable120_STRUCT_fld1);
ClockInfoArray->ClockInfo[ClkStateIndex].vddcIndex = PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Vid;
ClockInfoArray->ClockInfo[ClkStateIndex].ATOM_PPLIB_SUMO_CLOCK_INFO_fld3 = PpWorkspace->PP_WORKSPACE_V2_fld4[Index].Tdp;
ClkStateIndex++;
}
}
ClockInfoArray->ucNumEntries = ClkStateIndex;
ClockInfoArray->ucEntrySize = sizeof (GfxPwrPlayTable143_STRUCT);
PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (CLOCK_INFO_ARRAY) + sizeof (GfxPwrPlayTable143_STRUCT) * ClkStateIndex - sizeof (GfxPwrPlayTable143_STRUCT);
return ClockInfoArray;
}
/*----------------------------------------------------------------------------------------*/
/**
* Copy non clock info to PPTable
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachNonClockInfoBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
NON_CLOCK_INFO_ARRAY *NonClockInfoArray;
UINT8 Index;
UINT8 NonClkStateIndex;
NonClockInfoArray = (NON_CLOCK_INFO_ARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
NonClkStateIndex = 0;
for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
if (PpWorkspace->SwStateArray[Index].Valid && PpWorkspace->SwStateArray[Index].SW_STATE_fld6 != 0) {
NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification = PpWorkspace->SwStateArray[Index].Classification;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulCapsAndSettings = PpWorkspace->SwStateArray[Index].CapsAndSettings;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification2 = PpWorkspace->SwStateArray[Index].Classification2;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].ATOM_PPLIB_NONCLOCK_INFO_fld7 = PpWorkspace->SwStateArray[Index].SW_STATE_fld5;
NonClockInfoArray->NonClockInfo[NonClkStateIndex].ATOM_PPLIB_NONCLOCK_INFO_fld6 = PpWorkspace->SwStateArray[Index].SW_STATE_fld4;
NonClkStateIndex++;
}
}
NonClockInfoArray->ucNumEntries = NonClkStateIndex;
NonClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_NONCLOCK_INFO);
PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (NON_CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_NONCLOCK_INFO) * NonClkStateIndex - sizeof (ATOM_PPLIB_NONCLOCK_INFO);
return NonClockInfoArray;
}
/*----------------------------------------------------------------------------------------*/
/**
* Check if state valid
*
*
* @param[out] Index State index
* @param[in] PpF1s Pointer
* @param[in] Gfx Gfx configuration info
* @retval TRUE State is valid
*/
STATIC BOOLEAN
GfxPwrPlayIsF1dStateValid (
IN UINT8 Index,
IN PP_F1_ARRAY_V2 *PpF1s,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
BOOLEAN Result;
Result = FALSE;
if ((PpF1s->PP_FUSE_ARRAY_V2_fld37 & (1 << Index)) || (PpF1s->PP_FUSE_ARRAY_V2_fld38 & (1 << Index))) {
Result = TRUE;
}
return Result;
}
/*----------------------------------------------------------------------------------------*/
STATIC VOID
GfxPwrPlayTable437_fun (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINT8 ClkStateIndex;
UINT8 DpmF1Index;
UINT32 fv2;
SW_STATE *State;
PP_F1_ARRAY_V2 *PpF1s;
PpF1s = PpWorkspace->PpF1s;
// Create Battery state
State = GfxPwrPlayCreateSwState (PpWorkspace);
State->Classification = ATOM_PPLIB_CLASSIFICATION_UI_BATTERY;
State->Classification2 = 0;
State->SW_STATE_fld4 = 0;
State->SW_STATE_fld5 = 0;
if (PpWorkspace->Gfx->AbmSupport != 0) {
State->CapsAndSettings |= ATOM_PPLIB_ENABLE_VARIBRIGHT;
}
if (PpWorkspace->Gfx->DynamicRefreshRate != 0) {
State->CapsAndSettings |= ATOM_PPLIB_ENABLE_DRR;
}
for (DpmF1Index = 0; DpmF1Index < 5; DpmF1Index++) {
if (PpF1s->PP_FUSE_ARRAY_V2_fld38 & (1 << DpmF1Index)) {
fv2 = (PpF1s->PP_FUSE_ARRAY_V2_fld33[DpmF1Index] != 0) ?
GfxFmCalculateClock (PpF1s->PP_FUSE_ARRAY_V2_fld33[DpmF1Index],
GnbLibGetHeader (PpWorkspace->Gfx)) : 0;
if (fv2 != 0) {
ClkStateIndex = GfxPwrPlayTable224_fun (PpWorkspace, fv2, PpF1s->PP_FUSE_ARRAY_V2_fld32[DpmF1Index]);
GfxPwrPlayTable256_fun (State, ClkStateIndex);
}
}
}
// Create Performance state
State = GfxPwrPlayCreateSwState (PpWorkspace);
State->Classification = ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE;
State->Classification2 = 0;
State->SW_STATE_fld4 = 0;
State->SW_STATE_fld5 = 0;
// Loop through fused DPM states and find those that go with Performance
for (DpmF1Index = 0; DpmF1Index < 5; DpmF1Index++) {
if (PpF1s->PP_FUSE_ARRAY_V2_fld37 & (1 << DpmF1Index)) {
fv2 = (PpF1s->PP_FUSE_ARRAY_V2_fld33[DpmF1Index] != 0) ?
GfxFmCalculateClock (PpF1s->PP_FUSE_ARRAY_V2_fld33[DpmF1Index],
GnbLibGetHeader (PpWorkspace->Gfx)) : 0;
if (fv2 != 0) {
ClkStateIndex = GfxPwrPlayTable224_fun (PpWorkspace, fv2, PpF1s->PP_FUSE_ARRAY_V2_fld32[DpmF1Index]);
GfxPwrPlayTable256_fun (State, ClkStateIndex);
}
}
}
// Create Boot State
State = GfxPwrPlayCreateSwState (PpWorkspace);
State->Classification = ATOM_PPLIB_CLASSIFICATION_BOOT;
fv2 = 200 * 100;
ClkStateIndex = GfxPwrPlayTable224_fun (PpWorkspace, fv2, 0);
GfxPwrPlayTable256_fun (State, ClkStateIndex);
}
/*----------------------------------------------------------------------------------------*/
STATIC UINT8
GfxPwrPlayAddEclkState (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT32 Eclk
)
{
UINT8 Index;
USHORT EclkLow;
UCHAR EclkHigh;
EclkLow = (USHORT) (Eclk & 0xffff);
EclkHigh = (UCHAR) (Eclk >> 16);
for (Index = 0; Index < PpWorkspace->NumOfVceClockEnties; Index++) {
if (PpWorkspace->VceClockInfoArray[Index].ucECClkHigh == EclkHigh && PpWorkspace->VceClockInfoArray[Index].usECClkLow == EclkLow) {
return Index;
}
}
PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].ucECClkHigh = EclkHigh;
PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].usECClkLow = EclkLow;
PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].GfxPwrPlayTable204_STRUCT_fld1 = EclkHigh;
PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].GfxPwrPlayTable204_STRUCT_fld0 = EclkLow;
return PpWorkspace->NumOfVceClockEnties++;
}
/*----------------------------------------------------------------------------------------*/
/**
* Add ECLK state
*
*
* @param[in, out] PpWorkspace PP workspace
* @param[in] EclkIndex ECLK index
* @param[in] Vid Vid index
* @retval Index of state entry in Eclk Voltage record array
*/
STATIC UINT8
GfxPwrPlayAddEclkVoltageRecord (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT8 EclkIndex,
IN UINT8 Vid
)
{
UINT8 Index;
for (Index = 0; Index < PpWorkspace->NumOfClockVoltageLimitEnties; Index++) {
if (PpWorkspace->VceClockVoltageLimitArray[Index].ucVCEClockInfoIndex == EclkIndex) {
return Index;
}
}
PpWorkspace->VceClockVoltageLimitArray[PpWorkspace->NumOfClockVoltageLimitEnties].ucVCEClockInfoIndex = EclkIndex;
PpWorkspace->VceClockVoltageLimitArray[PpWorkspace->NumOfClockVoltageLimitEnties].usVoltage = Vid;
return PpWorkspace->NumOfClockVoltageLimitEnties++;
}
/*----------------------------------------------------------------------------------------*/
STATIC UINT8
GfxPwrPlayTable588_fun (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT32 fv1,
IN UINT32 fv2
)
{
UINT8 Index;
USHORT v1;
UCHAR v2;
USHORT v3;
UCHAR v4;
v1 = (USHORT) (fv1 & 0xffff);
v2 = (UCHAR) (fv1 >> 16);
v3 = (USHORT) (fv2 & 0xffff);
v4 = (UCHAR) (fv2 >> 16);
for (Index = 0; Index < PpWorkspace->NumOfUvdClockEntries; Index++) {
if (PpWorkspace->UvdClockInfoArray[Index].GfxPwrPlayTable261_STRUCT_fld1 == v2 &&
PpWorkspace->UvdClockInfoArray[Index].GfxPwrPlayTable261_STRUCT_fld0 == v1) {
return Index;
}
}
PpWorkspace->UvdClockInfoArray[PpWorkspace->NumOfUvdClockEntries].GfxPwrPlayTable261_STRUCT_fld1 = v2;
PpWorkspace->UvdClockInfoArray[PpWorkspace->NumOfUvdClockEntries].GfxPwrPlayTable261_STRUCT_fld0 = v1;
PpWorkspace->UvdClockInfoArray[PpWorkspace->NumOfUvdClockEntries].GfxPwrPlayTable261_STRUCT_fld3 = v4;
PpWorkspace->UvdClockInfoArray[PpWorkspace->NumOfUvdClockEntries].GfxPwrPlayTable261_STRUCT_fld2 = v3;
return PpWorkspace->NumOfUvdClockEntries++;
}
/*----------------------------------------------------------------------------------------*/
/**
* Add Uvd voltage record
*
*
* @param[in, out] PpWorkspace PP workspace
* @param[in] ClkIndex CLK index
* @param[in] Vid Vid index
* @retval Index of state entry in Eclk Voltage record array
*/
STATIC UINT8
GfxPwrPlayAddUvdVoltageRecord (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT8 ClkIndex,
IN UINT8 Vid
)
{
UINT8 Index;
for (Index = 0; Index < PpWorkspace->NumOfUvdClkVoltLimitEntries; Index++) {
if (PpWorkspace->UvdClkVoltLimitArray[Index].ucUVDClockInfoIndex == ClkIndex) {
return Index;
}
}
PpWorkspace->UvdClkVoltLimitArray[PpWorkspace->NumOfUvdClkVoltLimitEntries].ucUVDClockInfoIndex =
ClkIndex;
PpWorkspace->UvdClkVoltLimitArray[PpWorkspace->NumOfUvdClkVoltLimitEntries].usVoltage = Vid;
return PpWorkspace->NumOfUvdClkVoltLimitEntries++;
}
/*----------------------------------------------------------------------------------------*/
/**
* Add Samu voltage record
*
*
* @param[in, out] PpWorkspace PP workspace
* @param[in] Vid Vid
* @param[in] Samclk CLK associated with the Vid
* @retval Index of state entry in Voltage record array
*/
STATIC UINT8
GfxPwrPlayAddSamuVoltageRecord (
IN OUT PP_WORKSPACE_V2 *PpWorkspace,
IN UINT8 Vid,
IN UINT32 Samclk
)
{
UINT8 Index;
USHORT SamclkLow;
UCHAR SamclkHigh;
SamclkLow = (USHORT) (Samclk & 0xffff);
SamclkHigh = (UCHAR) (Samclk >> 16);
for (Index = 0; Index < PpWorkspace->PP_WORKSPACE_V2_fld15; Index++) {
if ((PpWorkspace->PP_WORKSPACE_V2_fld16[Index].usSAMClockHigh == SamclkHigh) &&
(PpWorkspace->PP_WORKSPACE_V2_fld16[Index].usSAMClockLow == SamclkLow) &&
(PpWorkspace->PP_WORKSPACE_V2_fld16[Index].usVoltage == Vid)
) {
return Index;
}
}
PpWorkspace->PP_WORKSPACE_V2_fld16[PpWorkspace->PP_WORKSPACE_V2_fld15].usSAMClockHigh =
SamclkHigh;
PpWorkspace->PP_WORKSPACE_V2_fld16[PpWorkspace->PP_WORKSPACE_V2_fld15].usSAMClockLow =
SamclkLow;
PpWorkspace->PP_WORKSPACE_V2_fld16[PpWorkspace->PP_WORKSPACE_V2_fld15].usVoltage = Vid;
return PpWorkspace->PP_WORKSPACE_V2_fld15++;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach extended header
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachExtendedHeaderBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_EXTENDEDHEADER *ExtendedHeader;
ExtendedHeader = (ATOM_PPLIB_EXTENDEDHEADER *)
((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
ExtendedHeader->usSize = sizeof (ATOM_PPLIB_EXTENDEDHEADER);
PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (ATOM_PPLIB_EXTENDEDHEADER);
return ExtendedHeader;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach Vce Rev Block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachVceTableRevBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_VCE_TABLE *VceTable;
VceTable = (ATOM_PPLIB_VCE_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
VceTable->revid = 0;
PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (ATOM_PPLIB_VCE_TABLE);
return VceTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach VCE clock info block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachVceClockInfoBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
VCECLOCKINFOARRAY *VceClockInfoArray;
VceClockInfoArray = (VCECLOCKINFOARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
VceClockInfoArray->ucNumEntries = PpWorkspace->NumOfVceClockEnties;
LibAmdMemCopy (
&VceClockInfoArray->entries[0],
&PpWorkspace->VceClockInfoArray[0],
VceClockInfoArray->ucNumEntries * sizeof (GfxPwrPlayTable204_STRUCT),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (VCECLOCKINFOARRAY) +
VceClockInfoArray->ucNumEntries * sizeof (GfxPwrPlayTable204_STRUCT) -
sizeof (GfxPwrPlayTable204_STRUCT);
return VceClockInfoArray;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach VCE voltage limit block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachVceVoltageLimitBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *VceClockVoltageLimitTable;
VceClockVoltageLimitTable = (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
VceClockVoltageLimitTable->numEntries = PpWorkspace->NumOfClockVoltageLimitEnties;
LibAmdMemCopy (
&VceClockVoltageLimitTable->entries[0],
&PpWorkspace->VceClockVoltageLimitArray[0],
VceClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize =
PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE) +
VceClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD) -
sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD);
return VceClockVoltageLimitTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach VCE state block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachVceStateTableBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_VCE_STATE_TABLE *VceStateTable;
VceStateTable = (ATOM_PPLIB_VCE_STATE_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
VceStateTable->numEntries = PpWorkspace->NumOfVceStateEntries;
LibAmdMemCopy (
&VceStateTable->entries[0],
&PpWorkspace->VceStateArray[0],
VceStateTable->numEntries * sizeof (ATOM_PPLIB_VCE_STATE_RECORD),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (ATOM_PPLIB_VCE_STATE_TABLE) +
VceStateTable->numEntries * sizeof (ATOM_PPLIB_VCE_STATE_RECORD) -
sizeof (ATOM_PPLIB_VCE_STATE_RECORD);
return VceStateTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach Uvd Rev Block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachUvdTableRevBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_UVD_TABLE *UvdTable;
UvdTable = (ATOM_PPLIB_UVD_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
UvdTable->revid = 0;
PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (ATOM_PPLIB_UVD_TABLE);
return UvdTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach UVD clock info block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachUvdClockInfoBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
GfxPwrPlayTable267_STRUCT *UvdClockInfoArray;
UvdClockInfoArray = (GfxPwrPlayTable267_STRUCT *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
UvdClockInfoArray->ucNumEntries = PpWorkspace->NumOfUvdClockEntries;
LibAmdMemCopy (
&UvdClockInfoArray->entries[0],
&PpWorkspace->UvdClockInfoArray[0],
UvdClockInfoArray->ucNumEntries * sizeof (GfxPwrPlayTable261_STRUCT),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (GfxPwrPlayTable267_STRUCT) +
UvdClockInfoArray->ucNumEntries * sizeof (GfxPwrPlayTable261_STRUCT) -
sizeof (GfxPwrPlayTable261_STRUCT);
return UvdClockInfoArray;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach UVD voltage limit block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachUvdVoltageLimitBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UVD_CLK_VOLT_LIMIT_TABLE *UvdClockVoltageLimitTable;
UvdClockVoltageLimitTable = (UVD_CLK_VOLT_LIMIT_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
UvdClockVoltageLimitTable->numEntries = PpWorkspace->NumOfUvdClkVoltLimitEntries;
LibAmdMemCopy (
&UvdClockVoltageLimitTable->entries[0],
&PpWorkspace->UvdClkVoltLimitArray[0],
UvdClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_UVD_CLK_VOLT_LIMIT_RECORD),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize =
PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (UVD_CLK_VOLT_LIMIT_TABLE) +
UvdClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_UVD_CLK_VOLT_LIMIT_RECORD) -
sizeof (ATOM_PPLIB_UVD_CLK_VOLT_LIMIT_RECORD);
return UvdClockVoltageLimitTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach SAMU Rev Block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachSamuTableRevBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_SAMU_TABLE *VceTable;
VceTable = (ATOM_PPLIB_SAMU_TABLE *) ((UINT8 *) PpWorkspace->PpTable +
PpWorkspace->PpTable->sHeader.usStructureSize);
VceTable->revid = 0;
PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (ATOM_PPLIB_SAMU_TABLE);
return VceTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach SAMU voltage limit block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayAttachSamuVoltageLimitBlock (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
ATOM_PPLIB_SAMCLK_VOLT_LIMIT_TABLE *SamuClockVoltageLimitTable;
SamuClockVoltageLimitTable = (ATOM_PPLIB_SAMCLK_VOLT_LIMIT_TABLE *)
((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
SamuClockVoltageLimitTable->numEntries = PpWorkspace->PP_WORKSPACE_V2_fld15;
LibAmdMemCopy (
&SamuClockVoltageLimitTable->entries[0],
&PpWorkspace->PP_WORKSPACE_V2_fld16[0],
SamuClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_SAMCLK_VOLT_LIMIT_RECORD),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize =
PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (ATOM_PPLIB_SAMCLK_VOLT_LIMIT_TABLE) +
SamuClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_SAMCLK_VOLT_LIMIT_RECORD) -
sizeof (ATOM_PPLIB_SAMCLK_VOLT_LIMIT_RECORD);
return SamuClockVoltageLimitTable;
}
/*----------------------------------------------------------------------------------------*/
/**
* Attach Sclk Volt Dep Block
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID *
GfxPwrPlayTable956_fun (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
GfxPwrPlayTable316_STRUCT *v0;
v0 = (GfxPwrPlayTable316_STRUCT *)
((UINT8 *) PpWorkspace->PpTable +
PpWorkspace->PpTable->sHeader.usStructureSize);
v0->numEntries = PpWorkspace->PP_WORKSPACE_V2_fld17;
LibAmdMemCopy (
&v0->entries[0],
&PpWorkspace->PP_WORKSPACE_V2_fld18[0],
5 * sizeof (GfxPwrPlayTable310_STRUCT),
GnbLibGetHeader (PpWorkspace->Gfx)
);
PpWorkspace->PpTable->sHeader.usStructureSize =
PpWorkspace->PpTable->sHeader.usStructureSize +
sizeof (GfxPwrPlayTable316_STRUCT) +
v0->numEntries * sizeof (GfxPwrPlayTable310_STRUCT) -
sizeof (GfxPwrPlayTable310_STRUCT);
return v0;
}
/*----------------------------------------------------------------------------------------*/
/**
* Build VCE state info
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID
GfxPwrPlayBuildVceStateTable (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINT8 Index;
UINT8 VceStateIndex;
UINT8 Vid;
UINT32 Eclk;
UINT32 v4;
UINT8 UsedStateBitmap;
UsedStateBitmap = 0;
// build used state
for (Index = 0;
Index < ARRAY_SIZE(PpWorkspace->PpF1s->VceFlags);
Index++) {
UsedStateBitmap |= PpWorkspace->PpF1s->VceFlags[Index];
for (VceStateIndex = 0;
VceStateIndex < ARRAY_SIZE(PpWorkspace->VceStateArray);
VceStateIndex++) {
if ((PpWorkspace->PpF1s->VceFlags[Index] & (1 << VceStateIndex)) != 0) {
v4 = GfxFmCalculateClock (PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld33[PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld16[Index]],
GnbLibGetHeader (PpWorkspace->Gfx));
Vid = PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld32[PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld16[Index]];
PpWorkspace->VceStateArray[VceStateIndex].ucClockInfoIndex =
GfxPwrPlayTable224_fun (PpWorkspace, v4, Vid);
if (PpWorkspace->PpF1s->VceMclk) {
PpWorkspace->VceStateArray[VceStateIndex].ucClockInfoIndex |=
(PpWorkspace->PpF1s->VceMclk << 6);
}
Eclk = GfxFmCalculateClock (PpWorkspace->PpF1s->EclkDid[Index],
GnbLibGetHeader (PpWorkspace->Gfx));
PpWorkspace->VceStateArray[VceStateIndex].ucVCEClockInfoIndex =
GfxPwrPlayAddEclkState (PpWorkspace, Eclk);
GfxPwrPlayAddEclkVoltageRecord (PpWorkspace,
PpWorkspace->VceStateArray[VceStateIndex].ucVCEClockInfoIndex, Vid);
PpWorkspace->NumOfVceStateEntries++;
}
}
}
//build unused states
for (VceStateIndex = 0;
VceStateIndex < ARRAY_SIZE(PpWorkspace->VceStateArray);
VceStateIndex++) {
if ((UsedStateBitmap & (1 << VceStateIndex)) == 0) {
PpWorkspace->VceStateArray[VceStateIndex].ucClockInfoIndex = 0;
PpWorkspace->VceStateArray[VceStateIndex].ucVCEClockInfoIndex = GfxPwrPlayAddEclkState (PpWorkspace, 0);
PpWorkspace->NumOfVceStateEntries++;
}
}
}
/*----------------------------------------------------------------------------------------*/
STATIC VOID
GfxPwrPlayBuildUvdClockTable (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINT8 Index;
UINT8 Vid;
UINT32 v2;
UINT32 v3;
UINT8 UsedStateBitmap;
UINT8 UvdIndex;
UsedStateBitmap = 0;
// build used state
for (Index = 0; Index < MAX_NUM_OF_UVD_CLK_STATES ; Index++) {
if (GfxPwrPlayIsF1dStateValid (Index, PpWorkspace->PpF1s, PpWorkspace->Gfx)) {
Vid = PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld32[Index];
v2 = GfxFmCalculateClock (PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld1[Index],
GnbLibGetHeader (PpWorkspace->Gfx));
v3 = GfxFmCalculateClock (PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld2[Index],
GnbLibGetHeader (PpWorkspace->Gfx));
UvdIndex = GfxPwrPlayTable588_fun (PpWorkspace, v2, v3);
GfxPwrPlayAddUvdVoltageRecord (PpWorkspace,
UvdIndex, Vid);
}
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Build SAMU info
*
*
* @param[in, out] PpWorkspace PP workspace
*/
STATIC VOID
GfxPwrPlayBuildSamuTable (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINT8 SamuIndex;
UINT8 Vid;
UINT32 Samuclk;
UINT8 UsedStateBitmap;
UsedStateBitmap = 0;
// build used state
for (SamuIndex = 0; SamuIndex < MAX_NUM_OF_SAMCLK_STATES; SamuIndex++) {
if (GfxPwrPlayIsF1dStateValid (SamuIndex, PpWorkspace->PpF1s, PpWorkspace->Gfx)) {
Vid = PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld32[SamuIndex];
Samuclk = GfxFmCalculateClock (PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld34[SamuIndex],
GnbLibGetHeader (PpWorkspace->Gfx));
GfxPwrPlayAddSamuVoltageRecord (PpWorkspace, Vid, Samuclk);
}
}
}
/*----------------------------------------------------------------------------------------*/
STATIC VOID
GfxPwrPlayTable1122_fun (
IN OUT PP_WORKSPACE_V2 *PpWorkspace
)
{
UINT8 v0;
UINT8 Vid;
UINT32 v2;
USHORT v3;
UCHAR v4;
// build the table
for (v0 = 0; v0 < 5; v0++) {
Vid = PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld32[v0];
v2 = GfxFmCalculateClock (PpWorkspace->PpF1s->PP_FUSE_ARRAY_V2_fld33[v0],
GnbLibGetHeader (PpWorkspace->Gfx));
ASSERT (Vid != 0)
ASSERT (v2 != 0)
v3 = (USHORT) (v2 & 0xffff);
v4 = (UCHAR) (v2 >> 16);
PpWorkspace->PP_WORKSPACE_V2_fld18[v0].GfxPwrPlayTable310_fld2 = Vid;
PpWorkspace->PP_WORKSPACE_V2_fld18[v0].GfxPwrPlayTable310_fld1 = v4;
PpWorkspace->PP_WORKSPACE_V2_fld18[v0].GfxPwrPlayTable310_fld0 = v3;
PpWorkspace->PP_WORKSPACE_V2_fld17++;
}
}
/*----------------------------------------------------------------------------------------*/
/**
* 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
GfxPwrPlayBuildTable (
OUT VOID *Buffer,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
PP_WORKSPACE_V2 PpWorkspace;
VOID *BlockPtr;
LibAmdMemFill (&PpWorkspace, 0x00, sizeof (PP_WORKSPACE_V2), GnbLibGetHeader (Gfx));
PpWorkspace.PpF1s = GnbLocateHeapBuffer (AMD_PP_F1_TABLE_HANDLE, GnbLibGetHeader (Gfx));
ASSERT (PpWorkspace.PpF1s != NULL);
if (PpWorkspace.PpF1s == NULL) {
return AGESA_ERROR;
}
PpWorkspace.PpTable = (ATOM_PPLIB_POWERPLAYTABLE4 *) Buffer;
PpWorkspace.Gfx = Gfx;
//Fill static info
PpWorkspace.PpTable->sHeader.ucTableFormatRevision = 6;
PpWorkspace.PpTable->sHeader.ucTableContentRevision = 1;
PpWorkspace.PpTable->ucDataRevision = PpWorkspace.PpF1s->PPlayTableRev;
PpWorkspace.PpTable->sThermalController.ucType = ATOM_PP_THERMALCONTROLLER_KV;
PpWorkspace.PpTable->sThermalController.ucFanParameters = ATOM_PP_FANPARAMETERS_NOFAN;
PpWorkspace.PpTable->sHeader.usStructureSize = sizeof (ATOM_PPLIB_POWERPLAYTABLE4);
PpWorkspace.PpTable->usTableSize = sizeof (ATOM_PPLIB_POWERPLAYTABLE4);
PpWorkspace.PpTable->usFormatID = 0x13;
if ((Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) != 0) {
PpWorkspace.PpTable->ulPlatformCaps |= ATOM_PP_PLATFORM_CAP_POWERPLAY;
}
GfxPwrPlayTable437_fun (&PpWorkspace);
// Fill Eclk state info
if (PpWorkspace.PpF1s->PP_FUSE_ARRAY_V2_fld13) {
GfxPwrPlayBuildVceStateTable (&PpWorkspace);
GfxPwrPlayBuildUvdClockTable (&PpWorkspace);
GfxPwrPlayBuildSamuTable (&PpWorkspace);
GfxPwrPlayTable1122_fun (&PpWorkspace);
}
//Copy state info to actual PP table
BlockPtr = GfxPwrPlayAttachStateInfoBlock (&PpWorkspace);
PpWorkspace.PpTable->usStateArrayOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
BlockPtr = GfxPwrPlayAttachClockInfoBlock (&PpWorkspace);
PpWorkspace.PpTable->usClockInfoArrayOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
BlockPtr = GfxPwrPlayAttachNonClockInfoBlock (&PpWorkspace);
PpWorkspace.PpTable->usNonClockInfoArrayOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
if (PpWorkspace.PpF1s->PP_FUSE_ARRAY_V2_fld13) {
ATOM_PPLIB_EXTENDEDHEADER *ExtendedHeader;
ExtendedHeader =
(ATOM_PPLIB_EXTENDEDHEADER *) GfxPwrPlayAttachExtendedHeaderBlock (&PpWorkspace);
PpWorkspace.PpTable->usExtendendedHeaderOffset =
(USHORT) ((UINT8 *) ExtendedHeader - (UINT8 *) (PpWorkspace.PpTable));
BlockPtr = GfxPwrPlayAttachVceTableRevBlock (&PpWorkspace);
ExtendedHeader->usVCETableOffset =
(USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
GfxPwrPlayAttachVceClockInfoBlock (&PpWorkspace);
GfxPwrPlayAttachVceVoltageLimitBlock (&PpWorkspace);
GfxPwrPlayAttachVceStateTableBlock (&PpWorkspace);
BlockPtr = GfxPwrPlayAttachUvdTableRevBlock (&PpWorkspace);
ExtendedHeader->usUVDTableOffset =
(USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
GfxPwrPlayAttachUvdClockInfoBlock (&PpWorkspace);
GfxPwrPlayAttachUvdVoltageLimitBlock (&PpWorkspace);
BlockPtr = GfxPwrPlayAttachSamuTableRevBlock (&PpWorkspace);
ExtendedHeader->usSAMUTableOffset =
(USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
GfxPwrPlayAttachSamuVoltageLimitBlock (&PpWorkspace);
BlockPtr = GfxPwrPlayTable956_fun (&PpWorkspace);
PpWorkspace.PpTable->ATOM_PPLIB_POWERPLAYTABLE4_fld17 =
(USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
IDS_HDT_CONSOLE (GNB_TRACE, "ExtendedHeader \n");
IDS_HDT_CONSOLE (GNB_TRACE, " VceTableOffset = %04x\n", ExtendedHeader->usVCETableOffset);
IDS_HDT_CONSOLE (GNB_TRACE, " UvdTableOffset = %04x\n", ExtendedHeader->usUVDTableOffset);
IDS_HDT_CONSOLE (GNB_TRACE, " SamTableOffset = %04x\n", ExtendedHeader->usSAMUTableOffset);
IDS_HDT_CONSOLE (GNB_TRACE, "\n");
}
GNB_DEBUG_CODE (
GfxIntDebugDumpPpTable (PpWorkspace.PpTable, Gfx);
);
return AGESA_SUCCESS;
}
/*----------------------------------------------------------------------------------------*/
/**
* Dump PP table
*
*
*
* @param[in] PpTable Power Play table
* @param[in] Gfx Gfx configuration info
*/
VOID
GfxIntDebugDumpPpTable (
IN ATOM_PPLIB_POWERPLAYTABLE4 *PpTable,
IN GFX_PLATFORM_CONFIG *Gfx
)
{
UINTN Index;
STATE_ARRAY *StateArray;
ATOM_PPLIB_STATE_V2 *StatesPtr;
NON_CLOCK_INFO_ARRAY *NonClockInfoArrayPtr;
CLOCK_INFO_ARRAY *ClockInfoArrayPtr;
ATOM_PPLIB_EXTENDEDHEADER *ExtendedHeader;
ATOM_PPLIB_VCE_STATE_TABLE *VceStateTable;
ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *VceClockVoltageLimitTable;
VCECLOCKINFOARRAY *VceClockInfoArray;
GfxPwrPlayTable267_STRUCT *UvdClockInfoArray;
UVD_CLK_VOLT_LIMIT_TABLE *UvdClockVoltLimitTable;
ATOM_PPLIB_SAMCLK_VOLT_LIMIT_TABLE *SamuClockVoltLimitTable;
UINT8 EclkIndex;
IDS_HDT_CONSOLE (GFX_MISC, " < --- Power Play Table ------ > \n");
IDS_HDT_CONSOLE (GFX_MISC, " Table Revision = %d\n", PpTable->ucDataRevision);
StateArray = (STATE_ARRAY *) ((UINT8 *) PpTable + PpTable->usStateArrayOffset);
StatesPtr = StateArray->States;
NonClockInfoArrayPtr = (NON_CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usNonClockInfoArrayOffset);
ClockInfoArrayPtr = (CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usClockInfoArrayOffset);
IDS_HDT_CONSOLE (GFX_MISC, " < --- SW State Table ---------> \n");
for (Index = 0; Index < 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, "\n");
StatesPtr = (ATOM_PPLIB_STATE_V2 *) ((UINT8 *) StatesPtr + sizeof (ATOM_PPLIB_STATE_V2) + StatesPtr->ATOM_PPLIB_STATE_V2_fld0 - 1);
}
if (PpTable->usExtendendedHeaderOffset != 0) {
ExtendedHeader = (ATOM_PPLIB_EXTENDEDHEADER *) ((UINT8 *) PpTable +
PpTable->usExtendendedHeaderOffset);
IDS_HDT_CONSOLE (GNB_TRACE, "ExtendedHeader = %08x\n", ExtendedHeader);
VceClockInfoArray = (VCECLOCKINFOARRAY *) ((UINT8 *) PpTable +
ExtendedHeader->usVCETableOffset + sizeof (ATOM_PPLIB_VCE_TABLE));
VceClockVoltageLimitTable =
(ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *) ((UINT8 *) VceClockInfoArray +
sizeof (VCECLOCKINFOARRAY) +
VceClockInfoArray->ucNumEntries * sizeof (GfxPwrPlayTable204_STRUCT) -
sizeof (GfxPwrPlayTable204_STRUCT));
VceStateTable =
(ATOM_PPLIB_VCE_STATE_TABLE *) ((UINT8 *) VceClockVoltageLimitTable +
sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE) +
VceClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD) -
sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD));
UvdClockInfoArray =
(GfxPwrPlayTable267_STRUCT *) ((UINT8 *) PpTable + ExtendedHeader->usUVDTableOffset +
sizeof (ATOM_PPLIB_UVD_TABLE));
UvdClockVoltLimitTable =
(UVD_CLK_VOLT_LIMIT_TABLE *) ((UINT8 *) UvdClockInfoArray + sizeof (GfxPwrPlayTable267_STRUCT) +
UvdClockInfoArray->ucNumEntries * sizeof (GfxPwrPlayTable261_STRUCT) -
sizeof (GfxPwrPlayTable261_STRUCT));
SamuClockVoltLimitTable =
(ATOM_PPLIB_SAMCLK_VOLT_LIMIT_TABLE *)
((UINT8 *) PpTable + ExtendedHeader->usSAMUTableOffset + sizeof (ATOM_PPLIB_SAMU_TABLE));
IDS_HDT_CONSOLE (GFX_MISC, " < --- VCE State Table [%d]--> \n", VceStateTable->numEntries);
IDS_HDT_CONSOLE (GFX_MISC, " < --- VCE Voltage Record Table ---> \n");
for (Index = 0; Index < VceClockVoltageLimitTable->numEntries; Index++) {
EclkIndex = VceClockVoltageLimitTable->entries[Index].ucVCEClockInfoIndex;
IDS_HDT_CONSOLE (GFX_MISC, " VCE Voltage Record #%d\n", Index
);
IDS_HDT_CONSOLE (GFX_MISC, " ECLK = %d\n",
VceClockInfoArray->entries[EclkIndex].usECClkLow | (VceClockInfoArray->entries[EclkIndex].ucECClkHigh << 16)
);
IDS_HDT_CONSOLE (GFX_MISC, " VID index = %d\n",
VceClockVoltageLimitTable->entries[Index].usVoltage
);
}
IDS_HDT_CONSOLE (GFX_MISC, " < --- SAMU Voltage Record Table ---> \n");
for (Index = 0; Index < SamuClockVoltLimitTable->numEntries; Index++) {
IDS_HDT_CONSOLE (GFX_MISC, " SAMU Voltage Record #%d\n", Index
);
IDS_HDT_CONSOLE (GFX_MISC, " SAMCLK = %d\n",
SamuClockVoltLimitTable->entries[Index].usSAMClockLow |
(SamuClockVoltLimitTable->entries[Index].usSAMClockHigh << 16)
);
IDS_HDT_CONSOLE (GFX_MISC, " VID index = %d\n",
SamuClockVoltLimitTable->entries[Index].usVoltage
);
}
}
IDS_HDT_CONSOLE (GFX_MISC, " PplayDumpExit\n");
}