diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbGfxIntTableV3/GfxPwrPlayTable.c')
-rw-r--r-- | src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbGfxIntTableV3/GfxPwrPlayTable.c | 1233 |
1 files changed, 1233 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbGfxIntTableV3/GfxPwrPlayTable.c b/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbGfxIntTableV3/GfxPwrPlayTable.c new file mode 100644 index 0000000000..4e83c44359 --- /dev/null +++ b/src/vendorcode/amd/agesa/f16kb/Proc/GNB/Modules/GnbGfxIntTableV3/GfxPwrPlayTable.c @@ -0,0 +1,1233 @@ +/* $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 < (sizeof (PpWorkspace->PpF1s->VceFlags) / + sizeof (PpWorkspace->PpF1s->VceFlags[0])) ; + Index++) { + UsedStateBitmap |= PpWorkspace->PpF1s->VceFlags[Index]; + for (VceStateIndex = 0; + VceStateIndex < (sizeof (PpWorkspace->VceStateArray) / + sizeof (PpWorkspace->VceStateArray[0])); + 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 < (sizeof (PpWorkspace->VceStateArray) / sizeof (PpWorkspace->VceStateArray[0])); + 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"); + +} |