AGESA_STATUS GfxFmCalculateClock ( IN UINT8 Did, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 MainPllFreq10kHz; MainPllFreq10kHz = GfxLibGetMainPllFreq (StdHeader) * 100; return GfxLibCalculateClk (Did, MainPllFreq10kHz); }
VOID GfxIntegratedInfoInitDispclkTable ( IN PP_FUSE_ARRAY *PpFuseArray, IN ATOM_INTEGRATED_SYSTEM_INFO_V6 *IntegratedInfoTable, IN GFX_PLATFORM_CONFIG *Gfx ) { UINTN Index; for (Index = 0; Index < 4; Index++) { if (PpFuseArray->DisplclkDid[Index] != 0) { IntegratedInfoTable->sDISPCLK_Voltage[Index].ulMaximumSupportedCLK = GfxLibCalculateClk ( PpFuseArray->DisplclkDid[Index], IntegratedInfoTable->ulDentistVCOFreq ); IntegratedInfoTable->sDISPCLK_Voltage[Index].ulVoltageIndex = (ULONG) Index; } } }
AGESA_STATUS NbFmInitLclkDpmRcActivity ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; PP_FUSE_ARRAY *PpFuseArray; INT8 Index; UINTN LclkState; Status = AGESA_SUCCESS; IDS_HDT_CONSOLE (GNB_TRACE, "NbFmInitLclkDpmRcActivity F14 Enter\n"); PpFuseArray = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, StdHeader); if (PpFuseArray != NULL) { UINT32 ActivityThreshold [8]; UINT16 SamplingPeriod [10]; UINT8 LclkScalingDid [4]; UINT8 LclkScalingVid [4]; UINT32 LclkDpmValid; UINT32 MainPllVcoKHz; LibAmdMemFill (&ActivityThreshold[0], 0, sizeof (ActivityThreshold), StdHeader); LibAmdMemFill (&SamplingPeriod[0], 0, sizeof (SamplingPeriod), StdHeader); MainPllVcoKHz = GfxLibGetMainPllFreq (StdHeader) * 100; LclkDpmValid = 0; LclkState = 7; for (Index = 3; Index >= 0; Index--) { if (PpFuseArray->LclkDpmValid [Index] != 0) { // Set valid DPM state LclkDpmValid |= (1 << (LclkState)); // Set LCLK scaling DID LclkScalingDid [7 - LclkState] = PpFuseArray->LclkDpmDid [Index]; // Set LCLK scaling VID LclkScalingVid [7 - LclkState] = PpFuseArray->LclkDpmVid [Index]; // Set sampling period SamplingPeriod [LclkState] = 0xC350; // Changed from 0xC350 to 0x1388 for DPM 0 if (Index == 0) { SamplingPeriod [LclkState] = 0x1388; } // Set activity threshold from BKDG: // Raising -- ActivityThreshold [LclkState] = ((102 * (GfxLibCalculateClk (LclkScalingDid [7 - LclkState], MainPllVcoKHz) / 100)) - 10) / 10; // Lowering -- ActivityThreshold [LclkState] |= (((407 * (GfxLibCalculateClk (LclkScalingDid [7 - LclkState], MainPllVcoKHz) / 100)) + 99) / 10) << 16; // For ON specific enable LCLK DPM : ActivityThreshold [LclkState] = LclkDpmActivityThresholdTable [Index]; IDS_HDT_CONSOLE (GNB_TRACE, "Fused State Index:%d LCLK DPM State [%d]: LclkScalingDid - 0x%x, ActivityThreshold - 0x%x, SamplingPeriod - 0x%x\n", Index, LclkState, LclkScalingDid [7 - LclkState], ActivityThreshold [LclkState], SamplingPeriod [LclkState] ); LclkState--; } } if (LclkState != 7) { SMUx33_STRUCT SMUx33; SMUx0B_x8434_STRUCT SMUx0B_x8434; FCRxFF30_01E4_STRUCT FCRxFF30_01E4; UINT8 CurrentUnit; UINT16 FinalUnit; UINT16 FinalPeriod; UINT32 Freq; UINT32 FreqDelta; UINT32 Value; ASSERT (LclkScalingDid [0] != 0); FreqDelta = 0xffffffff; FinalPeriod = 0; FinalUnit = 0; Freq = (65535 * 100 * 100) / GfxLibCalculateClk (LclkScalingDid [0], MainPllVcoKHz); for (CurrentUnit = 0; CurrentUnit < 16; CurrentUnit++) { UINT32 CurrentFreqDelta; UINT32 CurrentPeriod; UINT32 Temp; Temp = GnbLibPowerOf (4, CurrentUnit); CurrentPeriod = Freq / Temp; if (CurrentPeriod <= 0xFFFF) { CurrentFreqDelta = Freq - Temp * CurrentPeriod; if (FreqDelta > CurrentFreqDelta) { FinalUnit = CurrentUnit; FinalPeriod = (UINT16) CurrentPeriod; FreqDelta = CurrentFreqDelta; } } } //Process to enablement LCLK DPM States NbSmuIndirectRead (SMUx33_ADDRESS, AccessWidth32, &SMUx33.Value, StdHeader); SMUx33.Field.BusyCntSel = 0x3; SMUx33.Field.LclkActMonUnt = FinalUnit; SMUx33.Field.LclkActMonPrd = FinalPeriod; NbSmuIndirectWrite (SMUx33_ADDRESS, AccessS3SaveWidth32, &SMUx33.Value, StdHeader); SMUx0B_x8434.Value = 0; SMUx0B_x8434.Field.LclkDpmType = 0x1; SMUx0B_x8434.Field.LclkDpmEn = 0x1; SMUx0B_x8434.Field.LclkTimerPeriod = 0x0C350; SMUx0B_x8434.Field.LclkTimerPrescalar = 0x1; NbSmuRcuRegisterWrite ( SMUx0B_x8434_ADDRESS, &SMUx0B_x8434.Value, 1, TRUE, StdHeader ); NbSmuRcuRegisterWrite ( 0x84AC, &LclkDpmCacTable[0], sizeof (LclkDpmCacTable) / sizeof (UINT32), TRUE, StdHeader ); // Program activity threshold IDS_HDT_CONSOLE (GNB_TRACE, "ActivityThreshold[4] - 0x%x ActivityThreshold[5] - 0x%x ActivityThreshold[6] - 0x%x ActivityThreshold[7] - 0x%x\n", ActivityThreshold[4], ActivityThreshold[5], ActivityThreshold[6], ActivityThreshold [7] ); NbSmuRcuRegisterWrite ( SMUx0B_x8470_ADDRESS, &ActivityThreshold[4], 4, TRUE, StdHeader ); // Program sampling period for (Index = 0; Index < (sizeof (SamplingPeriod) / sizeof (SamplingPeriod[0])); Index = Index + 2) { UINT16 Temp; Temp = SamplingPeriod[Index]; SamplingPeriod[Index] = SamplingPeriod[Index + 1]; SamplingPeriod[Index + 1] = Temp; } IDS_HDT_CONSOLE (GNB_TRACE, "SamplingPeriod[4] - 0x%x SamplingPeriod[5] - 0x%x SamplingPeriod[6] - 0x%x SamplingPeriod[7] - 0x%x \n", SamplingPeriod[4], SamplingPeriod[5], SamplingPeriod[6], SamplingPeriod[7] ); NbSmuRcuRegisterWrite ( SMUx0B_x8440_ADDRESS, (UINT32*) &SamplingPeriod[4], 2, TRUE, StdHeader ); // Program LCK scaling DID NbSmuRcuRegisterWrite ( SMUx0B_x848C_ADDRESS, (UINT32*) &LclkScalingDid[0], 1, TRUE, StdHeader ); // Program LCK scaling VID NbSmuRcuRegisterWrite ( SMUx0B_x8498_ADDRESS, (UINT32*) &LclkScalingVid[0], 1, TRUE, StdHeader ); // Program valid LCLK DPM states LclkDpmValid = NbFmDpmStateBootupInit (LclkDpmValid, StdHeader); NbSmuRcuRegisterWrite ( SMUx0B_x8490_ADDRESS, &LclkDpmValid, 1, TRUE, StdHeader ); //Setup Activity Monitor Coefficients Value = (0x24 << SMUx35_DownTrendCoef_OFFSET) | (0x24 << SMUx35_UpTrendCoef_OFFSET); NbSmuIndirectWrite (SMUx35_ADDRESS, AccessS3SaveWidth32, &Value, StdHeader); Value = (0x22 << SMUx35_DownTrendCoef_OFFSET) | (0x22 << SMUx35_UpTrendCoef_OFFSET); for (Index = SMUx37_ADDRESS; Index <= SMUx51_ADDRESS; Index = Index + 2) { NbSmuIndirectWrite (Index, AccessS3SaveWidth32, &Value, StdHeader); } // Enable LCLK DPM as voltage client NbSmuSrbmRegisterRead (FCRxFF30_01E4_ADDRESS, &FCRxFF30_01E4.Value, StdHeader); FCRxFF30_01E4.Field.VoltageChangeEn = 0x1; NbSmuSrbmRegisterWrite (FCRxFF30_01E4_ADDRESS, &FCRxFF30_01E4.Value, TRUE, StdHeader); // Start LCLK service NbSmuServiceRequest (0x8, TRUE, StdHeader); } } else { IDS_HDT_CONSOLE (GNB_TRACE, " ERROR! Cannot locate fuse table\n"); Status = AGESA_ERROR; } IDS_HDT_CONSOLE (GNB_TRACE, "NbFmInitLclkDpmRcActivity F14 Exit [0x%x]\n", Status); return Status; }
VOID GfxIntegratedInfoInitSclkTable ( IN PP_FUSE_ARRAY *PpFuseArray, IN ATOM_INTEGRATED_SYSTEM_INFO_V6 *IntegratedInfoTable, IN GFX_PLATFORM_CONFIG *Gfx ) { UINTN Index; UINTN TargetIndex; UINTN ValidSclkStateMask; UINT8 TempDID; UINT8 SclkVidArray[4]; UINTN AvailSclkIndex; ATOM_AVAILABLE_SCLK_LIST *AvailSclkList; BOOLEAN Sorting; AvailSclkList = &IntegratedInfoTable->sAvail_SCLK[0]; GnbLibPciRead ( MAKE_SBDFO ( 0, 0, 0x18, 3, D18F3x15C_ADDRESS), AccessWidth32, &SclkVidArray[0], GnbLibGetHeader (Gfx) ); AvailSclkIndex = 0; for (Index = 0; Index < MAX_NUM_OF_FUSED_DPM_STATES; Index++) { if (PpFuseArray->SclkDpmDid[Index] != 0) { AvailSclkList[AvailSclkIndex].ulSupportedSCLK = GfxLibCalculateClk (PpFuseArray->SclkDpmDid[Index], IntegratedInfoTable->ulDentistVCOFreq); AvailSclkList[AvailSclkIndex].usVoltageIndex = PpFuseArray->SclkDpmVid[Index]; AvailSclkList[AvailSclkIndex].usVoltageID = SclkVidArray [PpFuseArray->SclkDpmVid[Index]]; AvailSclkIndex++; } } //Sort by VoltageIndex & ulSupportedSCLK do { Sorting = FALSE; for (Index = 0; Index < (AvailSclkIndex - 1); Index++) { ATOM_AVAILABLE_SCLK_LIST Temp; BOOLEAN Exchange; Exchange = FALSE; if (AvailSclkList[Index].usVoltageIndex > AvailSclkList[Index + 1].usVoltageIndex) { Exchange = TRUE; } if ((AvailSclkList[Index].usVoltageIndex == AvailSclkList[Index + 1].usVoltageIndex) && (AvailSclkList[Index].ulSupportedSCLK > AvailSclkList[Index + 1].ulSupportedSCLK)) { Exchange = TRUE; } if (Exchange) { Sorting = TRUE; LibAmdMemCopy (&Temp, &AvailSclkList[Index], sizeof (ATOM_AVAILABLE_SCLK_LIST), GnbLibGetHeader (Gfx)); LibAmdMemCopy (&AvailSclkList[Index], &AvailSclkList[Index + 1], sizeof (ATOM_AVAILABLE_SCLK_LIST), GnbLibGetHeader (Gfx)); LibAmdMemCopy (&AvailSclkList[Index + 1], &Temp, sizeof (ATOM_AVAILABLE_SCLK_LIST), GnbLibGetHeader (Gfx)); } } } while (Sorting); if (PpFuseArray->GpuBoostCap == 1) { IntegratedInfoTable->SclkDpmThrottleMargin = PpFuseArray->SclkDpmThrottleMargin; IntegratedInfoTable->SclkDpmTdpLimitPG = PpFuseArray->SclkDpmTdpLimitPG; IntegratedInfoTable->EnableBoost = PpFuseArray->GpuBoostCap; IntegratedInfoTable->SclkDpmBoostMargin = PpFuseArray->SclkDpmBoostMargin; IntegratedInfoTable->SclkDpmTdpLimitBoost = (PpFuseArray->SclkDpmTdpLimit)[5]; IntegratedInfoTable->ulBoostEngineCLock = GfxFmCalculateClock ((PpFuseArray->SclkDpmDid)[5], GnbLibGetHeader (Gfx)); IntegratedInfoTable->ulBoostVid_2bit = (PpFuseArray->SclkDpmVid)[5]; ValidSclkStateMask = 0; TargetIndex = 0; for (Index = 0; Index < 6; Index++) { ValidSclkStateMask |= (PpFuseArray->SclkDpmValid)[Index]; } TempDID = 0x7F; for (Index = 0; Index < 6; Index++) { if ((ValidSclkStateMask & ((UINTN)1 << Index)) != 0) { if ((PpFuseArray->SclkDpmDid)[Index] <= TempDID) { TempDID = (PpFuseArray->SclkDpmDid)[Index]; TargetIndex = Index; } } } IntegratedInfoTable->GnbTdpLimit = (PpFuseArray->SclkDpmTdpLimit)[TargetIndex]; } }