1 /****************************************************************************
3 * Copyright (C) 2005 - 2014 by Vivante Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the license, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *****************************************************************************/
23 #include "gc_hal_kernel.h"
24 #include "gc_hal_kernel_hardware_command_vg.h"
28 #define _GC_OBJ_ZONE gcvZONE_HARDWARE
32 gcvPOWER_FLAG_INITIALIZE = 1 << 0,
33 gcvPOWER_FLAG_STALL = 1 << 1,
34 gcvPOWER_FLAG_STOP = 1 << 2,
35 gcvPOWER_FLAG_START = 1 << 3,
36 gcvPOWER_FLAG_RELEASE = 1 << 4,
37 gcvPOWER_FLAG_DELAY = 1 << 5,
38 gcvPOWER_FLAG_SAVE = 1 << 6,
39 gcvPOWER_FLAG_ACQUIRE = 1 << 7,
40 gcvPOWER_FLAG_POWER_OFF = 1 << 8,
41 gcvPOWER_FLAG_CLOCK_OFF = 1 << 9,
42 gcvPOWER_FLAG_CLOCK_ON = 1 << 10,
43 gcvPOWER_FLAG_NOP = 1 << 11,
47 /******************************************************************************\
48 ********************************* Support Code *********************************
49 \******************************************************************************/
55 gctUINT32 control, idle;
59 gcmkONERROR(gckOS_ReadRegisterEx(Os,
66 /* Disable clock gating. */
67 gcmkONERROR(gckOS_WriteRegisterEx(Os,
72 /* Wait for clock being stable. */
73 gcmkONERROR(gckOS_Delay(Os, 1));
75 /* Isolate the GPU. */
76 control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
78 gcmkONERROR(gckOS_WriteRegisterEx(Os,
84 gcmkONERROR(gckOS_WriteRegisterEx(Os,
87 ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
90 gcmkONERROR(gckOS_Delay(Os, 1));
92 /* Reset soft reset bit. */
93 gcmkONERROR(gckOS_WriteRegisterEx(Os,
96 ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 12:12) - (0 ? 12:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 12:12) - (0 ? 12:12) + 1))))))) << (0 ? 12:12)))));
98 /* Reset GPU isolation. */
99 control = ((((gctUINT32) (control)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 19:19) - (0 ? 19:19) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 19:19) - (0 ? 19:19) + 1))))))) << (0 ? 19:19)));
101 gcmkONERROR(gckOS_WriteRegisterEx(Os,
106 /* Read idle register. */
107 gcmkONERROR(gckOS_ReadRegisterEx(Os,
112 if ((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) == 0)
117 /* Read reset register. */
118 gcmkONERROR(gckOS_ReadRegisterEx(Os,
123 if (((((((gctUINT32) (control)) >> (0 ? 16:16)) & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1)))))) ) == 0)
124 || ((((((gctUINT32) (control)) >> (0 ? 17:17)) & ((gctUINT32) ((((1 ? 17:17) - (0 ? 17:17) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 17:17) - (0 ? 17:17) + 1)))))) ) == 0)
139 /* Return the error. */
147 OUT gceCHIPMODEL * ChipModel,
148 OUT gctUINT32 * ChipRevision,
149 OUT gctUINT32 * ChipFeatures,
150 OUT gctUINT32 * ChipMinorFeatures,
151 OUT gctUINT32 * ChipMinorFeatures2
155 gctUINT32 chipIdentity;
159 /* Read chip identity register. */
160 gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
162 /* Special case for older graphic cores. */
163 if (((((gctUINT32) (chipIdentity)) >> (0 ? 31:24) & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1)))))) == (0x01 & ((gctUINT32) ((((1 ? 31:24) - (0 ? 31:24) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:24) - (0 ? 31:24) + 1))))))))
166 *ChipRevision = (((((gctUINT32) (chipIdentity)) >> (0 ? 15:12)) & ((gctUINT32) ((((1 ? 15:12) - (0 ? 15:12) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:12) - (0 ? 15:12) + 1)))))) );
171 /* Read chip identity register. */
172 gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
174 (gctUINT32 *) ChipModel));
176 /* Read CHIP_REV register. */
177 gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
182 /* Read chip feature register. */
183 gcmkERR_BREAK(gckOS_ReadRegisterEx(
184 Os, gcvCORE_VG, 0x0001C, ChipFeatures
187 /* Read chip minor feature register. */
188 gcmkERR_BREAK(gckOS_ReadRegisterEx(
189 Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
192 /* Read chip minor feature register #2. */
193 gcmkERR_BREAK(gckOS_ReadRegisterEx(
194 Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
200 "ChipRevision=0x%08X\n"
201 "ChipFeatures=0x%08X\n"
202 "ChipMinorFeatures=0x%08X\n"
203 "ChipMinorFeatures2=0x%08X\n",
216 /* Return the status. */
220 #if gcdPOWEROFF_TIMEOUT
222 _VGPowerTimerFunction(
226 gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
228 gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
232 /******************************************************************************\
233 ****************************** gckVGHARDWARE API code *****************************
234 \******************************************************************************/
236 /*******************************************************************************
238 ** gckVGHARDWARE_Construct
240 ** Construct a new gckVGHARDWARE object.
245 ** Pointer to an initialized gckOS object.
249 ** gckVGHARDWARE * Hardware
250 ** Pointer to a variable that will hold the pointer to the gckVGHARDWARE
254 gckVGHARDWARE_Construct(
256 OUT gckVGHARDWARE * Hardware
259 gckVGHARDWARE hardware = gcvNULL;
261 gceCHIPMODEL chipModel;
262 gctUINT32 chipRevision;
263 gctUINT32 chipFeatures;
264 gctUINT32 chipMinorFeatures;
265 gctUINT32 chipMinorFeatures2;
267 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
269 /* Verify the arguments. */
270 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
271 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
275 gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
277 status = _ResetGPU(Os);
279 if (status != gcvSTATUS_OK)
281 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
282 "_ResetGPU failed: status=%d\n", status);
285 /* Identify the hardware. */
286 gcmkERR_BREAK(_IdentifyHardware(Os,
287 &chipModel, &chipRevision,
288 &chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
291 /* Allocate the gckVGHARDWARE object. */
292 gcmkERR_BREAK(gckOS_Allocate(Os,
293 gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
296 /* Initialize the gckVGHARDWARE object. */
297 hardware->object.type = gcvOBJ_HARDWARE;
300 /* Set chip identity. */
301 hardware->chipModel = chipModel;
302 hardware->chipRevision = chipRevision;
303 hardware->chipFeatures = chipFeatures;
304 hardware->chipMinorFeatures = chipMinorFeatures;
305 hardware->chipMinorFeatures2 = chipMinorFeatures2;
307 hardware->powerMutex = gcvNULL;
308 hardware->chipPowerState = gcvPOWER_ON;
309 hardware->chipPowerStateGlobal = gcvPOWER_ON;
310 hardware->clockState = gcvTRUE;
311 hardware->powerState = gcvTRUE;
313 #if gcdPOWEROFF_TIMEOUT
314 hardware->powerOffTime = 0;
315 hardware->powerOffTimeout = gcdPOWEROFF_TIMEOUT;
317 gcmkVERIFY_OK(gckOS_CreateTimer(Os,
318 _VGPowerTimerFunction,
319 (gctPOINTER)hardware,
320 &hardware->powerOffTimer));
323 /* Determine whether FE 2.0 is present. */
324 hardware->fe20 = ((((gctUINT32) (hardware->chipFeatures)) >> (0 ? 28:28) & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 28:28) - (0 ? 28:28) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 28:28) - (0 ? 28:28) + 1)))))));
326 /* Determine whether VG 2.0 is present. */
327 hardware->vg20 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 13:13) & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 13:13) - (0 ? 13:13) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 13:13) - (0 ? 13:13) + 1)))))));
329 /* Determine whether VG 2.1 is present. */
330 hardware->vg21 = ((((gctUINT32) (hardware->chipMinorFeatures)) >> (0 ? 18:18) & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))) == (0x1 & ((gctUINT32) ((((1 ? 18:18) - (0 ? 18:18) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 18:18) - (0 ? 18:18) + 1)))))));
332 /* Set default event mask. */
333 hardware->eventMask = 0xFFFFFFFF;
335 gcmkERR_BREAK(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
337 /* Set fast clear to auto. */
338 gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
340 gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
342 /* Enable power management by default. */
343 hardware->powerManagement = gcvTRUE;
345 /* Return pointer to the gckVGHARDWARE object. */
346 *Hardware = hardware;
354 #if gcdPOWEROFF_TIMEOUT
355 if (hardware->powerOffTimer != gcvNULL)
357 gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
358 gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
362 gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
364 if (hardware != gcvNULL && hardware->pageTableDirty != gcvNULL)
366 gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
369 if (hardware != gcvNULL)
371 gcmkVERIFY_OK(gckOS_Free(Os, hardware));
375 /* Return the status. */
379 /*******************************************************************************
381 ** gckVGHARDWARE_Destroy
383 ** Destroy an gckVGHARDWARE object.
387 ** gckVGHARDWARE Hardware
388 ** Pointer to the gckVGHARDWARE object that needs to be destroyed.
395 gckVGHARDWARE_Destroy(
396 IN gckVGHARDWARE Hardware
400 gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
401 /* Verify the arguments. */
402 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
404 /* Mark the object as unknown. */
405 Hardware->object.type = gcvOBJ_UNKNOWN;
407 if (Hardware->powerMutex != gcvNULL)
409 gcmkVERIFY_OK(gckOS_DeleteMutex(
410 Hardware->os, Hardware->powerMutex));
413 #if gcdPOWEROFF_TIMEOUT
414 gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
415 gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
418 if (Hardware->pageTableDirty != gcvNULL)
420 gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
423 /* Free the object. */
424 status = gckOS_Free(Hardware->os, Hardware);
429 /*******************************************************************************
431 ** gckVGHARDWARE_QueryMemory
433 ** Query the amount of memory available on the hardware.
437 ** gckVGHARDWARE Hardware
438 ** Pointer to the gckVGHARDWARE object.
442 ** gctSIZE_T * InternalSize
443 ** Pointer to a variable that will hold the size of the internal video
444 ** memory in bytes. If 'InternalSize' is gcvNULL, no information of the
445 ** internal memory will be returned.
447 ** gctUINT32 * InternalBaseAddress
448 ** Pointer to a variable that will hold the hardware's base address for
449 ** the internal video memory. This pointer cannot be gcvNULL if
450 ** 'InternalSize' is also non-gcvNULL.
452 ** gctUINT32 * InternalAlignment
453 ** Pointer to a variable that will hold the hardware's base address for
454 ** the internal video memory. This pointer cannot be gcvNULL if
455 ** 'InternalSize' is also non-gcvNULL.
457 ** gctSIZE_T * ExternalSize
458 ** Pointer to a variable that will hold the size of the external video
459 ** memory in bytes. If 'ExternalSize' is gcvNULL, no information of the
460 ** external memory will be returned.
462 ** gctUINT32 * ExternalBaseAddress
463 ** Pointer to a variable that will hold the hardware's base address for
464 ** the external video memory. This pointer cannot be gcvNULL if
465 ** 'ExternalSize' is also non-gcvNULL.
467 ** gctUINT32 * ExternalAlignment
468 ** Pointer to a variable that will hold the hardware's base address for
469 ** the external video memory. This pointer cannot be gcvNULL if
470 ** 'ExternalSize' is also non-gcvNULL.
472 ** gctUINT32 * HorizontalTileSize
473 ** Number of horizontal pixels per tile. If 'HorizontalTileSize' is
474 ** gcvNULL, no horizontal pixel per tile will be returned.
476 ** gctUINT32 * VerticalTileSize
477 ** Number of vertical pixels per tile. If 'VerticalTileSize' is
478 ** gcvNULL, no vertical pixel per tile will be returned.
481 gckVGHARDWARE_QueryMemory(
482 IN gckVGHARDWARE Hardware,
483 OUT gctSIZE_T * InternalSize,
484 OUT gctUINT32 * InternalBaseAddress,
485 OUT gctUINT32 * InternalAlignment,
486 OUT gctSIZE_T * ExternalSize,
487 OUT gctUINT32 * ExternalBaseAddress,
488 OUT gctUINT32 * ExternalAlignment,
489 OUT gctUINT32 * HorizontalTileSize,
490 OUT gctUINT32 * VerticalTileSize
493 gcmkHEADER_ARG("Hardware=0x%x InternalSize=0x%x InternalBaseAddress=0x%x InternalAlignment=0x%x"
494 "ExternalSize=0x%x ExternalBaseAddress=0x%x ExternalAlignment=0x%x HorizontalTileSize=0x%x VerticalTileSize=0x%x",
495 Hardware, InternalSize, InternalBaseAddress, InternalAlignment,
496 ExternalSize, ExternalBaseAddress, ExternalAlignment, HorizontalTileSize, VerticalTileSize);
498 /* Verify the arguments. */
499 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
501 if (InternalSize != gcvNULL)
503 /* No internal memory. */
507 if (ExternalSize != gcvNULL)
509 /* No external memory. */
513 if (HorizontalTileSize != gcvNULL)
516 *HorizontalTileSize = 4;
519 if (VerticalTileSize != gcvNULL)
522 *VerticalTileSize = 4;
530 /*******************************************************************************
532 ** gckVGHARDWARE_QueryChipIdentity
534 ** Query the identity of the hardware.
538 ** gckVGHARDWARE Hardware
539 ** Pointer to the gckVGHARDWARE object.
543 ** gceCHIPMODEL * ChipModel
544 ** If 'ChipModel' is not gcvNULL, the variable it points to will
545 ** receive the model of the chip.
547 ** gctUINT32 * ChipRevision
548 ** If 'ChipRevision' is not gcvNULL, the variable it points to will
549 ** receive the revision of the chip.
551 ** gctUINT32 * ChipFeatures
552 ** If 'ChipFeatures' is not gcvNULL, the variable it points to will
553 ** receive the feature set of the chip.
555 ** gctUINT32 * ChipMinorFeatures
556 ** If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
557 ** will receive the minor feature set of the chip.
559 ** gctUINT32 * ChipMinorFeatures2
560 ** If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
561 ** will receive the minor feature set of the chip.
565 gckVGHARDWARE_QueryChipIdentity(
566 IN gckVGHARDWARE Hardware,
567 OUT gceCHIPMODEL * ChipModel,
568 OUT gctUINT32 * ChipRevision,
569 OUT gctUINT32* ChipFeatures,
570 OUT gctUINT32* ChipMinorFeatures,
571 OUT gctUINT32* ChipMinorFeatures2
574 gcmkHEADER_ARG("Hardware=0x%x ChipModel=0x%x ChipRevision=0x%x ChipFeatures = 0x%x ChipMinorFeatures = 0x%x ChipMinorFeatures2 = 0x%x",
575 Hardware, ChipModel, ChipRevision, ChipFeatures, ChipMinorFeatures, ChipMinorFeatures2);
577 /* Verify the arguments. */
578 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
580 /* Return chip model. */
581 if (ChipModel != gcvNULL)
583 *ChipModel = Hardware->chipModel;
586 /* Return revision number. */
587 if (ChipRevision != gcvNULL)
589 *ChipRevision = Hardware->chipRevision;
592 /* Return feature set. */
593 if (ChipFeatures != gcvNULL)
595 gctUINT32 features = Hardware->chipFeatures;
597 if ((((((gctUINT32) (features)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
599 features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) ((gctUINT32) (Hardware->allowFastClear) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)));
602 /* Mark 2D pipe as available for GC500.0 since it did not have this *\
604 if ((Hardware->chipModel == gcv500)
605 && (Hardware->chipRevision == 0)
608 features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
611 /* Mark 2D pipe as available for GC300 since it did not have this *\
613 if (Hardware->chipModel == gcv300)
615 features = ((((gctUINT32) (features)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)));
618 *ChipFeatures = features;
621 /* Return minor feature set. */
622 if (ChipMinorFeatures != gcvNULL)
624 *ChipMinorFeatures = Hardware->chipMinorFeatures;
627 /* Return minor feature set #2. */
628 if (ChipMinorFeatures2 != gcvNULL)
630 *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
638 /*******************************************************************************
640 ** gckVGHARDWARE_ConvertFormat
642 ** Convert an API format to hardware parameters.
646 ** gckVGHARDWARE Hardware
647 ** Pointer to the gckVGHARDWARE object.
649 ** gceSURF_FORMAT Format
650 ** API format to convert.
654 ** gctUINT32 * BitsPerPixel
655 ** Pointer to a variable that will hold the number of bits per pixel.
657 ** gctUINT32 * BytesPerTile
658 ** Pointer to a variable that will hold the number of bytes per tile.
661 gckVGHARDWARE_ConvertFormat(
662 IN gckVGHARDWARE Hardware,
663 IN gceSURF_FORMAT Format,
664 OUT gctUINT32 * BitsPerPixel,
665 OUT gctUINT32 * BytesPerTile
668 gctUINT32 bitsPerPixel;
669 gctUINT32 bytesPerTile;
671 gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
672 Hardware, Format, BitsPerPixel, BytesPerTile);
674 /* Verify the arguments. */
675 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
677 /* Dispatch on format. */
684 bytesPerTile = (1 * 4 * 4) / 8;
690 bytesPerTile = (4 * 4 * 4) / 8;
698 bytesPerTile = (8 * 4 * 4) / 8;
702 /* 12-bpp planar YUV formats. */
704 bytesPerTile = (12 * 4 * 4) / 8;
708 /* 12-bpp planar YUV formats. */
710 bytesPerTile = (12 * 4 * 4) / 8;
713 /* 4444 variations. */
714 case gcvSURF_X4R4G4B4:
715 case gcvSURF_A4R4G4B4:
716 case gcvSURF_R4G4B4X4:
717 case gcvSURF_R4G4B4A4:
718 case gcvSURF_B4G4R4X4:
719 case gcvSURF_B4G4R4A4:
720 case gcvSURF_X4B4G4R4:
721 case gcvSURF_A4B4G4R4:
723 /* 1555 variations. */
724 case gcvSURF_X1R5G5B5:
725 case gcvSURF_A1R5G5B5:
726 case gcvSURF_R5G5B5X1:
727 case gcvSURF_R5G5B5A1:
728 case gcvSURF_X1B5G5R5:
729 case gcvSURF_A1B5G5R5:
730 case gcvSURF_B5G5R5X1:
731 case gcvSURF_B5G5R5A1:
733 /* 565 variations. */
743 bytesPerTile = (16 * 4 * 4) / 8;
746 case gcvSURF_X8R8G8B8:
747 case gcvSURF_A8R8G8B8:
748 case gcvSURF_X8B8G8R8:
749 case gcvSURF_A8B8G8R8:
750 case gcvSURF_R8G8B8X8:
751 case gcvSURF_R8G8B8A8:
752 case gcvSURF_B8G8R8X8:
753 case gcvSURF_B8G8R8A8:
757 bytesPerTile = (32 * 4 * 4) / 8;
763 bytesPerTile = (32 * 4 * 4) / 8;
769 bytesPerTile = (4 * 4 * 4) / 8;
777 bytesPerTile = (8 * 4 * 4) / 8;
781 /* Invalid format. */
783 return gcvSTATUS_INVALID_ARGUMENT;
786 /* Set the result. */
787 if (BitsPerPixel != gcvNULL)
789 * BitsPerPixel = bitsPerPixel;
792 if (BytesPerTile != gcvNULL)
794 * BytesPerTile = bytesPerTile;
802 /*******************************************************************************
804 ** gckVGHARDWARE_SplitMemory
806 ** Split a hardware specific memory address into a pool and offset.
810 ** gckVGHARDWARE Hardware
811 ** Pointer to the gckVGHARDWARE object.
814 ** Address in hardware specific format.
819 ** Pointer to a variable that will hold the pool type for the address.
821 ** gctUINT32 * Offset
822 ** Pointer to a variable that will hold the offset for the address.
825 gckVGHARDWARE_SplitMemory(
826 IN gckVGHARDWARE Hardware,
827 IN gctUINT32 Address,
829 OUT gctUINT32 * Offset
832 gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Pool=0x%x Offset = 0x%x",
833 Hardware, Address, Pool, Offset);
834 /* Verify the arguments. */
835 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
836 gcmkVERIFY_ARGUMENT(Pool != gcvNULL);
837 gcmkVERIFY_ARGUMENT(Offset != gcvNULL);
839 /* Dispatch on memory type. */
840 switch ((((((gctUINT32) (Address)) >> (0 ? 1:0)) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1)))))) ))
844 *Pool = gcvPOOL_SYSTEM;
848 /* Virtual memory. */
849 *Pool = gcvPOOL_VIRTUAL;
853 /* Invalid memory type. */
855 return gcvSTATUS_INVALID_ARGUMENT;
858 /* Return offset of address. */
859 *Offset = ((((gctUINT32) (Address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) ((gctUINT32) (0) & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
866 /*******************************************************************************
868 ** gckVGHARDWARE_Execute
870 ** Kickstart the hardware's command processor with an initialized command
875 ** gckVGHARDWARE Hardware
876 ** Pointer to the gckVGHARDWARE object.
879 ** Address of the command buffer.
882 ** Number of command-sized data units to be executed.
889 gckVGHARDWARE_Execute(
890 IN gckVGHARDWARE Hardware,
891 IN gctUINT32 Address,
897 gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
898 Hardware, Address, Count);
900 /* Verify the arguments. */
901 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
905 /* Enable all events. */
906 gcmkERR_BREAK(gckOS_WriteRegisterEx(
915 /* Write address register. */
916 gcmkERR_BREAK(gckOS_WriteRegisterEx(
920 gcmkFIXADDRESS(Address)
923 /* Write control register. */
924 gcmkERR_BREAK(gckOS_WriteRegisterEx(
933 /* Write address register. */
934 gcmkERR_BREAK(gckOS_WriteRegisterEx(
938 gcmkFIXADDRESS(Address)
941 /* Write control register. */
942 gcmkERR_BREAK(gckOS_WriteRegisterEx(
946 ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 16:16) - (0 ? 16:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 16:16) - (0 ? 16:16) + 1))))))) << (0 ? 16:16))) |
947 ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (Count) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
959 /* Return the status. */
963 /*******************************************************************************
965 ** gckVGHARDWARE_AlignToTile
967 ** Align the specified width and height to tile boundaries.
971 ** gckVGHARDWARE Hardware
972 ** Pointer to an gckVGHARDWARE object.
975 ** Type of alignment.
978 ** Pointer to the width to be aligned. If 'Width' is gcvNULL, no width
981 ** gctUINT32 * Height
982 ** Pointer to the height to be aligned. If 'Height' is gcvNULL, no height
988 ** Pointer to a variable that will receive the aligned width.
990 ** gctUINT32 * Height
991 ** Pointer to a variable that will receive the aligned height.
994 gckVGHARDWARE_AlignToTile(
995 IN gckVGHARDWARE Hardware,
996 IN gceSURF_TYPE Type,
997 IN OUT gctUINT32 * Width,
998 IN OUT gctUINT32 * Height
1001 gcmkHEADER_ARG("Hardware=0x%x Type=0x%x Width=0x%x Height=0x%x",
1002 Hardware, Type, Width, Height);
1003 /* Verify the arguments. */
1004 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1006 if (Width != gcvNULL)
1008 /* Align the width. */
1009 *Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
1012 if (Height != gcvNULL)
1014 /* Special case for VG images. */
1015 if ((*Height == 0) && (Type == gcvSURF_IMAGE))
1021 /* Align the height. */
1022 *Height = gcmALIGN(*Height, 4);
1028 return gcvSTATUS_OK;
1031 /*******************************************************************************
1033 ** gckVGHARDWARE_ConvertLogical
1035 ** Convert a logical system address into a hardware specific address.
1039 ** gckVGHARDWARE Hardware
1040 ** Pointer to an gckVGHARDWARE object.
1042 ** gctPOINTER Logical
1043 ** Logical address to convert.
1045 ** gctBOOL InUserSpace
1046 ** gcvTRUE if the memory in user space.
1048 ** gctUINT32* Address
1049 ** Return hardware specific address.
1056 gckVGHARDWARE_ConvertLogical(
1057 IN gckVGHARDWARE Hardware,
1058 IN gctPOINTER Logical,
1059 IN gctBOOL InUserSpace,
1060 OUT gctUINT32 * Address
1066 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d Address=0x%x",
1067 Hardware, Logical, InUserSpace, Address);
1069 /* Verify the arguments. */
1070 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1071 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1072 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1076 /* Convert logical address into a physical address. */
1079 gcmkERR_BREAK(gckOS_UserLogicalToPhysical(
1080 Hardware->os, Logical, &address
1085 gcmkERR_BREAK(gckOS_GetPhysicalAddress(
1086 Hardware->os, Logical, &address
1090 /* Return hardware specific address. */
1091 *Address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
1095 return gcvSTATUS_OK;
1100 /* Return the status. */
1104 /*******************************************************************************
1106 ** gckVGHARDWARE_QuerySystemMemory
1108 ** Query the command buffer alignment and number of reserved bytes.
1112 ** gckVGHARDWARE Harwdare
1113 ** Pointer to an gckVGHARDWARE object.
1117 ** gctSIZE_T * SystemSize
1118 ** Pointer to a variable that receives the maximum size of the system
1121 ** gctUINT32 * SystemBaseAddress
1122 ** Poinetr to a variable that receives the base address for system
1125 gceSTATUS gckVGHARDWARE_QuerySystemMemory(
1126 IN gckVGHARDWARE Hardware,
1127 OUT gctSIZE_T * SystemSize,
1128 OUT gctUINT32 * SystemBaseAddress
1131 gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
1132 Hardware, SystemSize, SystemBaseAddress);
1134 /* Verify the arguments. */
1135 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1137 if (SystemSize != gcvNULL)
1139 /* Maximum system memory can be 2GB. */
1140 *SystemSize = (gctSIZE_T)(1 << 31);
1143 if (SystemBaseAddress != gcvNULL)
1145 /* Set system memory base address. */
1146 *SystemBaseAddress = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
1151 return gcvSTATUS_OK;
1154 /*******************************************************************************
1156 ** gckVGHARDWARE_SetMMU
1158 ** Set the page table base address.
1162 ** gckVGHARDWARE Harwdare
1163 ** Pointer to an gckVGHARDWARE object.
1165 ** gctPOINTER Logical
1166 ** Logical address of the page table.
1172 gceSTATUS gckVGHARDWARE_SetMMU(
1173 IN gckVGHARDWARE Hardware,
1174 IN gctPOINTER Logical
1178 gctUINT32 address = 0;
1180 gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
1183 /* Verify the arguments. */
1184 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1185 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1189 /* Convert the logical address into an hardware address. */
1190 gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical,
1191 gcvFALSE, &address));
1193 /* Write the AQMemoryFePageTable register. */
1194 gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1196 gcmkFIXADDRESS(address)));
1198 /* Write the AQMemoryTxPageTable register. */
1199 gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1201 gcmkFIXADDRESS(address)));
1203 /* Write the AQMemoryPePageTable register. */
1204 gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1206 gcmkFIXADDRESS(address)));
1208 /* Write the AQMemoryPezPageTable register. */
1209 gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1211 gcmkFIXADDRESS(address)));
1213 /* Write the AQMemoryRaPageTable register. */
1214 gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1216 gcmkFIXADDRESS(address)));
1221 /* Return the status. */
1225 /*******************************************************************************
1227 ** gckVGHARDWARE_FlushMMU
1229 ** Flush the page table.
1233 ** gckVGHARDWARE Harwdare
1234 ** Pointer to an gckVGHARDWARE object.
1240 gceSTATUS gckVGHARDWARE_FlushMMU(
1241 IN gckVGHARDWARE Hardware
1245 gckVGCOMMAND command;
1247 gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
1248 /* Verify the arguments. */
1249 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1253 gcsCMDBUFFER_PTR commandBuffer;
1254 gctUINT32_PTR buffer;
1256 /* Create a shortcut to the command buffer object. */
1257 command = Hardware->kernel->command;
1259 /* Allocate command buffer space. */
1260 gcmkERR_BREAK(gckVGCOMMAND_Allocate(
1261 command, 8, &commandBuffer, (gctPOINTER *) &buffer
1265 = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
1266 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E04) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
1267 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
1270 = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
1271 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
1272 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
1273 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
1274 | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
1279 /* Return the status. */
1283 /*******************************************************************************
1285 ** gckVGHARDWARE_BuildVirtualAddress
1287 ** Build a virtual address.
1291 ** gckVGHARDWARE Harwdare
1292 ** Pointer to an gckVGHARDWARE object.
1295 ** Index into page table.
1298 ** Offset into page.
1302 ** gctUINT32 * Address
1303 ** Pointer to a variable receiving te hardware address.
1305 gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
1306 IN gckVGHARDWARE Hardware,
1308 IN gctUINT32 Offset,
1309 OUT gctUINT32 * Address
1314 gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
1315 Hardware, Index, Offset, Address);
1317 /* Verify the arguments. */
1318 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1319 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1321 /* Build virtual address. */
1322 address = (Index << 12) | Offset;
1324 /* Set virtual type. */
1325 address = ((((gctUINT32) (address)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0))) | (((gctUINT32) (0x2 & ((gctUINT32) ((((1 ? 1:0) - (0 ? 1:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:0) - (0 ? 1:0) + 1))))))) << (0 ? 1:0)));
1327 /* Set the result. */
1332 return gcvSTATUS_OK;
1336 gckVGHARDWARE_GetIdle(
1337 IN gckVGHARDWARE Hardware,
1338 OUT gctUINT32 * Data
1342 gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
1343 /* Verify the arguments. */
1344 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1345 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
1347 /* Read register and return. */
1348 status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
1354 gckVGHARDWARE_SetFastClear(
1355 IN gckVGHARDWARE Hardware,
1362 if (!(((((gctUINT32) (Hardware->chipFeatures)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ))
1364 return gcvSTATUS_OK;
1371 Enable = (Hardware->chipModel > gcv500) ||
1372 ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
1375 gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
1379 debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? 20:20) - (0 ? 20:20) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 20:20) - (0 ? 20:20) + 1))))))) << (0 ? 20:20)));
1381 #ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
1382 debug = ((((gctUINT32) (debug)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION))) | (((gctUINT32) ((gctUINT32) (Enable == 0) & ((gctUINT32) ((((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1) == 32) ? ~0 : (~(~0 << ((1 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) - (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION) + 1))))))) << (0 ? AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION)));
1385 gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1389 Hardware->allowFastClear = Enable;
1399 gckVGHARDWARE_ReadInterrupt(
1400 IN gckVGHARDWARE Hardware,
1401 OUT gctUINT32_PTR IDs
1405 gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
1407 /* Verify the arguments. */
1408 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1409 gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
1411 /* Read AQIntrAcknowledge register. */
1412 status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
1419 static gceSTATUS _CommandStall(
1420 gckVGHARDWARE Hardware)
1423 gckVGCOMMAND command;
1425 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1426 /* Verify the arguments. */
1427 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1431 gctUINT32_PTR buffer;
1432 command = Hardware->kernel->command;
1434 /* Allocate command buffer space. */
1435 gcmkERR_BREAK(gckVGCOMMAND_Allocate(
1436 command, 8, &command->powerStallBuffer,
1437 (gctPOINTER *) &buffer
1440 gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
1441 command, buffer, gcvBLOCK_PIXEL,
1442 command->powerStallInt, gcvNULL));
1444 gcmkERR_BREAK(gckVGCOMMAND_Execute(
1446 command->powerStallBuffer
1449 /* Wait the signal. */
1450 gcmkERR_BREAK(gckOS_WaitSignal(
1452 command->powerStallSignal,
1453 command->kernel->kernel->timeOut));
1460 /* Return the status. */
1464 /*******************************************************************************
1466 ** gckHARDWARE_SetPowerManagementState
1468 ** Set GPU to a specified power state.
1472 ** gckHARDWARE Harwdare
1473 ** Pointer to an gckHARDWARE object.
1475 ** gceCHIPPOWERSTATE State
1480 gckVGHARDWARE_SetPowerManagementState(
1481 IN gckVGHARDWARE Hardware,
1482 IN gceCHIPPOWERSTATE State
1486 gckVGCOMMAND command = gcvNULL;
1488 gctUINT flag/*, clock*/;
1490 gctBOOL acquired = gcvFALSE;
1491 gctBOOL stall = gcvTRUE;
1492 gctBOOL commitMutex = gcvFALSE;
1493 gctBOOL mutexAcquired = gcvFALSE;
1495 #if gcdPOWEROFF_TIMEOUT
1496 gctBOOL timeout = gcvFALSE;
1497 gctBOOL isAfter = gcvFALSE;
1498 gctUINT32 currentTime;
1501 gctBOOL broadcast = gcvFALSE;
1502 gctUINT32 process, thread;
1503 gctBOOL global = gcvFALSE;
1505 #if gcdENABLE_PROFILING
1506 gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
1507 initTime, offTime, startTime, totalTime;
1510 /* State transition flags. */
1511 static const gctUINT flags[4][4] =
1515 /* OFF */ gcvPOWER_FLAG_ACQUIRE |
1516 gcvPOWER_FLAG_STALL |
1517 gcvPOWER_FLAG_STOP |
1518 gcvPOWER_FLAG_POWER_OFF |
1519 gcvPOWER_FLAG_CLOCK_OFF,
1520 /* IDLE */ gcvPOWER_FLAG_NOP,
1521 /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
1522 gcvPOWER_FLAG_STALL |
1523 gcvPOWER_FLAG_STOP |
1524 gcvPOWER_FLAG_CLOCK_OFF,
1528 { /* ON */ gcvPOWER_FLAG_INITIALIZE |
1529 gcvPOWER_FLAG_START |
1530 gcvPOWER_FLAG_RELEASE |
1531 gcvPOWER_FLAG_DELAY,
1533 /* IDLE */ gcvPOWER_FLAG_INITIALIZE |
1534 gcvPOWER_FLAG_START |
1535 gcvPOWER_FLAG_RELEASE |
1536 gcvPOWER_FLAG_DELAY,
1537 /* SUSPEND */ gcvPOWER_FLAG_INITIALIZE |
1538 gcvPOWER_FLAG_CLOCK_OFF,
1542 { /* ON */ gcvPOWER_FLAG_NOP,
1543 /* OFF */ gcvPOWER_FLAG_ACQUIRE |
1544 gcvPOWER_FLAG_STOP |
1545 gcvPOWER_FLAG_POWER_OFF |
1546 gcvPOWER_FLAG_CLOCK_OFF,
1548 /* SUSPEND */ gcvPOWER_FLAG_ACQUIRE |
1549 gcvPOWER_FLAG_STOP |
1550 gcvPOWER_FLAG_CLOCK_OFF,
1553 /* gcvPOWER_SUSPEND */
1554 { /* ON */ gcvPOWER_FLAG_START |
1555 gcvPOWER_FLAG_RELEASE |
1556 gcvPOWER_FLAG_DELAY |
1557 gcvPOWER_FLAG_CLOCK_ON,
1558 /* OFF */ gcvPOWER_FLAG_SAVE |
1559 gcvPOWER_FLAG_POWER_OFF |
1560 gcvPOWER_FLAG_CLOCK_OFF,
1561 /* IDLE */ gcvPOWER_FLAG_START |
1562 gcvPOWER_FLAG_DELAY |
1563 gcvPOWER_FLAG_RELEASE |
1564 gcvPOWER_FLAG_CLOCK_ON,
1569 gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
1570 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
1571 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1572 "Switching to power state %d",
1576 /* Verify the arguments. */
1577 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1579 /* Get the gckOS object pointer. */
1581 gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
1583 /* Get the gckCOMMAND object pointer. */
1584 gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
1585 command = Hardware->kernel->command;
1586 gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
1588 if (Hardware->powerManagement == gcvFALSE)
1591 return gcvSTATUS_OK;
1594 /* Start profiler. */
1595 gcmkPROFILE_INIT(freq, time);
1597 /* Convert the broadcast power state. */
1600 case gcvPOWER_SUSPEND_ATPOWERON:
1601 /* Convert to SUSPEND and don't wait for STALL. */
1602 State = gcvPOWER_SUSPEND;
1606 case gcvPOWER_OFF_ATPOWERON:
1607 /* Convert to OFF and don't wait for STALL. */
1608 State = gcvPOWER_OFF;
1612 case gcvPOWER_IDLE_BROADCAST:
1613 /* Convert to IDLE and note we are inside broadcast. */
1614 State = gcvPOWER_IDLE;
1615 broadcast = gcvTRUE;
1618 case gcvPOWER_SUSPEND_BROADCAST:
1619 /* Convert to SUSPEND and note we are inside broadcast. */
1620 State = gcvPOWER_SUSPEND;
1621 broadcast = gcvTRUE;
1624 case gcvPOWER_OFF_BROADCAST:
1625 /* Convert to OFF and note we are inside broadcast. */
1626 State = gcvPOWER_OFF;
1627 broadcast = gcvTRUE;
1630 case gcvPOWER_OFF_RECOVERY:
1631 /* Convert to OFF and note we are inside recovery. */
1632 State = gcvPOWER_OFF;
1634 broadcast = gcvTRUE;
1637 case gcvPOWER_ON_AUTO:
1638 /* Convert to ON and note we are inside recovery. */
1639 State = gcvPOWER_ON;
1644 case gcvPOWER_SUSPEND:
1646 /* Mark as global power management. */
1650 #if gcdPOWEROFF_TIMEOUT
1651 case gcvPOWER_OFF_TIMEOUT:
1652 /* Convert to OFF and note we are inside broadcast. */
1653 State = gcvPOWER_OFF;
1654 broadcast = gcvTRUE;
1655 /* Check time out */
1664 /* Get current process and thread IDs. */
1665 gcmkONERROR(gckOS_GetProcessID(&process));
1666 gcmkONERROR(gckOS_GetThreadID(&thread));
1668 /* Acquire the power mutex. */
1671 /* Try to acquire the power mutex. */
1672 status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
1674 if (status == gcvSTATUS_TIMEOUT)
1676 /* Check if we already own this mutex. */
1677 if ((Hardware->powerProcess == process)
1678 && (Hardware->powerThread == thread)
1681 /* Bail out on recursive power management. */
1683 return gcvSTATUS_OK;
1685 else if (State == gcvPOWER_IDLE)
1687 /* gcvPOWER_IDLE_BROADCAST is from IST,
1688 ** so waiting here will cause deadlock,
1689 ** if lock holder call gckCOMMAND_Stall() */
1690 gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
1694 /* Acquire the power mutex. */
1695 gcmkONERROR(gckOS_AcquireMutex(os,
1696 Hardware->powerMutex,
1703 /* Acquire the power mutex. */
1704 gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
1707 /* Get time until mtuex acquired. */
1708 gcmkPROFILE_QUERY(time, mutexTime);
1710 Hardware->powerProcess = process;
1711 Hardware->powerThread = thread;
1712 mutexAcquired = gcvTRUE;
1714 /* Grab control flags and clock. */
1715 flag = flags[Hardware->chipPowerState][State];
1716 /*clock = clocks[State];*/
1718 #if gcdPOWEROFF_TIMEOUT
1721 gcmkONERROR(gckOS_GetTicks(¤tTime));
1724 gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
1726 /* powerOffTime is pushed forward, give up.*/
1728 /* Expect a transition start from IDLE. */
1729 || (Hardware->chipPowerState == gcvPOWER_ON)
1730 || (Hardware->chipPowerState == gcvPOWER_OFF)
1733 /* Release the power mutex. */
1734 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1736 /* No need to do anything. */
1738 return gcvSTATUS_OK;
1745 /* Release the power mutex. */
1746 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1748 /* No need to do anything. */
1750 return gcvSTATUS_OK;
1753 /* internal power control */
1756 if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
1758 /* Release the power mutex. */
1759 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1761 /* No need to do anything. */
1763 return gcvSTATUS_OK;
1768 if (flag & gcvPOWER_FLAG_ACQUIRE)
1770 /* Acquire the power management semaphore. */
1771 gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
1774 /* avoid acquiring again. */
1775 flag &= ~gcvPOWER_FLAG_ACQUIRE;
1779 if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
1781 /* Turn on the power. */
1782 gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
1784 /* Mark clock and power as enabled. */
1785 Hardware->clockState = gcvTRUE;
1786 Hardware->powerState = gcvTRUE;
1789 /* Get time until powered on. */
1790 gcmkPROFILE_QUERY(time, onTime);
1792 if ((flag & gcvPOWER_FLAG_STALL) && stall)
1794 /* Acquire the mutex. */
1795 gcmkONERROR(gckOS_AcquireMutex(
1797 command->commitMutex,
1801 commitMutex = gcvTRUE;
1803 gcmkONERROR(_CommandStall(Hardware));
1806 /* Get time until stalled. */
1807 gcmkPROFILE_QUERY(time, stallTime);
1809 if (flag & gcvPOWER_FLAG_ACQUIRE)
1811 /* Acquire the power management semaphore. */
1812 gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
1818 /* Get time until stopped. */
1819 gcmkPROFILE_QUERY(time, stopTime);
1822 if (flag & gcvPOWER_FLAG_DELAY)
1824 /* Wait for the specified amount of time to settle coming back from
1825 ** power-off or suspend state. */
1826 gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
1829 /* Get time until delayed. */
1830 gcmkPROFILE_QUERY(time, delayTime);
1832 if (flag & gcvPOWER_FLAG_INITIALIZE)
1835 /* Initialize GPU here, replaced by InitializeHardware later */
1836 gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
1837 gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(Hardware, -1));
1839 /* Force the command queue to reload the next context. */
1840 command->currentContext = 0;
1843 /* Get time until initialized. */
1844 gcmkPROFILE_QUERY(time, initTime);
1846 if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
1848 /* Turn off the GPU power. */
1850 gckOS_SetGPUPower(os,
1852 (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
1854 (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
1857 /* Save current hardware power and clock states. */
1858 Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
1860 Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
1864 /* Get time until off. */
1865 gcmkPROFILE_QUERY(time, offTime);
1868 /* Get time until started. */
1869 gcmkPROFILE_QUERY(time, startTime);
1871 if (flag & gcvPOWER_FLAG_RELEASE)
1873 /* Release the power management semaphore. */
1874 gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
1875 acquired = gcvFALSE;
1878 /* Save the new power state. */
1879 Hardware->chipPowerState = State;
1883 /* Save the new power state. */
1884 Hardware->chipPowerStateGlobal = State;
1889 /* Acquire the mutex. */
1890 gcmkVERIFY_OK(gckOS_ReleaseMutex(
1892 command->commitMutex
1896 #if gcdPOWEROFF_TIMEOUT
1897 /* Reset power off time */
1898 gcmkONERROR(gckOS_GetTicks(¤tTime));
1900 Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
1902 if (State == gcvPOWER_IDLE)
1904 /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
1905 gcmkVERIFY_OK(gckOS_StartTimer(os,
1906 Hardware->powerOffTimer,
1907 Hardware->powerOffTimeout));
1911 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
1913 /* Cancel running timer when GPU enters ON or OFF. */
1914 gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
1918 /* Release the power mutex. */
1919 gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1921 /* Get total time. */
1922 gcmkPROFILE_QUERY(time, totalTime);
1923 #if gcdENABLE_PROFILING
1924 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1925 "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
1926 freq, mutexTime, onTime, stallTime, stopTime);
1927 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1928 " delay:%llu init:%llu off:%llu start:%llu total:%llu",
1929 delayTime, initTime, offTime, startTime, totalTime);
1934 return gcvSTATUS_OK;
1940 /* Release semaphore. */
1941 gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
1942 command->powerSemaphore));
1947 gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
1952 /* Acquire the mutex. */
1953 gcmkVERIFY_OK(gckOS_ReleaseMutex(
1955 command->commitMutex
1959 /* Return the status. */
1964 /*******************************************************************************
1966 ** gckHARDWARE_QueryPowerManagementState
1968 ** Get GPU power state.
1972 ** gckHARDWARE Harwdare
1973 ** Pointer to an gckHARDWARE object.
1975 ** gceCHIPPOWERSTATE* State
1980 gckVGHARDWARE_QueryPowerManagementState(
1981 IN gckVGHARDWARE Hardware,
1982 OUT gceCHIPPOWERSTATE* State
1985 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1987 /* Verify the arguments. */
1988 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1989 gcmkVERIFY_ARGUMENT(State != gcvNULL);
1991 /* Return the statue. */
1992 *State = Hardware->chipPowerState;
1995 gcmkFOOTER_ARG("*State=%d", *State);
1996 return gcvSTATUS_OK;
1999 /*******************************************************************************
2001 ** gckVGHARDWARE_SetPowerManagement
2003 ** Configure GPU power management function.
2004 ** Only used in driver initialization stage.
2008 ** gckVGHARDWARE Harwdare
2009 ** Pointer to an gckHARDWARE object.
2011 ** gctBOOL PowerManagement
2012 ** Power Mangement State.
2016 gckVGHARDWARE_SetPowerManagement(
2017 IN gckVGHARDWARE Hardware,
2018 IN gctBOOL PowerManagement
2021 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2023 /* Verify the arguments. */
2024 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2026 Hardware->powerManagement = PowerManagement;
2030 return gcvSTATUS_OK;
2033 #if gcdPOWEROFF_TIMEOUT
2035 gckVGHARDWARE_SetPowerOffTimeout(
2036 IN gckVGHARDWARE Hardware,
2037 IN gctUINT32 Timeout
2040 gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
2042 Hardware->powerOffTimeout = Timeout;
2045 return gcvSTATUS_OK;
2050 gckVGHARDWARE_QueryPowerOffTimeout(
2051 IN gckVGHARDWARE Hardware,
2052 OUT gctUINT32* Timeout
2055 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2057 *Timeout = Hardware->powerOffTimeout;
2059 gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
2060 return gcvSTATUS_OK;
2065 gckVGHARDWARE_QueryIdle(
2066 IN gckVGHARDWARE Hardware,
2067 OUT gctBOOL_PTR IsIdle
2073 gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2075 /* Verify the arguments. */
2076 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2077 gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
2079 /* We are idle when the power is not ON. */
2080 if (Hardware->chipPowerState != gcvPOWER_ON)
2087 /* Read idle register. */
2089 gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
2091 /* Pipe must be idle. */
2092 if (((((((gctUINT32) (idle)) >> (0 ? 0:0)) & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1)))))) ) != 1)
2093 || ((((((gctUINT32) (idle)) >> (0 ? 8:8)) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) ) != 1)
2094 || ((((((gctUINT32) (idle)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ) != 1)
2095 || ((((((gctUINT32) (idle)) >> (0 ? 10:10)) & ((gctUINT32) ((((1 ? 10:10) - (0 ? 10:10) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 10:10) - (0 ? 10:10) + 1)))))) ) != 1)
2096 || ((((((gctUINT32) (idle)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ) != 1)
2099 /* Something is busy. */
2111 return gcvSTATUS_OK;
2114 /* Return the status. */
2118 #endif /* gcdENABLE_VG */