blob: 5f06eb6dd022e6b59797babe2c6781b4b5dfea4e [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $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: 38882 $ @e \$Date: 2010-09-30 18:42:57 -0700 (Thu, 30 Sep 2010) $
13 *
14 */
15/*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
Edward O'Callaghan8dd407a2014-05-15 19:37:24 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * 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.
Edward O'Callaghan8dd407a2014-05-15 19:37:24 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan8dd407a2014-05-15 19:37:24 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * 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.
Edward O'Callaghan8dd407a2014-05-15 19:37:24 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
46
47
48/*----------------------------------------------------------------------------------------
49 * M O D U L E S U S E D
50 *----------------------------------------------------------------------------------------
51 */
52#include "AGESA.h"
53#include "Ids.h"
54#include "amdlib.h"
55#include "heapManager.h"
56#include "Gnb.h"
57#include "GnbFuseTable.h"
58#include "GnbPcie.h"
59#include "GnbGfx.h"
60#include "GnbFuseTable.h"
61#include "GnbGfxFamServices.h"
62#include GNB_MODULE_DEFINITIONS (GnbCommonLib)
63#include "GfxPowerPlayTable.h"
64#include "Filecode.h"
65#define FILECODE PROC_GNB_MODULES_GNBGFXINITLIBV1_GFXPOWERPLAYTABLE_FILECODE
66
67/*----------------------------------------------------------------------------------------
68 * D E F I N I T I O N S A N D M A C R O S
69 *----------------------------------------------------------------------------------------
70 */
71
72
73
74/*----------------------------------------------------------------------------------------
75 * T Y P E D E F S A N D S T R U C T U R E S
76 *----------------------------------------------------------------------------------------
77 */
78/// Software state
79typedef struct {
80 BOOLEAN Valid; ///< State valid
81 UINT16 Classification; ///< State classification
82 UINT32 CapsAndSettings; ///< State capability and settings
83 UINT32 Vclk; ///< UVD VCLK
84 UINT32 Dclk; ///< UVD DCLK
85 UINT8 NumberOfDpmStates; ///< Number of DPM states
86 UINT8 DpmSatesArray[MAX_NUM_OF_DPM_STATES]; ///< DPM state index array
87} SW_STATE;
88
89/// DPM state
90typedef struct {
91 BOOLEAN Valid; ///< State valid
92 UINT32 Sclk; ///< Sclk in kHz
93 UINT8 Vid; ///< VID index
efdesign9884cbce22011-08-04 12:09:17 -060094 UINT16 Tdp; ///< Tdp limit
Frank Vibrans2b4c8312011-02-14 18:30:54 +000095} DPM_STATE;
96
97/*----------------------------------------------------------------------------------------
98 * 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
99 *----------------------------------------------------------------------------------------
100 */
efdesign9884cbce22011-08-04 12:09:17 -0600101UINT16
102GfxPowerPlayLocateTdp (
103 IN PP_FUSE_ARRAY *PpFuses,
104 IN UINT32 Sclk,
105 IN AMD_CONFIG_PARAMS *StdHeader
106 );
107
108SW_STATE*
109GfxPowerPlayCreateSwState (
110 IN OUT SW_STATE *SwStateArray
111 );
112
113UINT8
114GfxPowerPlayCreateDpmState (
115 IN DPM_STATE *DpmStateArray,
116 IN UINT32 Sclk,
117 IN UINT8 Vid,
118 IN UINT16 Tdp
119 );
120
121UINT8
122GfxPowerPlayAddDpmState (
123 IN DPM_STATE *DpmStateArray,
124 IN UINT32 Sclk,
125 IN UINT8 Vid,
126 IN UINT16 Tdp
127 );
128
129VOID
130GfxPowerPlayAddDpmStateToSwState (
131 IN OUT SW_STATE *SwStateArray,
132 IN UINT8 DpmStateIndex
133 );
134
135UINT32
136GfxPowerPlayCopyStateInfo (
137 IN OUT STATE_ARRAY *StateArray,
138 IN SW_STATE *SwStateArray,
139 IN AMD_CONFIG_PARAMS *StdHeader
140 );
141
142UINT32
143GfxPowerPlayCopyClockInfo (
144 IN CLOCK_INFO_ARRAY *ClockInfoArray,
145 IN DPM_STATE *DpmStateArray,
146 IN AMD_CONFIG_PARAMS *StdHeader
147 );
148
149UINT32
150GfxPowerPlayCopyNonClockInfo (
151 IN NON_CLOCK_INFO_ARRAY *NonClockInfoArray,
152 IN SW_STATE *SwStateArray,
153 IN AMD_CONFIG_PARAMS *StdHeader
154 );
155
156BOOLEAN
157GfxPowerPlayIsFusedStateValid (
158 IN UINT8 Index,
159 IN PP_FUSE_ARRAY *PpFuses,
160 IN GFX_PLATFORM_CONFIG *Gfx
161 );
162
163UINT16
164GfxPowerPlayGetClassificationFromFuses (
165 IN UINT8 Index,
166 IN PP_FUSE_ARRAY *PpFuses,
167 IN GFX_PLATFORM_CONFIG *Gfx
168 );
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000169
170VOID
171GfxIntegratedDebugDumpPpTable (
172 IN ATOM_PPLIB_POWERPLAYTABLE3 *PpTable,
173 IN GFX_PLATFORM_CONFIG *Gfx
174 );
175
176/*----------------------------------------------------------------------------------------*/
177/**
efdesign9884cbce22011-08-04 12:09:17 -0600178 * Locate existing tdp
179 *
180 *
181 * @param[in ] PpFuses Pointer to PP_FUSE_ARRAY
182 * @param[in] Sclk Sclk in 10kHz
183 * @param[in] StdHeader Standard configuration header
184 * @retval Tdp limit in DPM state array
185 */
186
187UINT16
188GfxPowerPlayLocateTdp (
189 IN PP_FUSE_ARRAY *PpFuses,
190 IN UINT32 Sclk,
191 IN AMD_CONFIG_PARAMS *StdHeader
192 )
193{
194 UINT8 Index;
195 UINT32 DpmIndex;
196 UINT32 DpmSclk;
197 UINT32 DeltaSclk;
198 UINT32 MinDeltaSclk;
199
200 DpmIndex = 0;
201 MinDeltaSclk = 0xFFFFFFFF;
202 for (Index = 0; Index < MAX_NUM_OF_FUSED_DPM_STATES; Index++) {
203 if (PpFuses->SclkDpmDid[Index] != 0) {
204 DpmSclk = GfxFmCalculateClock (PpFuses->SclkDpmDid[Index], StdHeader);
205 DeltaSclk = (DpmSclk > Sclk) ? (DpmSclk - Sclk) : (Sclk - DpmSclk);
206 if (DeltaSclk < MinDeltaSclk) {
Edward O'Callaghan8dd407a2014-05-15 19:37:24 +1000207 MinDeltaSclk = DeltaSclk;
efdesign9884cbce22011-08-04 12:09:17 -0600208 DpmIndex = Index;
209 }
210 }
211 }
212 return PpFuses->SclkDpmTdpLimit[DpmIndex];
213}
214
215/*----------------------------------------------------------------------------------------*/
216/**
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000217 * Create new software state
218 *
219 *
220 * @param[in, out] SwStateArray Pointer to SW state array
221 * @retval Pointer to state entry in SW state array
222 */
223
224SW_STATE*
225GfxPowerPlayCreateSwState (
226 IN OUT SW_STATE *SwStateArray
227 )
228{
229 UINTN Index;
230 for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
231 if (SwStateArray[Index].Valid == FALSE) {
232 SwStateArray[Index].Valid = TRUE;
233 return &SwStateArray[Index];
234 }
235 }
236 return NULL;
237}
238
239/*----------------------------------------------------------------------------------------*/
240/**
241 * Create new DPM state
242 *
243 *
244 * @param[in, out] DpmStateArray Pointer to DPM state array
245 * @param[in] Sclk SCLK in kHz
246 * @param[in] Vid Vid index
efdesign9884cbce22011-08-04 12:09:17 -0600247 * @param[in] Tdp Tdp limit
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000248 * @retval Index of state entry in DPM state array
249 */
250
251UINT8
252GfxPowerPlayCreateDpmState (
253 IN DPM_STATE *DpmStateArray,
254 IN UINT32 Sclk,
efdesign9884cbce22011-08-04 12:09:17 -0600255 IN UINT8 Vid,
256 IN UINT16 Tdp
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000257 )
258{
259 UINT8 Index;
260 for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
261 if (DpmStateArray[Index].Valid == FALSE) {
262 DpmStateArray[Index].Sclk = Sclk;
263 DpmStateArray[Index].Vid = Vid;
264 DpmStateArray[Index].Valid = TRUE;
efdesign9884cbce22011-08-04 12:09:17 -0600265 DpmStateArray[Index].Tdp = Tdp;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000266 return Index;
267 }
268 }
269 return 0;
270}
271
272/*----------------------------------------------------------------------------------------*/
273/**
274 * Locate existing or Create new DPM state
275 *
276 *
277 * @param[in, out] DpmStateArray Pointer to DPM state array
278 * @param[in] Sclk SCLK in kHz
279 * @param[in] Vid Vid index
efdesign9884cbce22011-08-04 12:09:17 -0600280 * @param[in] Tdp Tdp limit
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000281 * @retval Index of state entry in DPM state array
282 */
283
284UINT8
285GfxPowerPlayAddDpmState (
286 IN DPM_STATE *DpmStateArray,
287 IN UINT32 Sclk,
efdesign9884cbce22011-08-04 12:09:17 -0600288 IN UINT8 Vid,
289 IN UINT16 Tdp
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000290 )
291{
292 UINT8 Index;
293 for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
294 if (DpmStateArray[Index].Valid && Sclk == DpmStateArray[Index].Sclk && Vid == DpmStateArray[Index].Vid) {
295 return Index;
296 }
297 }
efdesign9884cbce22011-08-04 12:09:17 -0600298 return GfxPowerPlayCreateDpmState (DpmStateArray, Sclk, Vid, Tdp);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000299}
300
301/*----------------------------------------------------------------------------------------*/
302/**
303 * Add reference to DPM state for SW state
304 *
305 *
306 * @param[in, out] SwStateArray Pointer to SW state array
307 * @param[in] DpmStateIndex DPM state index
308 */
309
310VOID
311GfxPowerPlayAddDpmStateToSwState (
312 IN OUT SW_STATE *SwStateArray,
313 IN UINT8 DpmStateIndex
314 )
315{
316 SwStateArray->DpmSatesArray[SwStateArray->NumberOfDpmStates++] = DpmStateIndex;
317}
318
319/*----------------------------------------------------------------------------------------*/
320/**
321 * Copy SW state info to PPTable
322 *
323 *
324 * @param[out] StateArray Pointer to PPtable SW state array
325 * @param[in] SwStateArray Pointer to SW state array
326 * @param[in] StdHeader Standard configuration header
327 */
328UINT32
329GfxPowerPlayCopyStateInfo (
330 IN OUT STATE_ARRAY *StateArray,
331 IN SW_STATE *SwStateArray,
332 IN AMD_CONFIG_PARAMS *StdHeader
333 )
334{
335 UINT8 Index;
336 UINT8 SwStateIndex;
337 ATOM_PPLIB_STATE_V2 *States;
338 States = &StateArray->States[0];
339 SwStateIndex = 0;
340 for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
341 if (SwStateArray[Index].Valid && SwStateArray[Index].NumberOfDpmStates != 0) {
342 States->nonClockInfoIndex = SwStateIndex;
343 States->ucNumDPMLevels = SwStateArray[Index].NumberOfDpmStates;
344 LibAmdMemCopy (
345 &States->ClockInfoIndex[0],
346 SwStateArray[Index].DpmSatesArray,
347 SwStateArray[Index].NumberOfDpmStates,
348 StdHeader
349 );
350 States = (ATOM_PPLIB_STATE_V2*) ((UINT8*) States + sizeof (ATOM_PPLIB_STATE_V2) + sizeof (UINT8) * (States->ucNumDPMLevels - 1));
351 SwStateIndex++;
352 }
353 }
354 StateArray->ucNumEntries = SwStateIndex;
355 return (UINT32) ((UINT8*) States - (UINT8*) StateArray);
356}
357/*----------------------------------------------------------------------------------------*/
358/**
359 * Copy clock info to PPTable
360 *
361 *
362 * @param[out] ClockInfoArray Pointer to clock info array
363 * @param[in] DpmStateArray Pointer to DPM state array
364 * @param[in] StdHeader Standard configuration header
365 */
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000366UINT32
367GfxPowerPlayCopyClockInfo (
368 IN CLOCK_INFO_ARRAY *ClockInfoArray,
369 IN DPM_STATE *DpmStateArray,
370 IN AMD_CONFIG_PARAMS *StdHeader
371 )
372{
373 UINT8 Index;
374 UINT8 ClkStateIndex;
375 ClkStateIndex = 0;
376 for (Index = 0; Index < MAX_NUM_OF_DPM_STATES; Index++) {
377 if (DpmStateArray[Index].Valid == TRUE) {
378 ClockInfoArray->ClockInfo[ClkStateIndex].ucEngineClockHigh = (UINT8) (DpmStateArray[Index].Sclk >> 16);
379 ClockInfoArray->ClockInfo[ClkStateIndex].usEngineClockLow = (UINT16) (DpmStateArray[Index].Sclk);
380 ClockInfoArray->ClockInfo[ClkStateIndex].vddcIndex = DpmStateArray[Index].Vid;
efdesign9884cbce22011-08-04 12:09:17 -0600381 ClockInfoArray->ClockInfo[ClkStateIndex].tdpLimit = DpmStateArray[Index].Tdp;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000382 ClkStateIndex++;
383 }
384 }
385 ClockInfoArray->ucNumEntries = ClkStateIndex;
386 ClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO);
387 return sizeof (CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO) * (ClkStateIndex) - sizeof (ATOM_PPLIB_SUMO_CLOCK_INFO);
388}
389
390/*----------------------------------------------------------------------------------------*/
391/**
392 * Copy non clock info to PPTable
393 *
394 *
395 * @param[out] NonClockInfoArray Pointer to PPtable Non clock array
396 * @param[in] SwStateArray Pointer to SW state array
397 * @param[in] StdHeader Standard configuration header
398 */
399
400UINT32
401GfxPowerPlayCopyNonClockInfo (
402 IN NON_CLOCK_INFO_ARRAY *NonClockInfoArray,
403 IN SW_STATE *SwStateArray,
404 IN AMD_CONFIG_PARAMS *StdHeader
405 )
406{
407 UINT8 Index;
408 UINT8 NonClkStateIndex;
409 NonClkStateIndex = 0;
410 for (Index = 0; Index < MAX_NUM_OF_SW_STATES; Index++) {
411 if (SwStateArray[Index].Valid && SwStateArray[Index].NumberOfDpmStates != 0) {
412 NonClockInfoArray->NonClockInfo[NonClkStateIndex].usClassification = SwStateArray[Index].Classification;
413 NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulCapsAndSettings = SwStateArray[Index].CapsAndSettings;
414 NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulDCLK = SwStateArray[Index].Dclk;
415 NonClockInfoArray->NonClockInfo[NonClkStateIndex].ulVCLK = SwStateArray[Index].Vclk;
416 NonClkStateIndex++;
417 }
418 }
419 NonClockInfoArray->ucNumEntries = NonClkStateIndex;
420 NonClockInfoArray->ucEntrySize = sizeof (ATOM_PPLIB_NONCLOCK_INFO);
421 return sizeof (NON_CLOCK_INFO_ARRAY) + sizeof (ATOM_PPLIB_NONCLOCK_INFO) * NonClkStateIndex - sizeof (ATOM_PPLIB_NONCLOCK_INFO);
422}
423
424/*----------------------------------------------------------------------------------------*/
425/**
426 * Check if fused state valid
427 *
428 *
429 * @param[out] Index State index
430 * @param[in] PpFuses Pointer to fuse table
431 * @param[in] Gfx Gfx configuration info
432 * @retval TRUE State is valid
433 */
434BOOLEAN
435GfxPowerPlayIsFusedStateValid (
436 IN UINT8 Index,
437 IN PP_FUSE_ARRAY *PpFuses,
438 IN GFX_PLATFORM_CONFIG *Gfx
439 )
440{
441 BOOLEAN Result;
442 Result = FALSE;
443 if (PpFuses->SclkDpmValid[Index] != 0) {
444 Result = TRUE;
445 if (PpFuses->PolicyLabel[Index] == POLICY_LABEL_BATTERY && (Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) == 0) {
446 Result = FALSE;
447 }
448 }
449 return Result;
450}
451
452/*----------------------------------------------------------------------------------------*/
453/**
454 * Get SW state calssification from fuses
455 *
456 *
457 * @param[out] Index State index
458 * @param[in] PpFuses Pointer to fuse table
459 * @param[in] Gfx Gfx configuration info
460 * @retval State classification
461 */
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000462UINT16
463GfxPowerPlayGetClassificationFromFuses (
464 IN UINT8 Index,
465 IN PP_FUSE_ARRAY *PpFuses,
466 IN GFX_PLATFORM_CONFIG *Gfx
467 )
468{
469 UINT16 Classification;
470 Classification = 0;
471 switch (PpFuses->PolicyFlags[Index]) {
472 case 0x1:
473 Classification |= ATOM_PPLIB_CLASSIFICATION_NONUVDSTATE;
474 break;
475 case 0x2:
476 Classification |= ATOM_PPLIB_CLASSIFICATION_UVDSTATE;
477 break;
478 case 0x4:
479 //Possible SD + HD state
480 break;
481 case 0x8:
482 Classification |= ATOM_PPLIB_CLASSIFICATION_HDSTATE;
483 break;
484 case 0x10:
485 Classification |= ATOM_PPLIB_CLASSIFICATION_SDSTATE;
486 break;
487 default:
488 break;
489 }
490 switch (PpFuses->PolicyLabel[Index]) {
491 case POLICY_LABEL_BATTERY:
492 Classification |= ATOM_PPLIB_CLASSIFICATION_UI_BATTERY;
493 break;
494 case POLICY_LABEL_PERFORMANCE:
495 Classification |= ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE;
496 break;
497 default:
498 break;
499 }
500 return Classification;
501}
502
503/*----------------------------------------------------------------------------------------*/
504/**
505 * Build PP table
506 *
507 *
508 * @param[out] Buffer Buffer to create PP table
509 * @param[in] Gfx Gfx configuration info
510 * @retval AGESA_SUCCESS
511 * @retval AGESA_ERROR
512 */
513
514AGESA_STATUS
515GfxPowerPlayBuildTable (
516 OUT VOID *Buffer,
517 IN GFX_PLATFORM_CONFIG *Gfx
518 )
519{
520 ATOM_PPLIB_POWERPLAYTABLE3 *PpTable;
521 SW_STATE SwStateArray [MAX_NUM_OF_SW_STATES];
522 DPM_STATE DpmStateArray[MAX_NUM_OF_DPM_STATES];
523 UINT8 ClkStateIndex;
524 UINT8 DpmFuseIndex;
525 UINT8 Index;
526 UINT32 StateArrayLength;
527 UINT32 ClockArrayLength;
528 UINT32 NonClockArrayLength;
529 SW_STATE *State;
530 PP_FUSE_ARRAY *PpFuses;
efdesign9884cbce22011-08-04 12:09:17 -0600531 UINT32 Sclk;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000532
533 PpFuses = GnbLocateHeapBuffer (AMD_PP_FUSE_TABLE_HANDLE, GnbLibGetHeader (Gfx));
534 ASSERT (PpFuses != NULL);
535 if (PpFuses == NULL) {
536 return AGESA_ERROR;
537 }
538
539 PpTable = (ATOM_PPLIB_POWERPLAYTABLE3 *) Buffer;
540 LibAmdMemFill (SwStateArray, 0x00, sizeof (SwStateArray), GnbLibGetHeader (Gfx));
541 LibAmdMemFill (DpmStateArray, 0x00, sizeof (DpmStateArray), GnbLibGetHeader (Gfx));
542 // Create States from Fuses
543 for (Index = 0; Index < MAX_NUM_OF_FUSED_SW_STATES; Index++) {
544 if (GfxPowerPlayIsFusedStateValid (Index, PpFuses, Gfx)) {
545 //Create new SW State;
546 State = GfxPowerPlayCreateSwState (SwStateArray);
547 State->Classification = GfxPowerPlayGetClassificationFromFuses (Index, PpFuses, Gfx);
548 if ((State->Classification & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_UVDSTATE)) != 0) {
549 State->Vclk = (PpFuses->VclkDid[PpFuses->VclkDclkSel[Index]] != 0) ? GfxFmCalculateClock (PpFuses->VclkDid[PpFuses->VclkDclkSel[Index]], GnbLibGetHeader (Gfx)) : 0;
550 State->Dclk = (PpFuses->DclkDid[PpFuses->VclkDclkSel[Index]] != 0) ? GfxFmCalculateClock (PpFuses->DclkDid[PpFuses->VclkDclkSel[Index]], GnbLibGetHeader (Gfx)) : 0;
551 }
552 if ((State->Classification & 0x7) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) {
553 if (Gfx->AbmSupport != 0) {
554 State->CapsAndSettings |= ATOM_PPLIB_ENABLE_VARIBRIGHT;
555 }
556 if (Gfx->DynamicRefreshRate != 0) {
557 State->CapsAndSettings |= ATOM_PPLIB_ENABLE_DRR;
558 }
559 }
560 for (DpmFuseIndex = 0; DpmFuseIndex < MAX_NUM_OF_FUSED_DPM_STATES; DpmFuseIndex++) {
561 if ((PpFuses->SclkDpmValid[Index] & (1 << DpmFuseIndex)) != 0 ) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000562 Sclk = (PpFuses->SclkDpmDid[DpmFuseIndex] != 0) ? GfxFmCalculateClock (PpFuses->SclkDpmDid[DpmFuseIndex], GnbLibGetHeader (Gfx)) : 0;
563 if (Sclk != 0) {
efdesign9884cbce22011-08-04 12:09:17 -0600564 ClkStateIndex = GfxPowerPlayAddDpmState (DpmStateArray, Sclk, PpFuses->SclkDpmVid[DpmFuseIndex], PpFuses->SclkDpmTdpLimit[DpmFuseIndex]);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000565 GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
566 }
567 }
568 }
569 }
570 }
571 // Create Boot State
572 State = GfxPowerPlayCreateSwState (SwStateArray);
573 State->Classification = ATOM_PPLIB_CLASSIFICATION_BOOT;
efdesign9884cbce22011-08-04 12:09:17 -0600574 Sclk = 200 * 100;
575 ClkStateIndex = GfxPowerPlayAddDpmState (DpmStateArray, Sclk, 0, GfxPowerPlayLocateTdp (PpFuses, Sclk, GnbLibGetHeader (Gfx)));
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000576 GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
577
578 // Create Thermal State
579 State = GfxPowerPlayCreateSwState (SwStateArray);
580 State->Classification = ATOM_PPLIB_CLASSIFICATION_THERMAL;
efdesign9884cbce22011-08-04 12:09:17 -0600581 Sclk = GfxFmCalculateClock (PpFuses->SclkThermDid, GnbLibGetHeader (Gfx));
582 ClkStateIndex = GfxPowerPlayAddDpmState (DpmStateArray, Sclk, 0, GfxPowerPlayLocateTdp (PpFuses, Sclk, GnbLibGetHeader (Gfx)));
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000583 GfxPowerPlayAddDpmStateToSwState (State, ClkStateIndex);
584
585 //Copy state info to actual PP table
586 StateArrayLength = GfxPowerPlayCopyStateInfo (
587 &PpTable->StateArray,
588 SwStateArray,
589 GnbLibGetHeader (Gfx)
590 );
591 ClockArrayLength = GfxPowerPlayCopyClockInfo (
592 (CLOCK_INFO_ARRAY*) ((UINT8 *)&PpTable->StateArray + StateArrayLength),
593 DpmStateArray,
594 GnbLibGetHeader (Gfx)
595 );
596 NonClockArrayLength = GfxPowerPlayCopyNonClockInfo (
597 (NON_CLOCK_INFO_ARRAY*) ((UINT8 *)&PpTable->StateArray + StateArrayLength + ClockArrayLength),
598 SwStateArray,
599 GnbLibGetHeader (Gfx)
600 );
601 //Fill static info
602 PpTable->sHeader.ucTableFormatRevision = 6;
603 PpTable->sHeader.ucTableContentRevision = 1;
604 PpTable->ucDataRevision = PpFuses->PPlayTableRev;
605 PpTable->sThermalController.ucType = ATOM_PP_THERMALCONTROLLER_SUMO;
606 PpTable->sThermalController.ucFanParameters = ATOM_PP_FANPARAMETERS_NOFAN;
607 if ((Gfx->AmdPlatformType & AMD_PLATFORM_MOBILE) != 0) {
608 PpTable->ulPlatformCaps |= ATOM_PP_PLATFORM_CAP_POWERPLAY;
609 }
610 PpTable->usStateArrayOffset = offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray);
611 PpTable->usClockInfoArrayOffset = (USHORT) (offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray) + StateArrayLength);
612 PpTable->usNonClockInfoArrayOffset = (USHORT) (offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray) + StateArrayLength + ClockArrayLength);
613 PpTable->sHeader.usStructureSize = (USHORT) (offsetof (ATOM_PPLIB_POWERPLAYTABLE3, StateArray) + StateArrayLength + ClockArrayLength + NonClockArrayLength);
614 PpTable->usFormatID = 7;
615 GNB_DEBUG_CODE (
616 GfxIntegratedDebugDumpPpTable (PpTable, Gfx);
617 );
618 return AGESA_SUCCESS;
619}
620
621/*----------------------------------------------------------------------------------------*/
622/**
623 * Dump PP table
624 *
625 *
626 *
627 * @param[in] PpTable Power Play table
628 * @param[in] Gfx Gfx configuration info
629 */
630
631VOID
632GfxIntegratedDebugDumpPpTable (
633 IN ATOM_PPLIB_POWERPLAYTABLE3 *PpTable,
634 IN GFX_PLATFORM_CONFIG *Gfx
635 )
636{
637 UINTN Index;
638 UINTN DpmIndex;
639 ATOM_PPLIB_STATE_V2 *StatesPtr;
640 NON_CLOCK_INFO_ARRAY *NonClockInfoArrayPtr;
641 CLOCK_INFO_ARRAY *ClockInfoArrayPtr;
642 IDS_HDT_CONSOLE (GFX_MISC, " < --- Power Play Table ------ > \n");
643
644 IDS_HDT_CONSOLE (GFX_MISC, " Table Revision = %d\n", PpTable->ucDataRevision
645 );
646 StatesPtr = PpTable->StateArray.States;
647 NonClockInfoArrayPtr = (NON_CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usNonClockInfoArrayOffset);
648 ClockInfoArrayPtr = (CLOCK_INFO_ARRAY *) ((UINT8 *) PpTable + PpTable->usClockInfoArrayOffset);
649 for (Index = 0; Index < PpTable->StateArray.ucNumEntries; Index++) {
650 IDS_HDT_CONSOLE (GFX_MISC, " State #%d\n", Index + 1
651 );
652 IDS_HDT_CONSOLE (GFX_MISC, " Classification 0x%x\n",
653 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].usClassification
654 );
655 IDS_HDT_CONSOLE (GFX_MISC, " VCLK = %dkHz\n",
656 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].ulVCLK
657 );
658 IDS_HDT_CONSOLE (GFX_MISC, " DCLK = %dkHz\n",
659 NonClockInfoArrayPtr->NonClockInfo[StatesPtr->nonClockInfoIndex].ulDCLK
660 );
661 IDS_HDT_CONSOLE (GFX_MISC, " DPM State Index: ");
662 for (DpmIndex = 0; DpmIndex < StatesPtr->ucNumDPMLevels; DpmIndex++) {
663 IDS_HDT_CONSOLE (GFX_MISC, "%d ",
664 StatesPtr->ClockInfoIndex [DpmIndex]
665 );
666 }
667 IDS_HDT_CONSOLE (GFX_MISC, "\n");
668 StatesPtr = (ATOM_PPLIB_STATE_V2 *) ((UINT8 *) StatesPtr + sizeof (ATOM_PPLIB_STATE_V2) + StatesPtr->ucNumDPMLevels - 1);
669 }
670 for (Index = 0; Index < ClockInfoArrayPtr->ucNumEntries; Index++) {
671 UINT32 Sclk;
672 Sclk = ClockInfoArrayPtr->ClockInfo[Index].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[Index].ucEngineClockHigh << 16);
673 IDS_HDT_CONSOLE (GFX_MISC, " DPM State #%d\n",
674 Index
675 );
676 IDS_HDT_CONSOLE (GFX_MISC, " SCLK = %d\n",
677 ClockInfoArrayPtr->ClockInfo[Index].usEngineClockLow | (ClockInfoArrayPtr->ClockInfo[Index].ucEngineClockHigh << 16)
678 );
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000679 IDS_HDT_CONSOLE (GFX_MISC, " VID index = %d\n",
680 ClockInfoArrayPtr->ClockInfo[Index].vddcIndex
681 );
efdesign9884cbce22011-08-04 12:09:17 -0600682 IDS_HDT_CONSOLE (GFX_MISC, " tdpLimit = %d\n",
683 ClockInfoArrayPtr->ClockInfo[Index].tdpLimit
684 );
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000685 }
686}