| /* $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"); |
| |
| } |