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