blob: 7cb69fd3743860d7f2c8beb3c42337e74bfdda31 [file] [log] [blame]
zbao7d94cf92012-07-02 14:19:14 +08001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * Service procedure to initialize Integrated Info Table
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
12 * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
13 *
14 */
15/*
16*****************************************************************************
17*
Siyuan Wang641f00c2013-06-08 11:50:55 +080018 * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc.
19 * All rights reserved.
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
zbao7d94cf92012-07-02 14:19:14 +080042* ***************************************************************************
43*
44*/
45
46
47/*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
50 */
51#include "AGESA.h"
52#include "Ids.h"
53#include "amdlib.h"
54#include "heapManager.h"
55#include "Gnb.h"
56#include "GnbFuseTable.h"
57#include "GnbPcie.h"
58#include "GnbGfx.h"
59#include "GnbFuseTable.h"
60#include "GnbGfxFamServices.h"
61#include "GnbCommonLib.h"
62#include "GfxPowerPlayTable.h"
63#include "Filecode.h"
64#define FILECODE PROC_GNB_MODULES_GNBGFXINITLIBV1_GFXPOWERPLAYTABLE_FILECODE
65
66/*----------------------------------------------------------------------------------------
67 * D E F I N I T I O N S A N D M A C R O S
68 *----------------------------------------------------------------------------------------
69 */
70
71/*----------------------------------------------------------------------------------------
72 * T Y P E D E F S A N D S T R U C T U R E S
73 *----------------------------------------------------------------------------------------
74 */
75/// Software state
76typedef struct {
77 BOOLEAN Valid; ///< State valid
78 UINT16 Classification; ///< State classification
79 UINT32 CapsAndSettings; ///< State capability and settings
80 UINT16 Classification2; ///< State classification2
81 UINT32 Vclk; ///< UVD VCLK
82 UINT32 Dclk; ///< UVD DCLK
83 UINT8 NumberOfDpmStates; ///< Number of DPM states
84 UINT8 DpmSatesArray[MAX_NUM_OF_DPM_STATES]; ///< DPM state index array
85} SW_STATE;
86
87/// DPM state
88typedef struct {
89 BOOLEAN Valid; ///< State valid
90 UINT32 Sclk; ///< Sclk in kHz
91 UINT8 Vid; ///< VID index
92 UINT16 Tdp; ///< Tdp limit
93} DPM_STATE;
94
95typedef struct {
96 GFX_PLATFORM_CONFIG *Gfx;
97 ATOM_PPLIB_POWERPLAYTABLE3 *PpTable;
98 PP_FUSE_ARRAY *PpFuses;
99 SW_STATE SwStateArray [MAX_NUM_OF_SW_STATES]; ///< SW state array
100 DPM_STATE DpmStateArray[MAX_NUM_OF_DPM_STATES]; ///< Sclk DPM state array
101 UINT8 NumOfClockVoltageLimitEnties; ///
102 ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD VceClockVoltageLimitArray[MAX_NUM_OF_VCE_CLK_STATES];
103 UINT8 NumOfVceClockEnties;
104 VCECLOCKINFO VceClockInfoArray[MAX_NUM_OF_VCE_CLK_STATES];
105 UINT8 NumOfVceStateEntries;
106 ATOM_PPLIB_VCE_STATE_RECORD VceStateArray[MAX_NUM_OF_VCE_STATES]; ///< VCE state array
107} PP_WORKSPACE;
108/*----------------------------------------------------------------------------------------
109 * 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
110 *----------------------------------------------------------------------------------------
111 */
112
113VOID
114GfxIntegratedDebugDumpPpTable (
115 IN ATOM_PPLIB_POWERPLAYTABLE3 *PpTable,
116 IN GFX_PLATFORM_CONFIG *Gfx
117 );
118
119/*----------------------------------------------------------------------------------------*/
120/**
121 * Locate existing tdp
122 *
123 *
124 * @param[in ] PpFuses Pointer to PP_FUSE_ARRAY
125 * @param[in] Sclk Sclk in 10kHz
126 * @param[in] StdHeader Standard configuration header
127 * @retval Tdp limit in DPM state array
128 */
129
130STATIC UINT16
131GfxPowerPlayLocateTdp (
132 IN PP_FUSE_ARRAY *PpFuses,
133 IN UINT32 Sclk,
134 IN AMD_CONFIG_PARAMS *StdHeader
135 )
136{
137 UINT8 Index;
138 UINT32 DpmIndex;
139 UINT32 DpmSclk;
140 UINT32 DeltaSclk;
141 UINT32 MinDeltaSclk;
142
143 DpmIndex = 0;
144 MinDeltaSclk = 0xFFFFFFFF;
145 for (Index = 0; Index < MAX_NUM_OF_FUSED_DPM_STATES; Index++) {
146 if (PpFuses->SclkDpmDid[Index] != 0) {
147 DpmSclk = GfxFmCalculateClock (PpFuses->SclkDpmDid[Index], StdHeader);
148 DeltaSclk = (DpmSclk > Sclk) ? (DpmSclk - Sclk) : (Sclk - DpmSclk);
149 if (DeltaSclk < MinDeltaSclk) {
Edward O'Callaghan8dd407a2014-05-15 19:37:24 +1000150 MinDeltaSclk = DeltaSclk;
zbao7d94cf92012-07-02 14:19:14 +0800151 DpmIndex = Index;
152 }
153 }
154 }
155 return PpFuses->SclkDpmTdpLimit[DpmIndex];
156}
157
158/*----------------------------------------------------------------------------------------*/
159/**
160 * Create new software state
161 *
162 *
163 * @param[in, out] PpWorkspace PP workspace
164 * @retval Pointer to state entry in SW state array
165 */
166
167STATIC SW_STATE*
168GfxPowerPlayCreateSwState (
169 IN OUT PP_WORKSPACE *PpWorkspace
170 )
171{
172 UINTN Index;
173 for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
174 if (PpWorkspace->SwStateArray[Index].Valid == FALSE) {
175 PpWorkspace->SwStateArray[Index].Valid = TRUE;
176 return &(PpWorkspace->SwStateArray[Index]);
177 }
178 }
179 return NULL;
180}
181
182/*----------------------------------------------------------------------------------------*/
183/**
184 * Create new DPM state
185 *
186 *
187 * @param[in, out] PpWorkspace PP workspace
188 * @param[in] Sclk SCLK in kHz
189 * @param[in] Vid Vid index
190 * @param[in] Tdp Tdp limit
191 * @retval Index of state entry in DPM state array
192 */
193
194STATIC UINT8
195GfxPowerPlayCreateDpmState (
196 IN OUT PP_WORKSPACE *PpWorkspace,
197 IN UINT32 Sclk,
198 IN UINT8 Vid,
199 IN UINT16 Tdp
200 )
201{
202 UINT8 Index;
203 for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
204 if (PpWorkspace->DpmStateArray[Index].Valid == FALSE) {
205 PpWorkspace->DpmStateArray[Index].Sclk = Sclk;
206 PpWorkspace->DpmStateArray[Index].Vid = Vid;
207 PpWorkspace->DpmStateArray[Index].Valid = TRUE;
208 PpWorkspace->DpmStateArray[Index].Tdp = Tdp;
209 return Index;
210 }
211 }
212 return 0;
213}
214
215/*----------------------------------------------------------------------------------------*/
216/**
217 * Locate existing or Create new DPM state
218 *
219 *
220 * @param[in, out] PpWorkspace PP workspace
221 * @param[in] Sclk SCLK in kHz
222 * @param[in] Vid Vid index
223 * @param[in] Tdp Tdp limit
224 * @retval Index of state entry in DPM state array
225 */
226
227STATIC UINT8
228GfxPowerPlayAddDpmState (
229 IN OUT PP_WORKSPACE *PpWorkspace,
230 IN UINT32 Sclk,
231 IN UINT8 Vid,
232 IN UINT16 Tdp
233 )
234{
235 UINT8 Index;
236 for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
237 if (PpWorkspace->DpmStateArray[Index].Valid && Sclk == PpWorkspace->DpmStateArray[Index].Sclk && Vid == PpWorkspace->DpmStateArray[Index].Vid) {
238 return Index;
239 }
240 }
241 return GfxPowerPlayCreateDpmState (PpWorkspace, Sclk, Vid, Tdp);
242}
243
244/*----------------------------------------------------------------------------------------*/
245/**
246 * Add reference to DPM state for SW state
247 *
248 *
249 * @param[in, out] SwStateArray Pointer to SW state array
250 * @param[in] DpmStateIndex DPM state index
251 */
252
253STATIC VOID
254GfxPowerPlayAddDpmStateToSwState (
255 IN OUT SW_STATE *SwStateArray,
256 IN UINT8 DpmStateIndex
257 )
258{
259 SwStateArray->DpmSatesArray[SwStateArray->NumberOfDpmStates++] = DpmStateIndex;
260}
261
262/*----------------------------------------------------------------------------------------*/
263/**
264 * Copy SW state info to PPTable
265 *
266 *
267 * @param[in, out] PpWorkspace PP workspace
268 */
269STATIC VOID *
270GfxPowerPlayAttachStateInfoBlock (
271 IN OUT PP_WORKSPACE *PpWorkspace
272 )
273{
274 UINT8 Index;
275 UINT8 SwStateIndex;
276 STATE_ARRAY *StateArray;
277 ATOM_PPLIB_STATE_V2 *States;
278 StateArray = (STATE_ARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
279 States = &StateArray->States[0];
280 SwStateIndex = 0;
281 for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
282 if (PpWorkspace->SwStateArray[Index].Valid && PpWorkspace->SwStateArray[Index].NumberOfDpmStates != 0) {
283 States->nonClockInfoIndex = SwStateIndex;
284 States->ucNumDPMLevels = PpWorkspace->SwStateArray[Index].NumberOfDpmStates;
285 LibAmdMemCopy (
286 &States->ClockInfoIndex[0],
287 PpWorkspace->SwStateArray[Index].DpmSatesArray,
288 PpWorkspace->SwStateArray[Index].NumberOfDpmStates,
289 GnbLibGetHeader (PpWorkspace->Gfx)
290 );
291 States = (ATOM_PPLIB_STATE_V2*) ((UINT8*) States + sizeof (ATOM_PPLIB_STATE_V2) + sizeof (UINT8) * (States->ucNumDPMLevels - 1));
292 SwStateIndex++;
293 }
294 }
295 StateArray->ucNumEntries = SwStateIndex;
296 PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize + (USHORT) ((UINT8 *) States - (UINT8 *) StateArray);
297 return StateArray;
298}
299/*----------------------------------------------------------------------------------------*/
300/**
301 * Copy clock info to PPTable
302 *
303 *
304 * @param[in, out] PpWorkspace PP workspace
305 */
306
307STATIC VOID *
308GfxPowerPlayAttachClockInfoBlock (
309 IN OUT PP_WORKSPACE *PpWorkspace
310 )
311{
312 CLOCK_INFO_ARRAY *ClockInfoArray;
313 UINT8 Index;
314 UINT8 ClkStateIndex;
315 ClkStateIndex = 0;
316 ClockInfoArray = (CLOCK_INFO_ARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
317 for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
318 if (PpWorkspace->DpmStateArray[Index].Valid == TRUE) {
319 ClockInfoArray->ClockInfo[ClkStateIndex].ucEngineClockHigh = (UINT8) (PpWorkspace->DpmStateArray[Index].Sclk >> 16);
320 ClockInfoArray->ClockInfo[ClkStateIndex].usEngineClockLow = (UINT16) (PpWorkspace->DpmStateArray[Index].Sclk);
321 ClockInfoArray->ClockInfo[ClkStateIndex].vddcIndex = PpWorkspace->DpmStateArray[Index].Vid;
322 ClockInfoArray->ClockInfo[ClkStateIndex].tdpLimit = PpWorkspace->DpmStateArray[Index].Tdp;
323 ClkStateIndex++;
324 }
325 }
326 ClockInfoArray->ucNumEntries = ClkStateIndex;
327 ClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO);
328 PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO) * ClkStateIndex - sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO);
329 return ClockInfoArray;
330}
331
332/*----------------------------------------------------------------------------------------*/
333/**
334 * Copy non clock info to PPTable
335 *
336 *
337 * @param[in, out] PpWorkspace PP workspace
338 */
339
340STATIC VOID *
341GfxPowerPlayAttachNonClockInfoBlock (
342 IN OUT PP_WORKSPACE *PpWorkspace
343 )
344{
345 NON_CLOCK_INFO_ARRAY *NonClockInfoArray;
346 UINT8 Index;
347 UINT8 NonClkStateIndex;
348
349 NonClockInfoArray = (NON_CLOCK_INFO_ARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
350 NonClkStateIndex = 0;
351 for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
352 if (PpWorkspace->SwStateArray[Index].Valid && PpWorkspace->SwStateArray[Index].NumberOfDpmStates != 0) {
353 NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification = PpWorkspace->SwStateArray[Index].Classification;
354 NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulCapsAndSettings = PpWorkspace->SwStateArray[Index].CapsAndSettings;
355 NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification2 = PpWorkspace->SwStateArray[Index].Classification2;
356 NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulDCLK = PpWorkspace->SwStateArray[Index].Dclk;
357 NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulVCLK = PpWorkspace->SwStateArray[Index].Vclk;
358 NonClkStateIndex++;
359 }
360 }
361 NonClockInfoArray->ucNumEntries = NonClkStateIndex;
362 NonClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_NONCLOCK_INFO);
363 PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (NON_CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_NONCLOCK_INFO) * NonClkStateIndex - sizeof (ATOM_PPLIB_NONCLOCK_INFO);
364 return NonClockInfoArray;
365}
366
367/*----------------------------------------------------------------------------------------*/
368/**
369 * Check if fused state valid
370 *
371 *
372 * @param[out] Index State index
373 * @param[in] PpFuses Pointer to fuse table
374 * @param[in] Gfx Gfx configuration info
375 * @retval TRUE State is valid
376 */
377STATIC BOOLEAN
378GfxPowerPlayIsFusedStateValid (
379 IN UINT8 Index,
380 IN PP_FUSE_ARRAY *PpFuses,
381 IN GFX_PLATFORM_CONFIG *Gfx
382 )
383{
384 BOOLEAN Result;
385 Result = FALSE;
386 if (PpFuses->SclkDpmValid[Index] != 0) {
387 Result = TRUE;
388 if (PpFuses->PolicyLabel[Index] == POLICY_LABEL_BATTERY && (Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) == 0) {
389 Result = FALSE;
390 }
391 }
392 return Result;
393}
394
395/*----------------------------------------------------------------------------------------*/
396/**
397 * Get SW state calssification from fuses
398 *
399 *
400 * @param[out] Index State index
401 * @param[in] PpFuses Pointer to fuse table
402 * @param[in] Gfx Gfx configuration info
403 * @retval State classification
404 */
405
406STATIC UINT16
407GfxPowerPlayGetClassificationFromFuses (
408 IN UINT8 Index,
409 IN PP_FUSE_ARRAY *PpFuses,
410 IN GFX_PLATFORM_CONFIG *Gfx
411 )
412{
413 UINT16 Classification;
414 Classification = 0;
415 switch (PpFuses->PolicyFlags[Index]) {
416 case 0x1:
417 Classification |= ATOM_PPLIB_CLASSIFICATION_NONUVDSTATE;
418 break;
419 case 0x2:
420 Classification |= ATOM_PPLIB_CLASSIFICATION_UVDSTATE;
421 break;
422 case 0x4:
423 //Possible SD + HD state
424 break;
425 case 0x8:
426 Classification |= ATOM_PPLIB_CLASSIFICATION_HDSTATE;
427 break;
428 case 0x10:
429 Classification |= ATOM_PPLIB_CLASSIFICATION_SDSTATE;
430 break;
431 default:
432 break;
433 }
434 switch (PpFuses->PolicyLabel[Index]) {
435 case POLICY_LABEL_BATTERY:
436 Classification |= ATOM_PPLIB_CLASSIFICATION_UI_BATTERY;
437 break;
438 case POLICY_LABEL_PERFORMANCE:
439 Classification |= ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE;
440 break;
441 default:
442 break;
443 }
444 return Classification;
445}
446
447/*----------------------------------------------------------------------------------------*/
448/**
449 * Get SW state calssification2 from fuses
450 *
451 *
452 * @param[out] Index State index
453 * @param[in] PpFuses Pointer to fuse table
454 * @param[in] Gfx Gfx configuration info
455 * @retval State classification2
456 */
457
458STATIC UINT16
459GfxPowerPlayGetClassification2FromFuses (
460 IN UINT8 Index,
461 IN PP_FUSE_ARRAY *PpFuses,
462 IN GFX_PLATFORM_CONFIG *Gfx
463 )
464{
465 UINT16 Classification2;
466 Classification2 = 0;
467
468 switch (PpFuses->PolicyFlags[Index]) {
469
470 case 0x4:
471 Classification2 |= ATOM_PPLIB_CLASSIFICATION2_MVC;
472 break;
473
474 default:
475 break;
476 }
477
478 return Classification2;
479}
480
481/*----------------------------------------------------------------------------------------*/
482/**
483 * Build SCLK state info
484 *
485 *
486 * @param[in, out] PpWorkspace PP workspace
487 */
488
489STATIC VOID
490GfxPowerPlayBuildSclkStateTable (
491 IN OUT PP_WORKSPACE *PpWorkspace
492 )
493{
494 UINT8 ClkStateIndex;
495 UINT8 DpmFuseIndex;
496 UINT8 Index;
497 UINT32 Sclk;
498 SW_STATE *State;
499 PP_FUSE_ARRAY *PpFuses;
500
501 PpFuses = PpWorkspace->PpFuses;
502 // Create States from Fuses
503 for (Index = 0; Index < MAX_NUM_OF_FUSED_SW_STATES; Index++) {
504 if (GfxPowerPlayIsFusedStateValid (Index, PpFuses, PpWorkspace->Gfx)) {
505 //Create new SW State;
506 State = GfxPowerPlayCreateSwState (PpWorkspace);
507 State->Classification = GfxPowerPlayGetClassificationFromFuses (Index, PpFuses, PpWorkspace->Gfx);
508 State->Classification2 = GfxPowerPlayGetClassification2FromFuses (Index, PpFuses, PpWorkspace->Gfx);
509 if ((State->Classification & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_UVDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) != 0 ||
510 (State->Classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) != 0) {
511 State->Vclk = (PpFuses->VclkDid[PpFuses->VclkDclkSel[Index]] != 0) ? GfxFmCalculateClock (PpFuses->VclkDid[PpFuses->VclkDclkSel[Index]], GnbLibGetHeader (PpWorkspace->Gfx)) : 0;
512 State->Dclk = (PpFuses->DclkDid[PpFuses->VclkDclkSel[Index]] != 0) ? GfxFmCalculateClock (PpFuses->DclkDid[PpFuses->VclkDclkSel[Index]], GnbLibGetHeader (PpWorkspace->Gfx)) : 0;
513 }
514 if (((State->Classification & 0x7) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) ||
515 ((State->Classification & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) != 0)) {
516 if (PpWorkspace->Gfx->AbmSupport != 0) {
517 State->CapsAndSettings |= ATOM_PPLIB_ENABLE_VARIBRIGHT;
518 }
519 if (PpWorkspace->Gfx->DynamicRefreshRate != 0) {
520 State->CapsAndSettings |= ATOM_PPLIB_ENABLE_DRR;
521 }
522 }
523 for (DpmFuseIndex = 0; DpmFuseIndex < MAX_NUM_OF_FUSED_DPM_STATES; DpmFuseIndex++) {
524 if ((PpFuses->SclkDpmValid[Index] & (1 << DpmFuseIndex)) != 0 ) {
525 Sclk = (PpFuses->SclkDpmDid[DpmFuseIndex] != 0) ? GfxFmCalculateClock (PpFuses->SclkDpmDid[DpmFuseIndex], GnbLibGetHeader (PpWorkspace->Gfx)) : 0;
526 if (Sclk != 0) {
527 ClkStateIndex = GfxPowerPlayAddDpmState (PpWorkspace, Sclk, PpFuses->SclkDpmVid[DpmFuseIndex], PpFuses->SclkDpmTdpLimit[DpmFuseIndex]);
528 GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
529 }
530 }
531 }
532 }
533 }
534 // Create Boot State
535 State = GfxPowerPlayCreateSwState (PpWorkspace);
536 State->Classification = ATOM_PPLIB_CLASSIFICATION_BOOT;
537 Sclk = 200 * 100;
538 ClkStateIndex = GfxPowerPlayAddDpmState (PpWorkspace, Sclk, 0, GfxPowerPlayLocateTdp (PpFuses, Sclk, GnbLibGetHeader (PpWorkspace->Gfx)));
539 GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
540
541 // Create Thermal State
542 State = GfxPowerPlayCreateSwState (PpWorkspace);
543 State->Classification = ATOM_PPLIB_CLASSIFICATION_THERMAL;
544 Sclk = GfxFmCalculateClock (PpFuses->SclkThermDid, GnbLibGetHeader (PpWorkspace->Gfx));
545 ClkStateIndex = GfxPowerPlayAddDpmState (PpWorkspace, Sclk, 0, GfxPowerPlayLocateTdp (PpFuses, Sclk, GnbLibGetHeader (PpWorkspace->Gfx)));
546 GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
547}
548
549
550/*----------------------------------------------------------------------------------------*/
551/**
552 * Add ECLK state
553 *
554 *
555 * @param[in, out] PpWorkspace PP workspace
556 * @param[in] Eclk SCLK in kHz
557 * @retval Index of state entry in ECLK clock array
558 */
559
560STATIC UINT8
561GfxPowerPlayAddEclkState (
562 IN OUT PP_WORKSPACE *PpWorkspace,
563 IN UINT32 Eclk
564 )
565{
566 UINT8 Index;
567 USHORT EclkLow;
568 UCHAR EclkHigh;
569 EclkLow = (USHORT) (Eclk & 0xffff);
570 EclkHigh = (UCHAR) (Eclk >> 16);
571 for (Index = 0; Index < PpWorkspace->NumOfVceClockEnties; Index++) {
572 if (PpWorkspace->VceClockInfoArray[Index].ucECClkHigh == EclkHigh && PpWorkspace->VceClockInfoArray[Index].usECClkLow == EclkLow) {
573 return Index;
574 }
575 }
576 PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].ucECClkHigh = EclkHigh;
577 PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].usECClkLow = EclkLow;
578 PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].ucEVClkHigh = EclkHigh;
579 PpWorkspace->VceClockInfoArray[PpWorkspace->NumOfVceClockEnties].usEVClkLow = EclkLow;
580 return PpWorkspace->NumOfVceClockEnties++;
581}
582
583/*----------------------------------------------------------------------------------------*/
584/**
585 * Add ECLK state
586 *
587 *
588 * @param[in, out] PpWorkspace PP workspace
589 * @param[in] EclkIndex ECLK index
590 * @param[in] Vid Vid index
591 * @retval Index of state entry in Eclk Voltage record array
592 */
593
594STATIC UINT8
595GfxPowerPlayAddEclkVoltageRecord (
596 IN OUT PP_WORKSPACE *PpWorkspace,
597 IN UINT8 EclkIndex,
598 IN UINT8 Vid
599 )
600{
601 UINT8 Index;
602 for (Index = 0; Index < PpWorkspace->NumOfClockVoltageLimitEnties; Index++) {
603 if (PpWorkspace->VceClockVoltageLimitArray[Index].ucVCEClockInfoIndex == EclkIndex) {
604 return Index;
605 }
606 }
607 PpWorkspace->VceClockVoltageLimitArray[PpWorkspace->NumOfClockVoltageLimitEnties].ucVCEClockInfoIndex = EclkIndex;
608 PpWorkspace->VceClockVoltageLimitArray[PpWorkspace->NumOfClockVoltageLimitEnties].usVoltage = Vid;
609 return PpWorkspace->NumOfClockVoltageLimitEnties++;
610}
611
612
613/*----------------------------------------------------------------------------------------*/
614/**
615 * Attach extended header
616 *
617 *
618 * @param[in, out] PpWorkspace PP workspace
619 */
620
621STATIC VOID *
622GfxPowerPlayAttachVceTableRevBlock (
623 IN OUT PP_WORKSPACE *PpWorkspace
624 )
625{
626 ATOM_PPLIB_VCE_TABLE *VceTable;
627 VceTable = (ATOM_PPLIB_VCE_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
628 VceTable->revid = 0;
629 PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (ATOM_PPLIB_VCE_TABLE);
630 return VceTable;
631}
632
633/*----------------------------------------------------------------------------------------*/
634/**
635 * Attach extended header
636 *
637 *
638 * @param[in, out] PpWorkspace PP workspace
639 */
640
641STATIC VOID *
642GfxPowerPlayAttachExtendedHeaderBlock (
643 IN OUT PP_WORKSPACE *PpWorkspace
644 )
645{
646 ATOM_PPLIB_EXTENDEDHEADER *ExtendedHeader;
647 ExtendedHeader = (ATOM_PPLIB_EXTENDEDHEADER *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
648 ExtendedHeader->usSize = sizeof (ATOM_PPLIB_EXTENDEDHEADER);
649 PpWorkspace->PpTable->sHeader.usStructureSize += sizeof (ATOM_PPLIB_EXTENDEDHEADER);
650 return ExtendedHeader;
651}
652
653/*----------------------------------------------------------------------------------------*/
654/**
655 * Attach VCE clock info block
656 *
657 *
658 * @param[in, out] PpWorkspace PP workspace
659 */
660
661STATIC VOID *
662GfxPowerPlayAttachVceClockInfoBlock (
663 IN OUT PP_WORKSPACE *PpWorkspace
664 )
665{
666 VCECLOCKINFOARRAY *VceClockInfoArray;
667 VceClockInfoArray = (VCECLOCKINFOARRAY *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
668 VceClockInfoArray->ucNumEntries = PpWorkspace->NumOfVceClockEnties;
669 LibAmdMemCopy (
670 &VceClockInfoArray->entries[0],
671 &PpWorkspace->VceClockInfoArray[0],
672 VceClockInfoArray->ucNumEntries * sizeof (VCECLOCKINFO),
673 GnbLibGetHeader (PpWorkspace->Gfx)
674 );
675 PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize +
676 sizeof (VCECLOCKINFOARRAY) +
677 VceClockInfoArray->ucNumEntries * sizeof (VCECLOCKINFO) -
678 sizeof (VCECLOCKINFO);
679 return VceClockInfoArray;
680}
681
682
683/*----------------------------------------------------------------------------------------*/
684/**
685 * Attach VCE voltage limit block
686 *
687 *
688 * @param[in, out] PpWorkspace PP workspace
689 */
690
691STATIC VOID *
692GfxPowerPlayAttachVceVoltageLimitBlock (
693 IN OUT PP_WORKSPACE *PpWorkspace
694 )
695{
696 ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *VceClockVoltageLimitTable;
697 VceClockVoltageLimitTable = (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
698 VceClockVoltageLimitTable->numEntries = PpWorkspace->NumOfClockVoltageLimitEnties;
699 LibAmdMemCopy (
700 &VceClockVoltageLimitTable->entries[0],
701 &PpWorkspace->VceClockVoltageLimitArray[0],
702 VceClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD),
703 GnbLibGetHeader (PpWorkspace->Gfx)
704 );
705 PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize +
706 sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE) +
707 VceClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD) -
708 sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD);
709 return VceClockVoltageLimitTable;
710}
711
712/*----------------------------------------------------------------------------------------*/
713/**
714 * Attach VCE state block
715 *
716 *
717 * @param[in, out] PpWorkspace PP workspace
718 */
719
720STATIC VOID *
721GfxPowerPlayAttachVceStateTaleBlock (
722 IN OUT PP_WORKSPACE *PpWorkspace
723 )
724{
725 ATOM_PPLIB_VCE_STATE_TABLE *VceStateTable;
726 VceStateTable = (ATOM_PPLIB_VCE_STATE_TABLE *) ((UINT8 *) PpWorkspace->PpTable + PpWorkspace->PpTable->sHeader.usStructureSize);
727 VceStateTable->numEntries = PpWorkspace->NumOfVceStateEntries;
728 LibAmdMemCopy (
729 &VceStateTable->entries[0],
730 &PpWorkspace->VceStateArray[0],
731 VceStateTable->numEntries * sizeof (ATOM_PPLIB_VCE_STATE_RECORD),
732 GnbLibGetHeader (PpWorkspace->Gfx)
733 );
734 PpWorkspace->PpTable->sHeader.usStructureSize = PpWorkspace->PpTable->sHeader.usStructureSize +
735 sizeof (ATOM_PPLIB_VCE_STATE_TABLE) +
736 VceStateTable->numEntries * sizeof (ATOM_PPLIB_VCE_STATE_RECORD) -
737 sizeof (ATOM_PPLIB_VCE_STATE_RECORD);
738 return VceStateTable;
739}
740
741/*----------------------------------------------------------------------------------------*/
742/**
743 * Build VCE state info
744 *
745 *
746 * @param[in, out] PpWorkspace PP workspace
747 */
748
749STATIC VOID
750GfxPowerPlayBuildVceStateTable (
751 IN OUT PP_WORKSPACE *PpWorkspace
752 )
753{
754 UINT8 Index;
755 UINT8 VceStateIndex;
756 UINT8 Vid;
757 UINT32 Eclk;
758 UINT32 Sclk;
759 UINT8 UsedStateBitmap;
760 UsedStateBitmap = 0;
761 // build used state
Patrick Georgi6b688f52021-02-12 13:49:11 +0100762 for (Index = 0; Index < ARRAY_SIZE(PpWorkspace->PpFuses->VceFlags); Index++) {
zbao7d94cf92012-07-02 14:19:14 +0800763 UsedStateBitmap |= PpWorkspace->PpFuses->VceFlags[Index];
Patrick Georgi6b688f52021-02-12 13:49:11 +0100764 for (VceStateIndex = 0; VceStateIndex < ARRAY_SIZE(PpWorkspace->VceStateArray); VceStateIndex++) {
zbao7d94cf92012-07-02 14:19:14 +0800765 if ((PpWorkspace->PpFuses->VceFlags[Index] & (1 << VceStateIndex)) != 0) {
766 Sclk = GfxFmCalculateClock (PpWorkspace->PpFuses->SclkDpmDid[PpWorkspace->PpFuses->VceReqSclkSel[Index]], GnbLibGetHeader (PpWorkspace->Gfx));
767 Vid = PpWorkspace->PpFuses->SclkDpmVid[PpWorkspace->PpFuses->VceReqSclkSel[Index]];
768 PpWorkspace->VceStateArray[VceStateIndex].ucClockInfoIndex = GfxPowerPlayAddDpmState (PpWorkspace, Sclk, Vid, GfxPowerPlayLocateTdp (PpWorkspace->PpFuses, Sclk, GnbLibGetHeader (PpWorkspace->Gfx)));
769 if (PpWorkspace->PpFuses->VceMclk[Index] == 1) {
770 PpWorkspace->VceStateArray[VceStateIndex].ucClockInfoIndex |= (PpWorkspace->PpFuses->VceMclk[Index] << 6);
771 }
772 Eclk = GfxFmCalculateClock (PpWorkspace->PpFuses->EclkDid[Index], GnbLibGetHeader (PpWorkspace->Gfx));
773 PpWorkspace->VceStateArray[VceStateIndex].ucVCEClockInfoIndex = GfxPowerPlayAddEclkState (PpWorkspace, Eclk);
774 GfxPowerPlayAddEclkVoltageRecord (PpWorkspace, PpWorkspace->VceStateArray[VceStateIndex].ucVCEClockInfoIndex, Vid);
775 PpWorkspace->NumOfVceStateEntries++;
776 }
777 }
778 }
779 //build unused states
Patrick Georgi6b688f52021-02-12 13:49:11 +0100780 for (VceStateIndex = 0; VceStateIndex < ARRAY_SIZE(PpWorkspace->VceStateArray); VceStateIndex++) {
zbao7d94cf92012-07-02 14:19:14 +0800781 if ((UsedStateBitmap & (1 << VceStateIndex)) == 0) {
782 PpWorkspace->VceStateArray[VceStateIndex].ucClockInfoIndex = 0;
783 PpWorkspace->VceStateArray[VceStateIndex].ucVCEClockInfoIndex = GfxPowerPlayAddEclkState (PpWorkspace, 0);
784 PpWorkspace->NumOfVceStateEntries++;
785 }
786 }
787}
788
789/*----------------------------------------------------------------------------------------*/
790/**
791 * Build PP table
792 *
793 *
794 * @param[out] Buffer Buffer to create PP table
795 * @param[in] Gfx Gfx configuration info
796 * @retval AGESA_SUCCESS
797 * @retval AGESA_ERROR
798 */
799
800AGESA_STATUS
801GfxPowerPlayBuildTable (
802 OUT VOID *Buffer,
803 IN GFX_PLATFORM_CONFIG *Gfx
804 )
805{
806 PP_WORKSPACE PpWorkspace;
807 VOID *BlockPtr;
808
809 LibAmdMemFill (&PpWorkspace, 0x00, sizeof (PP_WORKSPACE), GnbLibGetHeader (Gfx));
810 PpWorkspace.PpFuses = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, GnbLibGetHeader (Gfx));
811 ASSERT (PpWorkspace.PpFuses != NULL);
812 if (PpWorkspace.PpFuses == NULL) {
813 return AGESA_ERROR;
814 }
815 PpWorkspace.PpTable = (ATOM_PPLIB_POWERPLAYTABLE3 *) Buffer;
816 PpWorkspace.Gfx = Gfx;
817 //Fill static info
818 PpWorkspace.PpTable->sHeader.ucTableFormatRevision = 6;
819 PpWorkspace.PpTable->sHeader.ucTableContentRevision = 1;
820 PpWorkspace.PpTable->ucDataRevision = PpWorkspace.PpFuses->PPlayTableRev;
821 PpWorkspace.PpTable->sThermalController.ucType = ATOM_PP_THERMALCONTROLLER_SUMO;
822 PpWorkspace.PpTable->sThermalController.ucFanParameters = ATOM_PP_FANPARAMETERS_NOFAN;
823 PpWorkspace.PpTable->sHeader.usStructureSize = sizeof (ATOM_PPLIB_POWERPLAYTABLE3);
824 PpWorkspace.PpTable->usTableSize = sizeof (ATOM_PPLIB_POWERPLAYTABLE3);
825 PpWorkspace.PpTable->usFormatID = 7;
826 if ((Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) != 0) {
827 PpWorkspace.PpTable->ulPlatformCaps |= ATOM_PP_PLATFORM_CAP_POWERPLAY;
828 }
829
830 // Fill Slck SW/DPM state info
831 GfxPowerPlayBuildSclkStateTable (&PpWorkspace);
832 // Fill Eclk state info
833 if (PpWorkspace.PpFuses->VceSateTableSupport) {
834 GfxPowerPlayBuildVceStateTable (&PpWorkspace);
835 }
836
837 //Copy state info to actual PP table
838 BlockPtr = GfxPowerPlayAttachStateInfoBlock (&PpWorkspace);
839 PpWorkspace.PpTable->usStateArrayOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
840 BlockPtr = GfxPowerPlayAttachClockInfoBlock (&PpWorkspace);
841 PpWorkspace.PpTable->usClockInfoArrayOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
842 BlockPtr = GfxPowerPlayAttachNonClockInfoBlock (&PpWorkspace);
843 PpWorkspace.PpTable->usNonClockInfoArrayOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
844 if (PpWorkspace.PpFuses->VceSateTableSupport) {
845 ATOM_PPLIB_EXTENDEDHEADER *ExtendedHeader;
846 ExtendedHeader = (ATOM_PPLIB_EXTENDEDHEADER *) GfxPowerPlayAttachExtendedHeaderBlock (&PpWorkspace);
847 PpWorkspace.PpTable->usExtendendedHeaderOffset = (USHORT) ((UINT8 *) ExtendedHeader - (UINT8 *) (PpWorkspace.PpTable));
848 BlockPtr = GfxPowerPlayAttachVceTableRevBlock (&PpWorkspace);
849 ExtendedHeader->usVCETableOffset = (USHORT) ((UINT8 *) BlockPtr - (UINT8 *) (PpWorkspace.PpTable));
850 GfxPowerPlayAttachVceClockInfoBlock (&PpWorkspace);
851 GfxPowerPlayAttachVceVoltageLimitBlock (&PpWorkspace);
852 GfxPowerPlayAttachVceStateTaleBlock (&PpWorkspace);
853
854 }
855 GNB_DEBUG_CODE (
856 GfxIntegratedDebugDumpPpTable (PpWorkspace.PpTable, Gfx);
857 );
858 return AGESA_SUCCESS;
859}
860
861/*----------------------------------------------------------------------------------------*/
862/**
863 * Dump PP table
864 *
865 *
866 *
867 * @param[in] PpTable Power Play table
868 * @param[in] Gfx Gfx configuration info
869 */
870
871VOID
872GfxIntegratedDebugDumpPpTable (
873 IN ATOM_PPLIB_POWERPLAYTABLE3 *PpTable,
874 IN GFX_PLATFORM_CONFIG *Gfx
875 )
876{
877 UINTN Index;
878 UINTN DpmIndex;
879 STATE_ARRAY *StateArray;
880 ATOM_PPLIB_STATE_V2 *StatesPtr;
881 NON_CLOCK_INFO_ARRAY *NonClockInfoArrayPtr;
882 CLOCK_INFO_ARRAY *ClockInfoArrayPtr;
883 ATOM_PPLIB_EXTENDEDHEADER *ExtendedHeader;
884 ATOM_PPLIB_VCE_STATE_TABLE *VceStateTable;
885 ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *VceClockVoltageLimitTable;
886 VCECLOCKINFOARRAY *VceClockInfoArray;
887 UINT8 SclkIndex;
888 UINT8 EclkIndex;
889
890 IDS_HDT_CONSOLE (GFX_MISC, " < --- Power Play Table ------ > \n");
891 IDS_HDT_CONSOLE (GFX_MISC, " Table Revision = %d\n", PpTable->ucDataRevision);
892 StateArray = (STATE_ARRAY *) ((UINT8 *) PpTable + PpTable->usStateArrayOffset);
893 StatesPtr = StateArray->States;
894 NonClockInfoArrayPtr = (NON_CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usNonClockInfoArrayOffset);
895 ClockInfoArrayPtr = (CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usClockInfoArrayOffset);
896 IDS_HDT_CONSOLE (GFX_MISC, " < --- SW State Table ---------> \n");
897 for (Index = 0; Index < StateArray->ucNumEntries; Index++) {
Angel Ponsb382b892021-05-09 16:11:30 +0200898 IDS_HDT_CONSOLE (GFX_MISC, " State #%ld\n", Index + 1
zbao7d94cf92012-07-02 14:19:14 +0800899 );
900 IDS_HDT_CONSOLE (GFX_MISC, " Classification 0x%x\n",
901 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].usClassification
902 );
903 IDS_HDT_CONSOLE (GFX_MISC, " Classification2 0x%x\n",
904 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].usClassification2
905 );
906 IDS_HDT_CONSOLE (GFX_MISC, " VCLK = %dkHz\n",
907 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].ulVCLK
908 );
909 IDS_HDT_CONSOLE (GFX_MISC, " DCLK = %dkHz\n",
910 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].ulDCLK
911 );
912 IDS_HDT_CONSOLE (GFX_MISC, " DPM State Index: ");
913 for (DpmIndex = 0; DpmIndex < StatesPtr->ucNumDPMLevels; DpmIndex++) {
914 IDS_HDT_CONSOLE (GFX_MISC, "%d ",
915 StatesPtr->ClockInfoIndex [DpmIndex]
916 );
917 }
918 IDS_HDT_CONSOLE (GFX_MISC, "\n");
919 StatesPtr = (ATOM_PPLIB_STATE_V2 *) ((UINT8 *) StatesPtr + sizeof (ATOM_PPLIB_STATE_V2) + StatesPtr->ucNumDPMLevels - 1);
920 }
921 IDS_HDT_CONSOLE (GFX_MISC, " < --- SCLK DPM State Table ---> \n");
922 for (Index = 0; Index < ClockInfoArrayPtr->ucNumEntries; Index++) {
923 UINT32 Sclk;
924 Sclk = ClockInfoArrayPtr->ClockInfo[Index].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[Index].ucEngineClockHigh << 16);
Angel Ponsb382b892021-05-09 16:11:30 +0200925 IDS_HDT_CONSOLE (GFX_MISC, " DPM State #%ld\n",
zbao7d94cf92012-07-02 14:19:14 +0800926 Index
927 );
928 IDS_HDT_CONSOLE (GFX_MISC, " SCLK = %d\n",
929 ClockInfoArrayPtr->ClockInfo[Index].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[Index].ucEngineClockHigh << 16)
930 );
931 IDS_HDT_CONSOLE (GFX_MISC, " VID index = %d\n",
932 ClockInfoArrayPtr->ClockInfo[Index].vddcIndex
933 );
934 IDS_HDT_CONSOLE (GFX_MISC, " tdpLimit = %d\n",
935 ClockInfoArrayPtr->ClockInfo[Index].tdpLimit
936 );
937 }
938 if (PpTable->usExtendendedHeaderOffset != 0) {
939 ExtendedHeader = (ATOM_PPLIB_EXTENDEDHEADER *) ((UINT8 *) PpTable + PpTable->usExtendendedHeaderOffset);
940 VceClockInfoArray = (VCECLOCKINFOARRAY *) ((UINT8 *) ExtendedHeader + sizeof (ATOM_PPLIB_EXTENDEDHEADER) + sizeof (ATOM_PPLIB_VCE_TABLE));
941 VceClockVoltageLimitTable = (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE *) ((UINT8 *) VceClockInfoArray +
942 sizeof (VCECLOCKINFOARRAY) +
943 VceClockInfoArray->ucNumEntries * sizeof (VCECLOCKINFO) -
944 sizeof (VCECLOCKINFO));
945 VceStateTable = (ATOM_PPLIB_VCE_STATE_TABLE *) ((UINT8 *) VceClockVoltageLimitTable +
946 sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_TABLE) +
947 VceClockVoltageLimitTable->numEntries * sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD) -
948 sizeof (ATOM_PPLIB_VCE_CLOCK_VOLTAGE_LIMIT_RECORD));
949
950 IDS_HDT_CONSOLE (GFX_MISC, " < --- VCE State Table [%d]--> \n", VceStateTable->numEntries);
951 for (Index = 0; Index < VceStateTable->numEntries; Index++) {
952 SclkIndex = VceStateTable->entries[Index].ucClockInfoIndex & 0x3F;
953 EclkIndex = VceStateTable->entries[Index].ucVCEClockInfoIndex;
Angel Ponsb382b892021-05-09 16:11:30 +0200954 IDS_HDT_CONSOLE (GFX_MISC, " VCE State #%ld\n", Index
zbao7d94cf92012-07-02 14:19:14 +0800955 );
956 if ((VceClockInfoArray->entries[EclkIndex].usECClkLow | (VceClockInfoArray->entries[EclkIndex].ucECClkHigh << 16)) == 0) {
957 IDS_HDT_CONSOLE (GFX_MISC, " Disable\n");
958 } else {
959 IDS_HDT_CONSOLE (GFX_MISC, " SCLK = %d\n",
960 ClockInfoArrayPtr->ClockInfo[SclkIndex].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[SclkIndex].ucEngineClockHigh << 16)
961 );
962 IDS_HDT_CONSOLE (GFX_MISC, " ECCLK = %d\n",
963 VceClockInfoArray->entries[EclkIndex].usECClkLow | (VceClockInfoArray->entries[EclkIndex].ucECClkHigh << 16)
964 );
965 IDS_HDT_CONSOLE (GFX_MISC, " EVCLK = %d\n",
966 VceClockInfoArray->entries[EclkIndex].usEVClkLow | (VceClockInfoArray->entries[EclkIndex].ucEVClkHigh << 16)
967 );
968 IDS_HDT_CONSOLE (GFX_MISC, " MCLK = %d\n",
969 (VceStateTable->entries[Index].ucClockInfoIndex >> 6 ) & 0x3
970 );
971 }
972 }
973 IDS_HDT_CONSOLE (GFX_MISC, " < --- VCE Voltage Record Table ---> \n");
974 for (Index = 0; Index < VceClockVoltageLimitTable->numEntries; Index++) {
975 EclkIndex = VceClockVoltageLimitTable->entries[Index].ucVCEClockInfoIndex;
Angel Ponsb382b892021-05-09 16:11:30 +0200976 IDS_HDT_CONSOLE (GFX_MISC, " VCE Voltage Record #%ld\n", Index
zbao7d94cf92012-07-02 14:19:14 +0800977 );
978 IDS_HDT_CONSOLE (GFX_MISC, " ECLK = %d\n",
979 VceClockInfoArray->entries[EclkIndex].usECClkLow | (VceClockInfoArray->entries[EclkIndex].ucECClkHigh << 16)
980 );
981 IDS_HDT_CONSOLE (GFX_MISC, " VID index = %d\n",
982 VceClockVoltageLimitTable->entries[Index].usVoltage
983 );
984 }
985 }
986}