]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/mxc/gpu-viv/hal/kernel/archvg/gc_hal_kernel_hardware_vg.c
gpu: vivante: Update driver from Freescale 3.10.53-1.1-ga BSP
[karo-tx-linux.git] / drivers / mxc / gpu-viv / hal / kernel / archvg / gc_hal_kernel_hardware_vg.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2014 by Vivante Corp.
4 *
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.
9 *
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.
14 *
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.
18 *
19 *****************************************************************************/
20
21
22 #include "gc_hal.h"
23 #include "gc_hal_kernel.h"
24 #include "gc_hal_kernel_hardware_command_vg.h"
25
26 #if gcdENABLE_VG
27
28 #define _GC_OBJ_ZONE    gcvZONE_HARDWARE
29
30 typedef enum
31 {
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,
44 }
45 gcePOWER_FLAGS;
46
47 /******************************************************************************\
48 ********************************* Support Code *********************************
49 \******************************************************************************/
50 static gceSTATUS
51 _ResetGPU(
52     IN gckOS Os
53     )
54 {
55     gctUINT32 control, idle;
56     gceSTATUS status;
57
58     /* Read register. */
59     gcmkONERROR(gckOS_ReadRegisterEx(Os,
60                                      gcvCORE_VG,
61                                      0x00000,
62                                      &control));
63
64     for (;;)
65     {
66         /* Disable clock gating. */
67         gcmkONERROR(gckOS_WriteRegisterEx(Os,
68                     gcvCORE_VG,
69                     0x00104,
70                     0x00000000));
71
72         /* Wait for clock being stable. */
73         gcmkONERROR(gckOS_Delay(Os, 1));
74
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)));
77
78         gcmkONERROR(gckOS_WriteRegisterEx(Os,
79                                           gcvCORE_VG,
80                                           0x00000,
81                                           control));
82
83         /* Set soft reset. */
84         gcmkONERROR(gckOS_WriteRegisterEx(Os,
85                                           gcvCORE_VG,
86                                           0x00000,
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)))));
88
89         /* Wait for reset. */
90         gcmkONERROR(gckOS_Delay(Os, 1));
91
92         /* Reset soft reset bit. */
93         gcmkONERROR(gckOS_WriteRegisterEx(Os,
94                                           gcvCORE_VG,
95                                           0x00000,
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)))));
97
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)));
100
101         gcmkONERROR(gckOS_WriteRegisterEx(Os,
102                                           gcvCORE_VG,
103                                           0x00000,
104                                           control));
105
106         /* Read idle register. */
107         gcmkONERROR(gckOS_ReadRegisterEx(Os,
108                                          gcvCORE_VG,
109                                          0x00004,
110                                          &idle));
111
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)
113         {
114             continue;
115         }
116
117         /* Read reset register. */
118         gcmkONERROR(gckOS_ReadRegisterEx(Os,
119                                          gcvCORE_VG,
120                                          0x00000,
121                                          &control));
122
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)
125         )
126         {
127             continue;
128         }
129
130         /* GPU is idle. */
131         break;
132     }
133
134     /* Success. */
135     return gcvSTATUS_OK;
136
137 OnError:
138
139     /* Return the error. */
140     return status;
141 }
142
143
144 static gceSTATUS
145 _IdentifyHardware(
146     IN gckOS Os,
147     OUT gceCHIPMODEL * ChipModel,
148     OUT gctUINT32 * ChipRevision,
149     OUT gctUINT32 * ChipFeatures,
150     OUT gctUINT32 * ChipMinorFeatures,
151     OUT gctUINT32 * ChipMinorFeatures2
152     )
153 {
154     gceSTATUS status;
155     gctUINT32 chipIdentity;
156
157     do
158     {
159         /* Read chip identity register. */
160         gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG, 0x00018, &chipIdentity));
161
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))))))))
164         {
165             *ChipModel    = gcv500;
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)))))) );
167         }
168
169         else
170         {
171             /* Read chip identity register. */
172             gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
173                                             0x00020,
174                                             (gctUINT32 *) ChipModel));
175
176             /* Read CHIP_REV register. */
177             gcmkERR_BREAK(gckOS_ReadRegisterEx(Os, gcvCORE_VG,
178                                             0x00024,
179                                             ChipRevision));
180         }
181
182         /* Read chip feature register. */
183         gcmkERR_BREAK(gckOS_ReadRegisterEx(
184             Os, gcvCORE_VG, 0x0001C, ChipFeatures
185             ));
186
187         /* Read chip minor feature register. */
188         gcmkERR_BREAK(gckOS_ReadRegisterEx(
189             Os, gcvCORE_VG, 0x00034, ChipMinorFeatures
190             ));
191
192         /* Read chip minor feature register #2. */
193         gcmkERR_BREAK(gckOS_ReadRegisterEx(
194             Os, gcvCORE_VG, 0x00074, ChipMinorFeatures2
195             ));
196
197         gcmkTRACE(
198             gcvLEVEL_VERBOSE,
199             "ChipModel=0x%08X\n"
200             "ChipRevision=0x%08X\n"
201             "ChipFeatures=0x%08X\n"
202             "ChipMinorFeatures=0x%08X\n"
203             "ChipMinorFeatures2=0x%08X\n",
204             *ChipModel,
205             *ChipRevision,
206             *ChipFeatures,
207             *ChipMinorFeatures,
208             *ChipMinorFeatures2
209             );
210
211         /* Success. */
212         return gcvSTATUS_OK;
213     }
214     while (gcvFALSE);
215
216     /* Return the status. */
217     return status;
218 }
219
220 #if gcdPOWEROFF_TIMEOUT
221 void
222 _VGPowerTimerFunction(
223     gctPOINTER Data
224     )
225 {
226     gckVGHARDWARE hardware = (gckVGHARDWARE)Data;
227     gcmkVERIFY_OK(
228         gckVGHARDWARE_SetPowerManagementState(hardware, gcvPOWER_OFF_TIMEOUT));
229 }
230 #endif
231
232 /******************************************************************************\
233 ****************************** gckVGHARDWARE API code *****************************
234 \******************************************************************************/
235
236 /*******************************************************************************
237 **
238 **  gckVGHARDWARE_Construct
239 **
240 **  Construct a new gckVGHARDWARE object.
241 **
242 **  INPUT:
243 **
244 **      gckOS Os
245 **          Pointer to an initialized gckOS object.
246 **
247 **  OUTPUT:
248 **
249 **      gckVGHARDWARE * Hardware
250 **          Pointer to a variable that will hold the pointer to the gckVGHARDWARE
251 **          object.
252 */
253 gceSTATUS
254 gckVGHARDWARE_Construct(
255     IN gckOS Os,
256     OUT gckVGHARDWARE * Hardware
257     )
258 {
259     gckVGHARDWARE hardware = gcvNULL;
260     gceSTATUS status;
261     gceCHIPMODEL chipModel;
262     gctUINT32 chipRevision;
263     gctUINT32 chipFeatures;
264     gctUINT32 chipMinorFeatures;
265     gctUINT32 chipMinorFeatures2;
266
267     gcmkHEADER_ARG("Os=0x%x Hardware=0x%x ", Os, Hardware);
268
269     /* Verify the arguments. */
270     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
271     gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
272
273     do
274     {
275         gcmkERR_BREAK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvTRUE, gcvTRUE));
276
277         status = _ResetGPU(Os);
278
279         if (status != gcvSTATUS_OK)
280         {
281             gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
282                 "_ResetGPU failed: status=%d\n", status);
283         }
284
285         /* Identify the hardware. */
286         gcmkERR_BREAK(_IdentifyHardware(Os,
287             &chipModel, &chipRevision,
288             &chipFeatures, &chipMinorFeatures, &chipMinorFeatures2
289             ));
290
291         /* Allocate the gckVGHARDWARE object. */
292         gcmkERR_BREAK(gckOS_Allocate(Os,
293             gcmSIZEOF(struct _gckVGHARDWARE), (gctPOINTER *) &hardware
294             ));
295
296         /* Initialize the gckVGHARDWARE object. */
297         hardware->object.type = gcvOBJ_HARDWARE;
298         hardware->os = Os;
299
300         /* Set chip identity. */
301         hardware->chipModel          = chipModel;
302         hardware->chipRevision       = chipRevision;
303         hardware->chipFeatures       = chipFeatures;
304         hardware->chipMinorFeatures  = chipMinorFeatures;
305         hardware->chipMinorFeatures2 = chipMinorFeatures2;
306
307         hardware->powerMutex            = gcvNULL;
308         hardware->chipPowerState        = gcvPOWER_ON;
309         hardware->chipPowerStateGlobal  = gcvPOWER_ON;
310         hardware->clockState            = gcvTRUE;
311         hardware->powerState            = gcvTRUE;
312
313 #if gcdPOWEROFF_TIMEOUT
314         hardware->powerOffTime          = 0;
315         hardware->powerOffTimeout       = gcdPOWEROFF_TIMEOUT;
316
317         gcmkVERIFY_OK(gckOS_CreateTimer(Os,
318                                         _VGPowerTimerFunction,
319                                         (gctPOINTER)hardware,
320                                         &hardware->powerOffTimer));
321 #endif
322
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)))))));
325
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)))))));
328
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)))))));
331
332         /* Set default event mask. */
333         hardware->eventMask = 0xFFFFFFFF;
334
335         gcmkERR_BREAK(gckOS_AtomConstruct(Os, &hardware->pageTableDirty));
336
337         /* Set fast clear to auto. */
338         gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(hardware, -1));
339
340         gcmkERR_BREAK(gckOS_CreateMutex(Os, &hardware->powerMutex));
341
342         /* Enable power management by default. */
343         hardware->powerManagement = gcvTRUE;
344
345         /* Return pointer to the gckVGHARDWARE object. */
346         *Hardware = hardware;
347
348         gcmkFOOTER_NO();
349         /* Success. */
350         return gcvSTATUS_OK;
351     }
352     while (gcvFALSE);
353
354 #if gcdPOWEROFF_TIMEOUT
355     if (hardware->powerOffTimer != gcvNULL)
356     {
357         gcmkVERIFY_OK(gckOS_StopTimer(Os, hardware->powerOffTimer));
358         gcmkVERIFY_OK(gckOS_DestroyTimer(Os, hardware->powerOffTimer));
359     }
360 #endif
361
362     gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
363
364     if (hardware != gcvNULL && hardware->pageTableDirty != gcvNULL)
365     {
366         gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
367     }
368
369     if (hardware != gcvNULL)
370     {
371         gcmkVERIFY_OK(gckOS_Free(Os, hardware));
372     }
373
374     gcmkFOOTER();
375     /* Return the status. */
376     return status;
377 }
378
379 /*******************************************************************************
380 **
381 **  gckVGHARDWARE_Destroy
382 **
383 **  Destroy an gckVGHARDWARE object.
384 **
385 **  INPUT:
386 **
387 **      gckVGHARDWARE Hardware
388 **          Pointer to the gckVGHARDWARE object that needs to be destroyed.
389 **
390 **  OUTPUT:
391 **
392 **      Nothing.
393 */
394 gceSTATUS
395 gckVGHARDWARE_Destroy(
396     IN gckVGHARDWARE Hardware
397     )
398 {
399     gceSTATUS status;
400     gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
401     /* Verify the arguments. */
402     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
403
404     /* Mark the object as unknown. */
405     Hardware->object.type = gcvOBJ_UNKNOWN;
406
407     if (Hardware->powerMutex != gcvNULL)
408     {
409         gcmkVERIFY_OK(gckOS_DeleteMutex(
410             Hardware->os, Hardware->powerMutex));
411     }
412
413 #if gcdPOWEROFF_TIMEOUT
414     gcmkVERIFY_OK(gckOS_StopTimer(Hardware->os, Hardware->powerOffTimer));
415     gcmkVERIFY_OK(gckOS_DestroyTimer(Hardware->os, Hardware->powerOffTimer));
416 #endif
417
418     if (Hardware->pageTableDirty != gcvNULL)
419     {
420         gcmkVERIFY_OK(gckOS_AtomDestroy(Hardware->os, Hardware->pageTableDirty));
421     }
422
423     /* Free the object. */
424     status = gckOS_Free(Hardware->os, Hardware);
425     gcmkFOOTER();
426     return status;
427 }
428
429 /*******************************************************************************
430 **
431 **  gckVGHARDWARE_QueryMemory
432 **
433 **  Query the amount of memory available on the hardware.
434 **
435 **  INPUT:
436 **
437 **      gckVGHARDWARE Hardware
438 **          Pointer to the gckVGHARDWARE object.
439 **
440 **  OUTPUT:
441 **
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.
446 **
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.
451 **
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.
456 **
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.
461 **
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.
466 **
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.
471 **
472 **      gctUINT32 * HorizontalTileSize
473 **          Number of horizontal pixels per tile.  If 'HorizontalTileSize' is
474 **          gcvNULL, no horizontal pixel per tile will be returned.
475 **
476 **      gctUINT32 * VerticalTileSize
477 **          Number of vertical pixels per tile.  If 'VerticalTileSize' is
478 **          gcvNULL, no vertical pixel per tile will be returned.
479 */
480 gceSTATUS
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
491     )
492 {
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);
497
498     /* Verify the arguments. */
499     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
500
501     if (InternalSize != gcvNULL)
502     {
503         /* No internal memory. */
504         *InternalSize = 0;
505     }
506
507     if (ExternalSize != gcvNULL)
508     {
509         /* No external memory. */
510         *ExternalSize = 0;
511     }
512
513     if (HorizontalTileSize != gcvNULL)
514     {
515         /* 4x4 tiles. */
516         *HorizontalTileSize = 4;
517     }
518
519     if (VerticalTileSize != gcvNULL)
520     {
521         /* 4x4 tiles. */
522         *VerticalTileSize = 4;
523     }
524
525     gcmkFOOTER_NO();
526     /* Success. */
527     return gcvSTATUS_OK;
528 }
529
530 /*******************************************************************************
531 **
532 **  gckVGHARDWARE_QueryChipIdentity
533 **
534 **  Query the identity of the hardware.
535 **
536 **  INPUT:
537 **
538 **      gckVGHARDWARE Hardware
539 **          Pointer to the gckVGHARDWARE object.
540 **
541 **  OUTPUT:
542 **
543 **      gceCHIPMODEL * ChipModel
544 **          If 'ChipModel' is not gcvNULL, the variable it points to will
545 **          receive the model of the chip.
546 **
547 **      gctUINT32 * ChipRevision
548 **          If 'ChipRevision' is not gcvNULL, the variable it points to will
549 **          receive the revision of the chip.
550 **
551 **      gctUINT32 * ChipFeatures
552 **          If 'ChipFeatures' is not gcvNULL, the variable it points to will
553 **          receive the feature set of the chip.
554 **
555 **      gctUINT32 * ChipMinorFeatures
556 **          If 'ChipMinorFeatures' is not gcvNULL, the variable it points to
557 **          will receive the minor feature set of the chip.
558 **
559 **      gctUINT32 * ChipMinorFeatures2
560 **          If 'ChipMinorFeatures2' is not gcvNULL, the variable it points to
561 **          will receive the minor feature set of the chip.
562 **
563 */
564 gceSTATUS
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
572     )
573 {
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);
576
577     /* Verify the arguments. */
578     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
579
580     /* Return chip model. */
581     if (ChipModel != gcvNULL)
582     {
583         *ChipModel = Hardware->chipModel;
584     }
585
586     /* Return revision number. */
587     if (ChipRevision != gcvNULL)
588     {
589         *ChipRevision = Hardware->chipRevision;
590     }
591
592     /* Return feature set. */
593     if (ChipFeatures != gcvNULL)
594     {
595         gctUINT32 features = Hardware->chipFeatures;
596
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)))))) ))
598         {
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)));
600         }
601
602         /* Mark 2D pipe as available for GC500.0 since it did not have this *\
603         \* bit.                                                             */
604         if ((Hardware->chipModel == gcv500)
605         &&  (Hardware->chipRevision == 0)
606         )
607         {
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)));
609         }
610
611         /* Mark 2D pipe as available for GC300 since it did not have this   *\
612         \* bit.                                                             */
613         if (Hardware->chipModel == gcv300)
614         {
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)));
616         }
617
618         *ChipFeatures = features;
619     }
620
621     /* Return minor feature set. */
622     if (ChipMinorFeatures != gcvNULL)
623     {
624         *ChipMinorFeatures = Hardware->chipMinorFeatures;
625     }
626
627     /* Return minor feature set #2. */
628     if (ChipMinorFeatures2 != gcvNULL)
629     {
630         *ChipMinorFeatures2 = Hardware->chipMinorFeatures2;
631     }
632
633     gcmkFOOTER_NO();
634     /* Success. */
635     return gcvSTATUS_OK;
636 }
637
638 /*******************************************************************************
639 **
640 **  gckVGHARDWARE_ConvertFormat
641 **
642 **  Convert an API format to hardware parameters.
643 **
644 **  INPUT:
645 **
646 **      gckVGHARDWARE Hardware
647 **          Pointer to the gckVGHARDWARE object.
648 **
649 **      gceSURF_FORMAT Format
650 **          API format to convert.
651 **
652 **  OUTPUT:
653 **
654 **      gctUINT32 * BitsPerPixel
655 **          Pointer to a variable that will hold the number of bits per pixel.
656 **
657 **      gctUINT32 * BytesPerTile
658 **          Pointer to a variable that will hold the number of bytes per tile.
659 */
660 gceSTATUS
661 gckVGHARDWARE_ConvertFormat(
662     IN gckVGHARDWARE Hardware,
663     IN gceSURF_FORMAT Format,
664     OUT gctUINT32 * BitsPerPixel,
665     OUT gctUINT32 * BytesPerTile
666     )
667 {
668     gctUINT32 bitsPerPixel;
669     gctUINT32 bytesPerTile;
670
671     gcmkHEADER_ARG("Hardware=0x%x Format=0x%x BitsPerPixel=0x%x BytesPerTile = 0x%x",
672                    Hardware, Format, BitsPerPixel, BytesPerTile);
673
674     /* Verify the arguments. */
675     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
676
677     /* Dispatch on format. */
678     switch (Format)
679     {
680     case gcvSURF_A1:
681     case gcvSURF_L1:
682         /* 1-bpp format. */
683         bitsPerPixel  = 1;
684         bytesPerTile  = (1 * 4 * 4) / 8;
685         break;
686
687     case gcvSURF_A4:
688         /* 4-bpp format. */
689         bitsPerPixel  = 4;
690         bytesPerTile  = (4 * 4 * 4) / 8;
691         break;
692
693     case gcvSURF_INDEX8:
694     case gcvSURF_A8:
695     case gcvSURF_L8:
696         /* 8-bpp format. */
697         bitsPerPixel  = 8;
698         bytesPerTile  = (8 * 4 * 4) / 8;
699         break;
700
701     case gcvSURF_YV12:
702         /* 12-bpp planar YUV formats. */
703         bitsPerPixel  = 12;
704         bytesPerTile  = (12 * 4 * 4) / 8;
705         break;
706
707     case gcvSURF_NV12:
708         /* 12-bpp planar YUV formats. */
709         bitsPerPixel  = 12;
710         bytesPerTile  = (12 * 4 * 4) / 8;
711         break;
712
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:
722
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:
732
733     /* 565 variations. */
734     case gcvSURF_R5G6B5:
735     case gcvSURF_B5G6R5:
736
737     case gcvSURF_A8L8:
738     case gcvSURF_YUY2:
739     case gcvSURF_UYVY:
740     case gcvSURF_D16:
741         /* 16-bpp format. */
742         bitsPerPixel  = 16;
743         bytesPerTile  = (16 * 4 * 4) / 8;
744         break;
745
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:
754     case gcvSURF_D32:
755         /* 32-bpp format. */
756         bitsPerPixel  = 32;
757         bytesPerTile  = (32 * 4 * 4) / 8;
758         break;
759
760     case gcvSURF_D24S8:
761         /* 24-bpp format. */
762         bitsPerPixel  = 32;
763         bytesPerTile  = (32 * 4 * 4) / 8;
764         break;
765
766     case gcvSURF_DXT1:
767     case gcvSURF_ETC1:
768         bitsPerPixel  = 4;
769         bytesPerTile  = (4 * 4 * 4) / 8;
770         break;
771
772     case gcvSURF_DXT2:
773     case gcvSURF_DXT3:
774     case gcvSURF_DXT4:
775     case gcvSURF_DXT5:
776         bitsPerPixel  = 8;
777         bytesPerTile  = (8 * 4 * 4) / 8;
778         break;
779
780     default:
781         /* Invalid format. */
782         gcmkFOOTER_NO();
783         return gcvSTATUS_INVALID_ARGUMENT;
784     }
785
786     /* Set the result. */
787     if (BitsPerPixel != gcvNULL)
788     {
789         * BitsPerPixel = bitsPerPixel;
790     }
791
792     if (BytesPerTile != gcvNULL)
793     {
794         * BytesPerTile = bytesPerTile;
795     }
796
797     gcmkFOOTER_NO();
798     /* Success. */
799     return gcvSTATUS_OK;
800 }
801
802 /*******************************************************************************
803 **
804 **  gckVGHARDWARE_SplitMemory
805 **
806 **  Split a hardware specific memory address into a pool and offset.
807 **
808 **  INPUT:
809 **
810 **      gckVGHARDWARE Hardware
811 **          Pointer to the gckVGHARDWARE object.
812 **
813 **      gctUINT32 Address
814 **          Address in hardware specific format.
815 **
816 **  OUTPUT:
817 **
818 **      gcePOOL * Pool
819 **          Pointer to a variable that will hold the pool type for the address.
820 **
821 **      gctUINT32 * Offset
822 **          Pointer to a variable that will hold the offset for the address.
823 */
824 gceSTATUS
825 gckVGHARDWARE_SplitMemory(
826     IN gckVGHARDWARE Hardware,
827     IN gctUINT32 Address,
828     OUT gcePOOL * Pool,
829     OUT gctUINT32 * Offset
830     )
831 {
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);
838
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)))))) ))
841     {
842     case 0x0:
843         /* System memory. */
844         *Pool = gcvPOOL_SYSTEM;
845         break;
846
847     case 0x2:
848         /* Virtual memory. */
849         *Pool = gcvPOOL_VIRTUAL;
850         break;
851
852     default:
853         /* Invalid memory type. */
854         gcmkFOOTER_NO();
855         return gcvSTATUS_INVALID_ARGUMENT;
856     }
857
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)));
860
861     gcmkFOOTER_NO();
862     /* Success. */
863     return gcvSTATUS_OK;
864 }
865
866 /*******************************************************************************
867 **
868 **  gckVGHARDWARE_Execute
869 **
870 **  Kickstart the hardware's command processor with an initialized command
871 **  buffer.
872 **
873 **  INPUT:
874 **
875 **      gckVGHARDWARE Hardware
876 **          Pointer to the gckVGHARDWARE object.
877 **
878 **      gctUINT32 Address
879 **          Address of the command buffer.
880 **
881 **      gctSIZE_T Count
882 **          Number of command-sized data units to be executed.
883 **
884 **  OUTPUT:
885 **
886 **      Nothing.
887 */
888 gceSTATUS
889 gckVGHARDWARE_Execute(
890     IN gckVGHARDWARE Hardware,
891     IN gctUINT32 Address,
892     IN gctUINT32 Count
893     )
894 {
895     gceSTATUS status;
896
897     gcmkHEADER_ARG("Hardware=0x%x Address=0x%x Count=0x%x",
898                    Hardware, Address, Count);
899
900     /* Verify the arguments. */
901     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
902
903     do
904     {
905         /* Enable all events. */
906         gcmkERR_BREAK(gckOS_WriteRegisterEx(
907             Hardware->os,
908             gcvCORE_VG,
909             0x00014,
910             Hardware->eventMask
911             ));
912
913         if (Hardware->fe20)
914         {
915             /* Write address register. */
916             gcmkERR_BREAK(gckOS_WriteRegisterEx(
917                 Hardware->os,
918                 gcvCORE_VG,
919                 0x00500,
920                 gcmkFIXADDRESS(Address)
921                 ));
922
923             /* Write control register. */
924             gcmkERR_BREAK(gckOS_WriteRegisterEx(
925                 Hardware->os,
926                 gcvCORE_VG,
927                 0x00504,
928                 Count
929                 ));
930         }
931         else
932         {
933             /* Write address register. */
934             gcmkERR_BREAK(gckOS_WriteRegisterEx(
935                 Hardware->os,
936                 gcvCORE_VG,
937                 0x00654,
938                 gcmkFIXADDRESS(Address)
939                 ));
940
941             /* Write control register. */
942             gcmkERR_BREAK(gckOS_WriteRegisterEx(
943                 Hardware->os,
944                 gcvCORE_VG,
945                 0x00658,
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)))
948                 ));
949         }
950
951         /* Success. */
952         gcmkFOOTER();
953         return gcvSTATUS_OK;
954     }
955     while (gcvFALSE);
956
957
958     gcmkFOOTER();
959     /* Return the status. */
960     return status;
961 }
962
963 /*******************************************************************************
964 **
965 **  gckVGHARDWARE_AlignToTile
966 **
967 **  Align the specified width and height to tile boundaries.
968 **
969 **  INPUT:
970 **
971 **      gckVGHARDWARE Hardware
972 **          Pointer to an gckVGHARDWARE object.
973 **
974 **      gceSURF_TYPE Type
975 **          Type of alignment.
976 **
977 **      gctUINT32 * Width
978 **          Pointer to the width to be aligned.  If 'Width' is gcvNULL, no width
979 **          will be aligned.
980 **
981 **      gctUINT32 * Height
982 **          Pointer to the height to be aligned.  If 'Height' is gcvNULL, no height
983 **          will be aligned.
984 **
985 **  OUTPUT:
986 **
987 **      gctUINT32 * Width
988 **          Pointer to a variable that will receive the aligned width.
989 **
990 **      gctUINT32 * Height
991 **          Pointer to a variable that will receive the aligned height.
992 */
993 gceSTATUS
994 gckVGHARDWARE_AlignToTile(
995     IN gckVGHARDWARE Hardware,
996     IN gceSURF_TYPE Type,
997     IN OUT gctUINT32 * Width,
998     IN OUT gctUINT32 * Height
999     )
1000 {
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);
1005
1006     if (Width != gcvNULL)
1007     {
1008         /* Align the width. */
1009         *Width = gcmALIGN(*Width, (Type == gcvSURF_TEXTURE) ? 4 : 16);
1010     }
1011
1012     if (Height != gcvNULL)
1013     {
1014         /* Special case for VG images. */
1015         if ((*Height == 0) && (Type == gcvSURF_IMAGE))
1016         {
1017             *Height = 4;
1018         }
1019         else
1020         {
1021             /* Align the height. */
1022             *Height = gcmALIGN(*Height, 4);
1023         }
1024     }
1025
1026     gcmkFOOTER_NO();
1027     /* Success. */
1028     return gcvSTATUS_OK;
1029 }
1030
1031 /*******************************************************************************
1032 **
1033 **  gckVGHARDWARE_ConvertLogical
1034 **
1035 **  Convert a logical system address into a hardware specific address.
1036 **
1037 **  INPUT:
1038 **
1039 **      gckVGHARDWARE Hardware
1040 **          Pointer to an gckVGHARDWARE object.
1041 **
1042 **      gctPOINTER Logical
1043 **          Logical address to convert.
1044 **
1045 **      gctBOOL InUserSpace
1046 **          gcvTRUE if the memory in user space.
1047 **
1048 **      gctUINT32* Address
1049 **          Return hardware specific address.
1050 **
1051 **  OUTPUT:
1052 **
1053 **      Nothing.
1054 */
1055 gceSTATUS
1056 gckVGHARDWARE_ConvertLogical(
1057     IN gckVGHARDWARE Hardware,
1058     IN gctPOINTER Logical,
1059     IN gctBOOL InUserSpace,
1060     OUT gctUINT32 * Address
1061     )
1062 {
1063     gctUINT32 address;
1064     gceSTATUS status;
1065
1066     gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x InUserSpace=%d Address=0x%x",
1067                    Hardware, Logical, InUserSpace, Address);
1068
1069     /* Verify the arguments. */
1070     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1071     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1072     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1073
1074     do
1075     {
1076         /* Convert logical address into a physical address. */
1077         if (InUserSpace)
1078         {
1079             gcmkERR_BREAK(gckOS_UserLogicalToPhysical(
1080                 Hardware->os, Logical, &address
1081                 ));
1082         }
1083         else
1084         {
1085             gcmkERR_BREAK(gckOS_GetPhysicalAddress(
1086                 Hardware->os, Logical, &address
1087                 ));
1088         }
1089
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)));
1092
1093         /* Success. */
1094         gcmkFOOTER();
1095         return gcvSTATUS_OK;
1096     }
1097     while (gcvFALSE);
1098
1099     gcmkFOOTER();
1100     /* Return the status. */
1101     return status;
1102 }
1103
1104 /*******************************************************************************
1105 **
1106 **  gckVGHARDWARE_QuerySystemMemory
1107 **
1108 **  Query the command buffer alignment and number of reserved bytes.
1109 **
1110 **  INPUT:
1111 **
1112 **      gckVGHARDWARE Harwdare
1113 **          Pointer to an gckVGHARDWARE object.
1114 **
1115 **  OUTPUT:
1116 **
1117 **      gctSIZE_T * SystemSize
1118 **          Pointer to a variable that receives the maximum size of the system
1119 **          memory.
1120 **
1121 **      gctUINT32 * SystemBaseAddress
1122 **          Poinetr to a variable that receives the base address for system
1123 **          memory.
1124 */
1125 gceSTATUS gckVGHARDWARE_QuerySystemMemory(
1126     IN gckVGHARDWARE Hardware,
1127     OUT gctSIZE_T * SystemSize,
1128     OUT gctUINT32 * SystemBaseAddress
1129     )
1130 {
1131     gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
1132                    Hardware, SystemSize, SystemBaseAddress);
1133
1134     /* Verify the arguments. */
1135     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1136
1137     if (SystemSize != gcvNULL)
1138     {
1139         /* Maximum system memory can be 2GB. */
1140         *SystemSize = (gctSIZE_T)(1 << 31);
1141     }
1142
1143     if (SystemBaseAddress != gcvNULL)
1144     {
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)));
1147     }
1148
1149     gcmkFOOTER_NO();
1150     /* Success. */
1151     return gcvSTATUS_OK;
1152 }
1153
1154 /*******************************************************************************
1155 **
1156 **  gckVGHARDWARE_SetMMU
1157 **
1158 **  Set the page table base address.
1159 **
1160 **  INPUT:
1161 **
1162 **      gckVGHARDWARE Harwdare
1163 **          Pointer to an gckVGHARDWARE object.
1164 **
1165 **      gctPOINTER Logical
1166 **          Logical address of the page table.
1167 **
1168 **  OUTPUT:
1169 **
1170 **      Nothing.
1171 */
1172 gceSTATUS gckVGHARDWARE_SetMMU(
1173     IN gckVGHARDWARE Hardware,
1174     IN gctPOINTER Logical
1175     )
1176 {
1177     gceSTATUS status;
1178     gctUINT32 address = 0;
1179
1180     gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
1181                    Hardware, Logical);
1182
1183     /* Verify the arguments. */
1184     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1185     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1186
1187     do
1188     {
1189         /* Convert the logical address into an hardware address. */
1190         gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical,
1191                                       gcvFALSE, &address));
1192
1193         /* Write the AQMemoryFePageTable register. */
1194         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1195                                       0x00400,
1196                                       gcmkFIXADDRESS(address)));
1197
1198         /* Write the AQMemoryTxPageTable register. */
1199         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1200                                       0x00404,
1201                                       gcmkFIXADDRESS(address)));
1202
1203         /* Write the AQMemoryPePageTable register. */
1204         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1205                                       0x00408,
1206                                       gcmkFIXADDRESS(address)));
1207
1208         /* Write the AQMemoryPezPageTable register. */
1209         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1210                                       0x0040C,
1211                                       gcmkFIXADDRESS(address)));
1212
1213         /* Write the AQMemoryRaPageTable register. */
1214         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1215                                       0x00410,
1216                                       gcmkFIXADDRESS(address)));
1217     }
1218     while (gcvFALSE);
1219
1220     gcmkFOOTER();
1221     /* Return the status. */
1222     return status;
1223 }
1224
1225 /*******************************************************************************
1226 **
1227 **  gckVGHARDWARE_FlushMMU
1228 **
1229 **  Flush the page table.
1230 **
1231 **  INPUT:
1232 **
1233 **      gckVGHARDWARE Harwdare
1234 **          Pointer to an gckVGHARDWARE object.
1235 **
1236 **  OUTPUT:
1237 **
1238 **      Nothing.
1239 */
1240 gceSTATUS gckVGHARDWARE_FlushMMU(
1241     IN gckVGHARDWARE Hardware
1242     )
1243 {
1244     gceSTATUS status;
1245     gckVGCOMMAND command;
1246
1247     gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
1248     /* Verify the arguments. */
1249     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1250
1251     do
1252     {
1253         gcsCMDBUFFER_PTR commandBuffer;
1254         gctUINT32_PTR buffer;
1255
1256         /* Create a shortcut to the command buffer object. */
1257         command = Hardware->kernel->command;
1258
1259         /* Allocate command buffer space. */
1260         gcmkERR_BREAK(gckVGCOMMAND_Allocate(
1261             command, 8, &commandBuffer, (gctPOINTER *) &buffer
1262             ));
1263
1264         buffer[0]
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)));
1268
1269         buffer[1]
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)));
1275     }
1276     while(gcvFALSE);
1277
1278     gcmkFOOTER();
1279     /* Return the status. */
1280     return status;
1281 }
1282
1283 /*******************************************************************************
1284 **
1285 **  gckVGHARDWARE_BuildVirtualAddress
1286 **
1287 **  Build a virtual address.
1288 **
1289 **  INPUT:
1290 **
1291 **      gckVGHARDWARE Harwdare
1292 **          Pointer to an gckVGHARDWARE object.
1293 **
1294 **      gctUINT32 Index
1295 **          Index into page table.
1296 **
1297 **      gctUINT32 Offset
1298 **          Offset into page.
1299 **
1300 **  OUTPUT:
1301 **
1302 **      gctUINT32 * Address
1303 **          Pointer to a variable receiving te hardware address.
1304 */
1305 gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
1306     IN gckVGHARDWARE Hardware,
1307     IN gctUINT32 Index,
1308     IN gctUINT32 Offset,
1309     OUT gctUINT32 * Address
1310     )
1311 {
1312     gctUINT32 address;
1313
1314     gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
1315                    Hardware, Index, Offset, Address);
1316
1317     /* Verify the arguments. */
1318     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1319     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1320
1321     /* Build virtual address. */
1322     address = (Index << 12) | Offset;
1323
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)));
1326
1327     /* Set the result. */
1328     *Address = address;
1329
1330     gcmkFOOTER_NO();
1331     /* Success. */
1332     return gcvSTATUS_OK;
1333 }
1334
1335 gceSTATUS
1336 gckVGHARDWARE_GetIdle(
1337     IN gckVGHARDWARE Hardware,
1338     OUT gctUINT32 * Data
1339     )
1340 {
1341     gceSTATUS status;
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);
1346
1347     /* Read register and return. */
1348     status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
1349     gcmkFOOTER();
1350     return status;
1351 }
1352
1353 gceSTATUS
1354 gckVGHARDWARE_SetFastClear(
1355     IN gckVGHARDWARE Hardware,
1356     IN gctINT Enable
1357     )
1358 {
1359     gctUINT32 debug;
1360     gceSTATUS status;
1361
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)))))) ))
1363     {
1364         return gcvSTATUS_OK;
1365     }
1366
1367     do
1368     {
1369         if (Enable == -1)
1370         {
1371             Enable = (Hardware->chipModel > gcv500) ||
1372                 ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
1373         }
1374
1375         gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
1376                                         0x00414,
1377                     &debug));
1378
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)));
1380
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)));
1383 #endif
1384
1385         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1386                                      0x00414,
1387                      debug));
1388
1389         Hardware->allowFastClear = Enable;
1390
1391         status = gcvFALSE;
1392     }
1393     while (gcvFALSE);
1394
1395     return status;
1396 }
1397
1398 gceSTATUS
1399 gckVGHARDWARE_ReadInterrupt(
1400     IN gckVGHARDWARE Hardware,
1401     OUT gctUINT32_PTR IDs
1402     )
1403 {
1404     gceSTATUS status;
1405     gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
1406
1407     /* Verify the arguments. */
1408     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1409     gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
1410
1411     /* Read AQIntrAcknowledge register. */
1412     status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
1413                               0x00010,
1414                               IDs);
1415     gcmkFOOTER();
1416     return status;
1417 }
1418
1419 static gceSTATUS _CommandStall(
1420     gckVGHARDWARE Hardware)
1421 {
1422     gceSTATUS status;
1423     gckVGCOMMAND command;
1424
1425     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1426     /* Verify the arguments. */
1427     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1428
1429     do
1430     {
1431         gctUINT32_PTR buffer;
1432         command = Hardware->kernel->command;
1433
1434         /* Allocate command buffer space. */
1435         gcmkERR_BREAK(gckVGCOMMAND_Allocate(
1436             command, 8, &command->powerStallBuffer,
1437             (gctPOINTER *) &buffer
1438             ));
1439
1440         gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
1441             command, buffer, gcvBLOCK_PIXEL,
1442             command->powerStallInt, gcvNULL));
1443
1444         gcmkERR_BREAK(gckVGCOMMAND_Execute(
1445             command,
1446             command->powerStallBuffer
1447             ));
1448
1449         /* Wait the signal. */
1450         gcmkERR_BREAK(gckOS_WaitSignal(
1451             command->os,
1452             command->powerStallSignal,
1453             command->kernel->kernel->timeOut));
1454
1455
1456     }
1457     while(gcvFALSE);
1458
1459     gcmkFOOTER();
1460     /* Return the status. */
1461     return status;
1462 }
1463
1464 /*******************************************************************************
1465 **
1466 **  gckHARDWARE_SetPowerManagementState
1467 **
1468 **  Set GPU to a specified power state.
1469 **
1470 **  INPUT:
1471 **
1472 **      gckHARDWARE Harwdare
1473 **          Pointer to an gckHARDWARE object.
1474 **
1475 **      gceCHIPPOWERSTATE State
1476 **          Power State.
1477 **
1478 */
1479 gceSTATUS
1480 gckVGHARDWARE_SetPowerManagementState(
1481     IN gckVGHARDWARE Hardware,
1482     IN gceCHIPPOWERSTATE State
1483     )
1484 {
1485     gceSTATUS status;
1486     gckVGCOMMAND command = gcvNULL;
1487     gckOS os;
1488     gctUINT flag/*, clock*/;
1489
1490     gctBOOL acquired        = gcvFALSE;
1491     gctBOOL stall           = gcvTRUE;
1492     gctBOOL commitMutex     = gcvFALSE;
1493     gctBOOL mutexAcquired   = gcvFALSE;
1494
1495 #if gcdPOWEROFF_TIMEOUT
1496     gctBOOL timeout = gcvFALSE;
1497     gctBOOL isAfter = gcvFALSE;
1498     gctUINT32 currentTime;
1499 #endif
1500
1501     gctBOOL broadcast = gcvFALSE;
1502     gctUINT32 process, thread;
1503     gctBOOL global = gcvFALSE;
1504
1505 #if gcdENABLE_PROFILING
1506     gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
1507               initTime, offTime, startTime, totalTime;
1508 #endif
1509
1510     /* State transition flags. */
1511     static const gctUINT flags[4][4] =
1512     {
1513         /* gcvPOWER_ON           */
1514         {   /* ON                */ 0,
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,
1525         },
1526
1527         /* gcvPOWER_OFF          */
1528         {   /* ON                */ gcvPOWER_FLAG_INITIALIZE |
1529                                     gcvPOWER_FLAG_START      |
1530                                     gcvPOWER_FLAG_RELEASE    |
1531                                     gcvPOWER_FLAG_DELAY,
1532             /* OFF               */ 0,
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,
1539         },
1540
1541         /* gcvPOWER_IDLE         */
1542         {   /* ON                */ gcvPOWER_FLAG_NOP,
1543             /* OFF               */ gcvPOWER_FLAG_ACQUIRE   |
1544                                     gcvPOWER_FLAG_STOP      |
1545                                     gcvPOWER_FLAG_POWER_OFF |
1546                                     gcvPOWER_FLAG_CLOCK_OFF,
1547             /* IDLE              */ 0,
1548             /* SUSPEND           */ gcvPOWER_FLAG_ACQUIRE   |
1549                                     gcvPOWER_FLAG_STOP      |
1550                                     gcvPOWER_FLAG_CLOCK_OFF,
1551         },
1552
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,
1565             /* SUSPEND           */ 0,
1566         },
1567     };
1568
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",
1573                    State);
1574 #endif
1575
1576     /* Verify the arguments. */
1577     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1578
1579     /* Get the gckOS object pointer. */
1580     os = Hardware->os;
1581     gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
1582
1583     /* Get the gckCOMMAND object pointer. */
1584     gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
1585     command = Hardware->kernel->command;
1586     gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
1587
1588     if (Hardware->powerManagement == gcvFALSE)
1589     {
1590         gcmkFOOTER_NO();
1591         return gcvSTATUS_OK;
1592     }
1593
1594     /* Start profiler. */
1595     gcmkPROFILE_INIT(freq, time);
1596
1597     /* Convert the broadcast power state. */
1598     switch (State)
1599     {
1600     case gcvPOWER_SUSPEND_ATPOWERON:
1601         /* Convert to SUSPEND and don't wait for STALL. */
1602         State = gcvPOWER_SUSPEND;
1603         stall = gcvFALSE;
1604         break;
1605
1606     case gcvPOWER_OFF_ATPOWERON:
1607         /* Convert to OFF and don't wait for STALL. */
1608         State = gcvPOWER_OFF;
1609         stall = gcvFALSE;
1610         break;
1611
1612     case gcvPOWER_IDLE_BROADCAST:
1613         /* Convert to IDLE and note we are inside broadcast. */
1614         State     = gcvPOWER_IDLE;
1615         broadcast = gcvTRUE;
1616         break;
1617
1618     case gcvPOWER_SUSPEND_BROADCAST:
1619         /* Convert to SUSPEND and note we are inside broadcast. */
1620         State     = gcvPOWER_SUSPEND;
1621         broadcast = gcvTRUE;
1622         break;
1623
1624     case gcvPOWER_OFF_BROADCAST:
1625         /* Convert to OFF and note we are inside broadcast. */
1626         State     = gcvPOWER_OFF;
1627         broadcast = gcvTRUE;
1628         break;
1629
1630     case gcvPOWER_OFF_RECOVERY:
1631         /* Convert to OFF and note we are inside recovery. */
1632         State     = gcvPOWER_OFF;
1633         stall     = gcvFALSE;
1634         broadcast = gcvTRUE;
1635         break;
1636
1637     case gcvPOWER_ON_AUTO:
1638         /* Convert to ON and note we are inside recovery. */
1639         State = gcvPOWER_ON;
1640         break;
1641
1642     case gcvPOWER_ON:
1643     case gcvPOWER_IDLE:
1644     case gcvPOWER_SUSPEND:
1645     case gcvPOWER_OFF:
1646         /* Mark as global power management. */
1647         global = gcvTRUE;
1648         break;
1649
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 */
1656         timeout = gcvTRUE;
1657         break;
1658 #endif
1659
1660     default:
1661         break;
1662     }
1663
1664     /* Get current process and thread IDs. */
1665     gcmkONERROR(gckOS_GetProcessID(&process));
1666     gcmkONERROR(gckOS_GetThreadID(&thread));
1667
1668     /* Acquire the power mutex. */
1669     if (broadcast)
1670     {
1671         /* Try to acquire the power mutex. */
1672         status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
1673
1674         if (status == gcvSTATUS_TIMEOUT)
1675         {
1676             /* Check if we already own this mutex. */
1677             if ((Hardware->powerProcess == process)
1678             &&  (Hardware->powerThread  == thread)
1679             )
1680             {
1681                 /* Bail out on recursive power management. */
1682                 gcmkFOOTER_NO();
1683                 return gcvSTATUS_OK;
1684             }
1685             else if (State == gcvPOWER_IDLE)
1686             {
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);
1691             }
1692             else
1693             {
1694                 /* Acquire the power mutex. */
1695                 gcmkONERROR(gckOS_AcquireMutex(os,
1696                                                Hardware->powerMutex,
1697                                                gcvINFINITE));
1698             }
1699         }
1700     }
1701     else
1702     {
1703         /* Acquire the power mutex. */
1704         gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
1705     }
1706
1707     /* Get time until mtuex acquired. */
1708     gcmkPROFILE_QUERY(time, mutexTime);
1709
1710     Hardware->powerProcess = process;
1711     Hardware->powerThread  = thread;
1712     mutexAcquired          = gcvTRUE;
1713
1714     /* Grab control flags and clock. */
1715     flag  = flags[Hardware->chipPowerState][State];
1716     /*clock = clocks[State];*/
1717
1718 #if gcdPOWEROFF_TIMEOUT
1719     if (timeout)
1720     {
1721         gcmkONERROR(gckOS_GetTicks(&currentTime));
1722
1723         gcmkONERROR(
1724             gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
1725
1726         /* powerOffTime is pushed forward, give up.*/
1727         if (isAfter
1728         /* Expect a transition start from IDLE. */
1729         ||  (Hardware->chipPowerState == gcvPOWER_ON)
1730         ||  (Hardware->chipPowerState == gcvPOWER_OFF)
1731         )
1732         {
1733             /* Release the power mutex. */
1734             gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1735
1736             /* No need to do anything. */
1737             gcmkFOOTER_NO();
1738             return gcvSTATUS_OK;
1739         }
1740     }
1741 #endif
1742
1743     if (flag == 0)
1744     {
1745         /* Release the power mutex. */
1746         gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1747
1748         /* No need to do anything. */
1749         gcmkFOOTER_NO();
1750         return gcvSTATUS_OK;
1751     }
1752
1753     /* internal power control */
1754     if (!global)
1755     {
1756         if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
1757         {
1758             /* Release the power mutex. */
1759             gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1760
1761             /* No need to do anything. */
1762             gcmkFOOTER_NO();
1763             return gcvSTATUS_OK;
1764         }
1765     }
1766     else
1767     {
1768         if (flag & gcvPOWER_FLAG_ACQUIRE)
1769         {
1770             /* Acquire the power management semaphore. */
1771             gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
1772             acquired = gcvTRUE;
1773
1774             /* avoid acquiring again. */
1775             flag &= ~gcvPOWER_FLAG_ACQUIRE;
1776         }
1777     }
1778
1779     if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
1780     {
1781         /* Turn on the power. */
1782         gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
1783
1784         /* Mark clock and power as enabled. */
1785         Hardware->clockState = gcvTRUE;
1786         Hardware->powerState = gcvTRUE;
1787     }
1788
1789     /* Get time until powered on. */
1790     gcmkPROFILE_QUERY(time, onTime);
1791
1792     if ((flag & gcvPOWER_FLAG_STALL) && stall)
1793     {
1794         /* Acquire the mutex. */
1795         gcmkONERROR(gckOS_AcquireMutex(
1796             command->os,
1797             command->commitMutex,
1798             gcvINFINITE
1799             ));
1800
1801         commitMutex = gcvTRUE;
1802
1803         gcmkONERROR(_CommandStall(Hardware));
1804     }
1805
1806     /* Get time until stalled. */
1807     gcmkPROFILE_QUERY(time, stallTime);
1808
1809     if (flag & gcvPOWER_FLAG_ACQUIRE)
1810     {
1811         /* Acquire the power management semaphore. */
1812         gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
1813
1814         acquired = gcvTRUE;
1815     }
1816
1817
1818     /* Get time until stopped. */
1819     gcmkPROFILE_QUERY(time, stopTime);
1820
1821
1822     if (flag & gcvPOWER_FLAG_DELAY)
1823     {
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));
1827     }
1828
1829     /* Get time until delayed. */
1830     gcmkPROFILE_QUERY(time, delayTime);
1831
1832     if (flag & gcvPOWER_FLAG_INITIALIZE)
1833     {
1834
1835         /* Initialize GPU here, replaced by InitializeHardware later */
1836         gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
1837         gcmkVERIFY_OK(gckVGHARDWARE_SetFastClear(Hardware, -1));
1838
1839         /* Force the command queue to reload the next context. */
1840         command->currentContext = 0;
1841     }
1842
1843     /* Get time until initialized. */
1844     gcmkPROFILE_QUERY(time, initTime);
1845
1846     if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
1847     {
1848         /* Turn off the GPU power. */
1849         gcmkONERROR(
1850             gckOS_SetGPUPower(os,
1851                               gcvCORE_VG,
1852                               (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
1853                                                                : gcvTRUE,
1854                               (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
1855                                                                : gcvTRUE));
1856
1857         /* Save current hardware power and clock states. */
1858         Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
1859                                                                 : gcvTRUE;
1860         Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
1861                                                                 : gcvTRUE;
1862     }
1863
1864     /* Get time until off. */
1865     gcmkPROFILE_QUERY(time, offTime);
1866
1867
1868     /* Get time until started. */
1869     gcmkPROFILE_QUERY(time, startTime);
1870
1871     if (flag & gcvPOWER_FLAG_RELEASE)
1872     {
1873         /* Release the power management semaphore. */
1874         gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
1875         acquired = gcvFALSE;
1876     }
1877
1878     /* Save the new power state. */
1879     Hardware->chipPowerState = State;
1880
1881     if (global)
1882     {
1883         /* Save the new power state. */
1884         Hardware->chipPowerStateGlobal = State;
1885     }
1886
1887     if (commitMutex)
1888     {
1889         /* Acquire the mutex. */
1890         gcmkVERIFY_OK(gckOS_ReleaseMutex(
1891             command->os,
1892             command->commitMutex
1893             ));
1894     }
1895
1896 #if gcdPOWEROFF_TIMEOUT
1897     /* Reset power off time */
1898     gcmkONERROR(gckOS_GetTicks(&currentTime));
1899
1900     Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
1901
1902     if (State == gcvPOWER_IDLE)
1903     {
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));
1908     }
1909     else
1910     {
1911         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
1912
1913         /* Cancel running timer when GPU enters ON or OFF. */
1914         gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
1915     }
1916 #endif
1917
1918     /* Release the power mutex. */
1919     gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1920
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);
1930 #endif
1931
1932     /* Success. */
1933     gcmkFOOTER_NO();
1934     return gcvSTATUS_OK;
1935
1936 OnError:
1937
1938     if (acquired)
1939     {
1940         /* Release semaphore. */
1941         gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
1942                                              command->powerSemaphore));
1943     }
1944
1945     if (mutexAcquired)
1946     {
1947         gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
1948     }
1949
1950     if (commitMutex)
1951     {
1952         /* Acquire the mutex. */
1953         gcmkVERIFY_OK(gckOS_ReleaseMutex(
1954             command->os,
1955             command->commitMutex
1956             ));
1957     }
1958
1959     /* Return the status. */
1960     gcmkFOOTER();
1961     return status;
1962 }
1963
1964 /*******************************************************************************
1965 **
1966 **  gckHARDWARE_QueryPowerManagementState
1967 **
1968 **  Get GPU power state.
1969 **
1970 **  INPUT:
1971 **
1972 **      gckHARDWARE Harwdare
1973 **          Pointer to an gckHARDWARE object.
1974 **
1975 **      gceCHIPPOWERSTATE* State
1976 **          Power State.
1977 **
1978 */
1979 gceSTATUS
1980 gckVGHARDWARE_QueryPowerManagementState(
1981     IN gckVGHARDWARE Hardware,
1982     OUT gceCHIPPOWERSTATE* State
1983     )
1984 {
1985     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1986
1987     /* Verify the arguments. */
1988     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1989     gcmkVERIFY_ARGUMENT(State != gcvNULL);
1990
1991     /* Return the statue. */
1992     *State = Hardware->chipPowerState;
1993
1994     /* Success. */
1995     gcmkFOOTER_ARG("*State=%d", *State);
1996     return gcvSTATUS_OK;
1997 }
1998
1999 /*******************************************************************************
2000 **
2001 **  gckVGHARDWARE_SetPowerManagement
2002 **
2003 **  Configure GPU power management function.
2004 **  Only used in driver initialization stage.
2005 **
2006 **  INPUT:
2007 **
2008 **      gckVGHARDWARE Harwdare
2009 **          Pointer to an gckHARDWARE object.
2010 **
2011 **      gctBOOL PowerManagement
2012 **          Power Mangement State.
2013 **
2014 */
2015 gceSTATUS
2016 gckVGHARDWARE_SetPowerManagement(
2017     IN gckVGHARDWARE Hardware,
2018     IN gctBOOL PowerManagement
2019     )
2020 {
2021     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2022
2023     /* Verify the arguments. */
2024     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2025
2026     Hardware->powerManagement = PowerManagement;
2027
2028     /* Success. */
2029     gcmkFOOTER_NO();
2030     return gcvSTATUS_OK;
2031 }
2032
2033 #if gcdPOWEROFF_TIMEOUT
2034 gceSTATUS
2035 gckVGHARDWARE_SetPowerOffTimeout(
2036     IN gckVGHARDWARE  Hardware,
2037     IN gctUINT32    Timeout
2038     )
2039 {
2040     gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
2041
2042     Hardware->powerOffTimeout = Timeout;
2043
2044     gcmkFOOTER_NO();
2045     return gcvSTATUS_OK;
2046 }
2047
2048
2049 gceSTATUS
2050 gckVGHARDWARE_QueryPowerOffTimeout(
2051     IN gckVGHARDWARE  Hardware,
2052     OUT gctUINT32*  Timeout
2053     )
2054 {
2055     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2056
2057     *Timeout = Hardware->powerOffTimeout;
2058
2059     gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
2060     return gcvSTATUS_OK;
2061 }
2062 #endif
2063
2064 gceSTATUS
2065 gckVGHARDWARE_QueryIdle(
2066     IN gckVGHARDWARE Hardware,
2067     OUT gctBOOL_PTR IsIdle
2068     )
2069 {
2070     gceSTATUS status;
2071     gctUINT32 idle;
2072
2073     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2074
2075     /* Verify the arguments. */
2076     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2077     gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
2078
2079     /* We are idle when the power is not ON. */
2080     if (Hardware->chipPowerState != gcvPOWER_ON)
2081     {
2082         *IsIdle = gcvTRUE;
2083     }
2084
2085     else
2086     {
2087         /* Read idle register. */
2088         gcmkONERROR(
2089             gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
2090
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)
2097         )
2098         {
2099             /* Something is busy. */
2100             *IsIdle = gcvFALSE;
2101         }
2102
2103         else
2104         {
2105             *IsIdle = gcvTRUE;
2106         }
2107     }
2108
2109     /* Success. */
2110     gcmkFOOTER_NO();
2111     return gcvSTATUS_OK;
2112
2113 OnError:
2114     /* Return the status. */
2115     gcmkFOOTER();
2116     return status;
2117 }
2118 #endif /* gcdENABLE_VG */
2119