]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/mxc/gpu-viv/arch/GC350/hal/kernel/gc_hal_kernel_hardware_vg.c
a17d2fdb7747ac14ca3860ebb4e330217e3853ab
[karo-tx-linux.git] / drivers / mxc / gpu-viv / arch / GC350 / hal / kernel / gc_hal_kernel_hardware_vg.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2013 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         hardware->powerOffTime          = 0;
314 #if gcdPOWEROFF_TIMEOUT
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     if (hardware->pageTableDirty != gcvNULL)
363     {
364         gcmkVERIFY_OK(gckOS_AtomDestroy(Os, hardware->pageTableDirty));
365     }
366
367     if (hardware != gcvNULL)
368     {
369         gcmkVERIFY_OK(gckOS_Free(Os, hardware));
370     }
371
372     gcmkVERIFY_OK(gckOS_SetGPUPower(Os, gcvCORE_VG, gcvFALSE, gcvFALSE));
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 gctSIZE_T 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 **      gctUINT32* Address
1046 **          Return hardware specific address.
1047 **
1048 **  OUTPUT:
1049 **
1050 **      Nothing.
1051 */
1052 gceSTATUS
1053 gckVGHARDWARE_ConvertLogical(
1054     IN gckVGHARDWARE Hardware,
1055     IN gctPOINTER Logical,
1056     OUT gctUINT32 * Address
1057     )
1058 {
1059     gctUINT32 address;
1060     gceSTATUS status;
1061
1062     gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x Address=0x%x",
1063                    Hardware, Logical, Address);
1064
1065     /* Verify the arguments. */
1066     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1067     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1068     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1069
1070     do
1071     {
1072         /* Convert logical address into a physical address. */
1073         gcmkERR_BREAK(gckOS_GetPhysicalAddress(
1074             Hardware->os, Logical, &address
1075             ));
1076
1077         /* Return hardware specific address. */
1078         *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)));
1079
1080         /* Success. */
1081         gcmkFOOTER();
1082         return gcvSTATUS_OK;
1083     }
1084     while (gcvFALSE);
1085
1086     gcmkFOOTER();
1087     /* Return the status. */
1088     return status;
1089 }
1090
1091 /*******************************************************************************
1092 **
1093 **  gckVGHARDWARE_QuerySystemMemory
1094 **
1095 **  Query the command buffer alignment and number of reserved bytes.
1096 **
1097 **  INPUT:
1098 **
1099 **      gckVGHARDWARE Harwdare
1100 **          Pointer to an gckVGHARDWARE object.
1101 **
1102 **  OUTPUT:
1103 **
1104 **      gctSIZE_T * SystemSize
1105 **          Pointer to a variable that receives the maximum size of the system
1106 **          memory.
1107 **
1108 **      gctUINT32 * SystemBaseAddress
1109 **          Poinetr to a variable that receives the base address for system
1110 **          memory.
1111 */
1112 gceSTATUS gckVGHARDWARE_QuerySystemMemory(
1113     IN gckVGHARDWARE Hardware,
1114     OUT gctSIZE_T * SystemSize,
1115     OUT gctUINT32 * SystemBaseAddress
1116     )
1117 {
1118     gcmkHEADER_ARG("Hardware=0x%x SystemSize=0x%x SystemBaseAddress=0x%x",
1119                    Hardware, SystemSize, SystemBaseAddress);
1120
1121     /* Verify the arguments. */
1122     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1123
1124     if (SystemSize != gcvNULL)
1125     {
1126         /* Maximum system memory can be 2GB. */
1127         *SystemSize = (gctSIZE_T)(1 << 31);
1128     }
1129
1130     if (SystemBaseAddress != gcvNULL)
1131     {
1132         /* Set system memory base address. */
1133         *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)));
1134     }
1135
1136     gcmkFOOTER_NO();
1137     /* Success. */
1138     return gcvSTATUS_OK;
1139 }
1140
1141 /*******************************************************************************
1142 **
1143 **  gckVGHARDWARE_SetMMU
1144 **
1145 **  Set the page table base address.
1146 **
1147 **  INPUT:
1148 **
1149 **      gckVGHARDWARE Harwdare
1150 **          Pointer to an gckVGHARDWARE object.
1151 **
1152 **      gctPOINTER Logical
1153 **          Logical address of the page table.
1154 **
1155 **  OUTPUT:
1156 **
1157 **      Nothing.
1158 */
1159 gceSTATUS gckVGHARDWARE_SetMMU(
1160     IN gckVGHARDWARE Hardware,
1161     IN gctPOINTER Logical
1162     )
1163 {
1164     gceSTATUS status;
1165     gctUINT32 address = 0;
1166
1167     gcmkHEADER_ARG("Hardware=0x%x Logical=0x%x",
1168                    Hardware, Logical);
1169
1170     /* Verify the arguments. */
1171     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1172     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1173
1174     do
1175     {
1176         /* Convert the logical address into an hardware address. */
1177         gcmkERR_BREAK(gckVGHARDWARE_ConvertLogical(Hardware, Logical, &address) );
1178
1179         /* Write the AQMemoryFePageTable register. */
1180         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1181                                       0x00400,
1182                                       gcmkFIXADDRESS(address)) );
1183
1184         /* Write the AQMemoryTxPageTable register. */
1185         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1186                                       0x00404,
1187                                       gcmkFIXADDRESS(address)) );
1188
1189         /* Write the AQMemoryPePageTable register. */
1190         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1191                                       0x00408,
1192                                       gcmkFIXADDRESS(address)) );
1193
1194         /* Write the AQMemoryPezPageTable register. */
1195         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1196                                       0x0040C,
1197                                       gcmkFIXADDRESS(address)) );
1198
1199         /* Write the AQMemoryRaPageTable register. */
1200         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1201                                       0x00410,
1202                                       gcmkFIXADDRESS(address)) );
1203     }
1204     while (gcvFALSE);
1205
1206     gcmkFOOTER();
1207     /* Return the status. */
1208     return status;
1209 }
1210
1211 /*******************************************************************************
1212 **
1213 **  gckVGHARDWARE_FlushMMU
1214 **
1215 **  Flush the page table.
1216 **
1217 **  INPUT:
1218 **
1219 **      gckVGHARDWARE Harwdare
1220 **          Pointer to an gckVGHARDWARE object.
1221 **
1222 **  OUTPUT:
1223 **
1224 **      Nothing.
1225 */
1226 gceSTATUS gckVGHARDWARE_FlushMMU(
1227     IN gckVGHARDWARE Hardware
1228     )
1229 {
1230     gceSTATUS status;
1231     gckVGCOMMAND command;
1232
1233     gcmkHEADER_ARG("Hardware=0x%x ", Hardware);
1234     /* Verify the arguments. */
1235     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1236
1237     do
1238     {
1239         gcsCMDBUFFER_PTR commandBuffer;
1240         gctUINT32_PTR buffer;
1241
1242         /* Create a shortcut to the command buffer object. */
1243         command = Hardware->kernel->command;
1244
1245         /* Allocate command buffer space. */
1246         gcmkERR_BREAK(gckVGCOMMAND_Allocate(
1247             command, 8, &commandBuffer, (gctPOINTER *) &buffer
1248             ));
1249
1250         buffer[0]
1251             = ((((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)))
1252             | ((((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)))
1253             | ((((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)));
1254
1255         buffer[1]
1256             = ((((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)))
1257             | ((((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)))
1258             | ((((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)))
1259             | ((((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)))
1260             | ((((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)));
1261     }
1262     while(gcvFALSE);
1263
1264     gcmkFOOTER();
1265     /* Return the status. */
1266     return status;
1267 }
1268
1269 /*******************************************************************************
1270 **
1271 **  gckVGHARDWARE_BuildVirtualAddress
1272 **
1273 **  Build a virtual address.
1274 **
1275 **  INPUT:
1276 **
1277 **      gckVGHARDWARE Harwdare
1278 **          Pointer to an gckVGHARDWARE object.
1279 **
1280 **      gctUINT32 Index
1281 **          Index into page table.
1282 **
1283 **      gctUINT32 Offset
1284 **          Offset into page.
1285 **
1286 **  OUTPUT:
1287 **
1288 **      gctUINT32 * Address
1289 **          Pointer to a variable receiving te hardware address.
1290 */
1291 gceSTATUS gckVGHARDWARE_BuildVirtualAddress(
1292     IN gckVGHARDWARE Hardware,
1293     IN gctUINT32 Index,
1294     IN gctUINT32 Offset,
1295     OUT gctUINT32 * Address
1296     )
1297 {
1298     gctUINT32 address;
1299
1300     gcmkHEADER_ARG("Hardware=0x%x Index=0x%x Offset=0x%x Address=0x%x",
1301                    Hardware, Index, Offset, Address);
1302
1303     /* Verify the arguments. */
1304     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1305     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1306
1307     /* Build virtual address. */
1308     address = (Index << 12) | Offset;
1309
1310     /* Set virtual type. */
1311     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)));
1312
1313     /* Set the result. */
1314     *Address = address;
1315
1316     gcmkFOOTER_NO();
1317     /* Success. */
1318     return gcvSTATUS_OK;
1319 }
1320
1321 gceSTATUS
1322 gckVGHARDWARE_GetIdle(
1323     IN gckVGHARDWARE Hardware,
1324     OUT gctUINT32 * Data
1325     )
1326 {
1327     gceSTATUS status;
1328     gcmkHEADER_ARG("Hardware=0x%x Data=0x%x", Hardware, Data);
1329     /* Verify the arguments. */
1330     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1331     gcmkVERIFY_ARGUMENT(Data != gcvNULL);
1332
1333     /* Read register and return. */
1334     status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, Data);
1335     gcmkFOOTER();
1336     return status;
1337 }
1338
1339 gceSTATUS
1340 gckVGHARDWARE_SetFastClear(
1341     IN gckVGHARDWARE Hardware,
1342     IN gctINT Enable
1343     )
1344 {
1345     gctUINT32 debug;
1346     gceSTATUS status;
1347
1348     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)))))) ))
1349     {
1350         return gcvSTATUS_OK;
1351     }
1352
1353     do
1354     {
1355         if (Enable == -1)
1356         {
1357             Enable = (Hardware->chipModel > gcv500) ||
1358                 ((Hardware->chipModel == gcv500) && (Hardware->chipRevision >= 3));
1359         }
1360
1361         gcmkERR_BREAK(gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
1362                                         0x00414,
1363                     &debug));
1364
1365         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)));
1366
1367 #ifdef AQ_MEMORY_DEBUG_DISABLE_Z_COMPRESSION
1368         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)));
1369 #endif
1370
1371         gcmkERR_BREAK(gckOS_WriteRegisterEx(Hardware->os, gcvCORE_VG,
1372                                      0x00414,
1373                      debug));
1374
1375         Hardware->allowFastClear = Enable;
1376
1377         status = gcvFALSE;
1378     }
1379     while (gcvFALSE);
1380
1381     return status;
1382 }
1383
1384 gceSTATUS
1385 gckVGHARDWARE_ReadInterrupt(
1386     IN gckVGHARDWARE Hardware,
1387     OUT gctUINT32_PTR IDs
1388     )
1389 {
1390     gceSTATUS status;
1391     gcmkHEADER_ARG("Hardware=0x%x IDs=0x%x", Hardware, IDs);
1392
1393     /* Verify the arguments. */
1394     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1395     gcmkVERIFY_ARGUMENT(IDs != gcvNULL);
1396
1397     /* Read AQIntrAcknowledge register. */
1398     status = gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG,
1399                               0x00010,
1400                               IDs);
1401     gcmkFOOTER();
1402     return status;
1403 }
1404
1405 static gceSTATUS _CommandStall(
1406     gckVGHARDWARE Hardware)
1407 {
1408     gceSTATUS status;
1409     gckVGCOMMAND command;
1410
1411     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1412     /* Verify the arguments. */
1413     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1414
1415     do
1416     {
1417         gctUINT32_PTR buffer;
1418         command = Hardware->kernel->command;
1419
1420         /* Allocate command buffer space. */
1421         gcmkERR_BREAK(gckVGCOMMAND_Allocate(
1422             command, 8, &command->powerStallBuffer,
1423             (gctPOINTER *) &buffer
1424             ));
1425
1426         gcmkERR_BREAK(gckVGCOMMAND_EventCommand(
1427             command, buffer, gcvBLOCK_PIXEL,
1428             command->powerStallInt, gcvNULL));
1429
1430         gcmkERR_BREAK(gckVGCOMMAND_Execute(
1431             command,
1432             command->powerStallBuffer
1433             ));
1434
1435         /* Wait the signal. */
1436         gcmkERR_BREAK(gckOS_WaitSignal(
1437             command->os,
1438             command->powerStallSignal,
1439             gcdGPU_TIMEOUT));
1440
1441
1442     }
1443     while(gcvFALSE);
1444
1445     gcmkFOOTER();
1446     /* Return the status. */
1447     return status;
1448 }
1449
1450 /*******************************************************************************
1451 **
1452 **  gckHARDWARE_SetPowerManagementState
1453 **
1454 **  Set GPU to a specified power state.
1455 **
1456 **  INPUT:
1457 **
1458 **      gckHARDWARE Harwdare
1459 **          Pointer to an gckHARDWARE object.
1460 **
1461 **      gceCHIPPOWERSTATE State
1462 **          Power State.
1463 **
1464 */
1465 gceSTATUS
1466 gckVGHARDWARE_SetPowerManagementState(
1467     IN gckVGHARDWARE Hardware,
1468     IN gceCHIPPOWERSTATE State
1469     )
1470 {
1471     gceSTATUS status;
1472     gckVGCOMMAND command = gcvNULL;
1473     gckOS os;
1474     gctUINT flag/*, clock*/;
1475
1476     gctBOOL acquired        = gcvFALSE;
1477     gctBOOL stall           = gcvTRUE;
1478     gctBOOL commitMutex     = gcvFALSE;
1479     gctBOOL mutexAcquired   = gcvFALSE;
1480
1481 #if gcdPOWEROFF_TIMEOUT
1482     gctBOOL timeout = gcvFALSE;
1483     gctBOOL isAfter = gcvFALSE;
1484     gctUINT32 currentTime;
1485 #endif
1486
1487     gctBOOL broadcast = gcvFALSE;
1488     gctUINT32 process, thread;
1489     gctBOOL global = gcvFALSE;
1490
1491 #if gcdENABLE_PROFILING
1492     gctUINT64 time, freq, mutexTime, onTime, stallTime, stopTime, delayTime,
1493               initTime, offTime, startTime, totalTime;
1494 #endif
1495
1496     /* State transition flags. */
1497     static const gctUINT flags[4][4] =
1498     {
1499         /* gcvPOWER_ON           */
1500         {   /* ON                */ 0,
1501             /* OFF               */ gcvPOWER_FLAG_ACQUIRE   |
1502                                     gcvPOWER_FLAG_STALL     |
1503                                     gcvPOWER_FLAG_STOP      |
1504                                     gcvPOWER_FLAG_POWER_OFF |
1505                                     gcvPOWER_FLAG_CLOCK_OFF,
1506             /* IDLE              */ gcvPOWER_FLAG_NOP,
1507             /* SUSPEND           */ gcvPOWER_FLAG_ACQUIRE   |
1508                                     gcvPOWER_FLAG_STALL     |
1509                                     gcvPOWER_FLAG_STOP      |
1510                                     gcvPOWER_FLAG_CLOCK_OFF,
1511         },
1512
1513         /* gcvPOWER_OFF          */
1514         {   /* ON                */ gcvPOWER_FLAG_INITIALIZE |
1515                                     gcvPOWER_FLAG_START      |
1516                                     gcvPOWER_FLAG_RELEASE    |
1517                                     gcvPOWER_FLAG_DELAY,
1518             /* OFF               */ 0,
1519             /* IDLE              */ gcvPOWER_FLAG_INITIALIZE |
1520                                     gcvPOWER_FLAG_START      |
1521                                     gcvPOWER_FLAG_RELEASE    |
1522                                     gcvPOWER_FLAG_DELAY,
1523             /* SUSPEND           */ gcvPOWER_FLAG_INITIALIZE |
1524                                     gcvPOWER_FLAG_CLOCK_OFF,
1525         },
1526
1527         /* gcvPOWER_IDLE         */
1528         {   /* ON                */ gcvPOWER_FLAG_NOP,
1529             /* OFF               */ gcvPOWER_FLAG_ACQUIRE   |
1530                                     gcvPOWER_FLAG_STOP      |
1531                                     gcvPOWER_FLAG_POWER_OFF |
1532                                     gcvPOWER_FLAG_CLOCK_OFF,
1533             /* IDLE              */ 0,
1534             /* SUSPEND           */ gcvPOWER_FLAG_ACQUIRE   |
1535                                     gcvPOWER_FLAG_STOP      |
1536                                     gcvPOWER_FLAG_CLOCK_OFF,
1537         },
1538
1539         /* gcvPOWER_SUSPEND      */
1540         {   /* ON                */ gcvPOWER_FLAG_START     |
1541                                     gcvPOWER_FLAG_RELEASE   |
1542                                     gcvPOWER_FLAG_DELAY     |
1543                                     gcvPOWER_FLAG_CLOCK_ON,
1544             /* OFF               */ gcvPOWER_FLAG_SAVE      |
1545                                     gcvPOWER_FLAG_POWER_OFF |
1546                                     gcvPOWER_FLAG_CLOCK_OFF,
1547             /* IDLE              */ gcvPOWER_FLAG_START     |
1548                                     gcvPOWER_FLAG_DELAY     |
1549                                     gcvPOWER_FLAG_RELEASE   |
1550                                     gcvPOWER_FLAG_CLOCK_ON,
1551             /* SUSPEND           */ 0,
1552         },
1553     };
1554
1555     gcmkHEADER_ARG("Hardware=0x%x State=%d", Hardware, State);
1556 #if gcmIS_DEBUG(gcdDEBUG_TRACE)
1557     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1558                    "Switching to power state %d",
1559                    State);
1560 #endif
1561
1562     /* Verify the arguments. */
1563     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1564
1565     /* Get the gckOS object pointer. */
1566     os = Hardware->os;
1567     gcmkVERIFY_OBJECT(os, gcvOBJ_OS);
1568
1569     /* Get the gckCOMMAND object pointer. */
1570     gcmkVERIFY_OBJECT(Hardware->kernel, gcvOBJ_KERNEL);
1571     command = Hardware->kernel->command;
1572     gcmkVERIFY_OBJECT(command, gcvOBJ_COMMAND);
1573
1574     if (Hardware->powerManagement == gcvFALSE)
1575     {
1576         gcmkFOOTER_NO();
1577         return gcvSTATUS_OK;
1578     }
1579
1580     /* Start profiler. */
1581     gcmkPROFILE_INIT(freq, time);
1582
1583     /* Convert the broadcast power state. */
1584     switch (State)
1585     {
1586     case gcvPOWER_SUSPEND_ATPOWERON:
1587         /* Convert to SUSPEND and don't wait for STALL. */
1588         State = gcvPOWER_SUSPEND;
1589         stall = gcvFALSE;
1590         break;
1591
1592     case gcvPOWER_OFF_ATPOWERON:
1593         /* Convert to OFF and don't wait for STALL. */
1594         State = gcvPOWER_OFF;
1595         stall = gcvFALSE;
1596         break;
1597
1598     case gcvPOWER_IDLE_BROADCAST:
1599         /* Convert to IDLE and note we are inside broadcast. */
1600         State     = gcvPOWER_IDLE;
1601         broadcast = gcvTRUE;
1602         break;
1603
1604     case gcvPOWER_SUSPEND_BROADCAST:
1605         /* Convert to SUSPEND and note we are inside broadcast. */
1606         State     = gcvPOWER_SUSPEND;
1607         broadcast = gcvTRUE;
1608         break;
1609
1610     case gcvPOWER_OFF_BROADCAST:
1611         /* Convert to OFF and note we are inside broadcast. */
1612         State     = gcvPOWER_OFF;
1613         broadcast = gcvTRUE;
1614         break;
1615
1616     case gcvPOWER_OFF_RECOVERY:
1617         /* Convert to OFF and note we are inside recovery. */
1618         State     = gcvPOWER_OFF;
1619         stall     = gcvFALSE;
1620         broadcast = gcvTRUE;
1621         break;
1622
1623     case gcvPOWER_ON_AUTO:
1624         /* Convert to ON and note we are inside recovery. */
1625         State = gcvPOWER_ON;
1626         break;
1627
1628     case gcvPOWER_ON:
1629     case gcvPOWER_IDLE:
1630     case gcvPOWER_SUSPEND:
1631     case gcvPOWER_OFF:
1632         /* Mark as global power management. */
1633         global = gcvTRUE;
1634         break;
1635
1636 #if gcdPOWEROFF_TIMEOUT
1637     case gcvPOWER_OFF_TIMEOUT:
1638         /* Convert to OFF and note we are inside broadcast. */
1639         State     = gcvPOWER_OFF;
1640         broadcast = gcvTRUE;
1641         /* Check time out */
1642         timeout = gcvTRUE;
1643         break;
1644 #endif
1645
1646     default:
1647         break;
1648     }
1649
1650     /* Get current process and thread IDs. */
1651     gcmkONERROR(gckOS_GetProcessID(&process));
1652     gcmkONERROR(gckOS_GetThreadID(&thread));
1653
1654     /* Acquire the power mutex. */
1655     if (broadcast)
1656     {
1657         /* Try to acquire the power mutex. */
1658         status = gckOS_AcquireMutex(os, Hardware->powerMutex, 0);
1659
1660         if (status == gcvSTATUS_TIMEOUT)
1661         {
1662             /* Check if we already own this mutex. */
1663             if ((Hardware->powerProcess == process)
1664             &&  (Hardware->powerThread  == thread)
1665             )
1666             {
1667                 /* Bail out on recursive power management. */
1668                 gcmkFOOTER_NO();
1669                 return gcvSTATUS_OK;
1670             }
1671             else if (State == gcvPOWER_IDLE)
1672             {
1673                 /* gcvPOWER_IDLE_BROADCAST is from IST,
1674                 ** so waiting here will cause deadlock,
1675                 ** if lock holder call gckCOMMAND_Stall() */
1676                 gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
1677             }
1678             else
1679             {
1680                 /* Acquire the power mutex. */
1681                 gcmkONERROR(gckOS_AcquireMutex(os,
1682                                                Hardware->powerMutex,
1683                                                gcvINFINITE));
1684             }
1685         }
1686     }
1687     else
1688     {
1689         /* Acquire the power mutex. */
1690         gcmkONERROR(gckOS_AcquireMutex(os, Hardware->powerMutex, gcvINFINITE));
1691     }
1692
1693     /* Get time until mtuex acquired. */
1694     gcmkPROFILE_QUERY(time, mutexTime);
1695
1696     Hardware->powerProcess = process;
1697     Hardware->powerThread  = thread;
1698     mutexAcquired          = gcvTRUE;
1699
1700     /* Grab control flags and clock. */
1701     flag  = flags[Hardware->chipPowerState][State];
1702     /*clock = clocks[State];*/
1703
1704 #if gcdPOWEROFF_TIMEOUT
1705     if (timeout)
1706     {
1707         gcmkONERROR(gckOS_GetTicks(&currentTime));
1708
1709         gcmkONERROR(
1710             gckOS_TicksAfter(Hardware->powerOffTime, currentTime, &isAfter));
1711
1712         /* powerOffTime is pushed forward, give up.*/
1713         if (isAfter
1714         /* Expect a transition start from IDLE. */
1715         ||  (Hardware->chipPowerState == gcvPOWER_ON)
1716         ||  (Hardware->chipPowerState == gcvPOWER_OFF)
1717         )
1718         {
1719             /* Release the power mutex. */
1720             gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1721
1722             /* No need to do anything. */
1723             gcmkFOOTER_NO();
1724             return gcvSTATUS_OK;
1725         }
1726     }
1727 #endif
1728
1729     if (flag == 0)
1730     {
1731         /* Release the power mutex. */
1732         gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1733
1734         /* No need to do anything. */
1735         gcmkFOOTER_NO();
1736         return gcvSTATUS_OK;
1737     }
1738
1739     /* internal power control */
1740     if (!global)
1741     {
1742         if (Hardware->chipPowerStateGlobal == gcvPOWER_OFF)
1743         {
1744             /* Release the power mutex. */
1745             gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1746
1747             /* No need to do anything. */
1748             gcmkFOOTER_NO();
1749             return gcvSTATUS_OK;
1750         }
1751     }
1752     else
1753     {
1754         if (flag & gcvPOWER_FLAG_ACQUIRE)
1755         {
1756             /* Acquire the power management semaphore. */
1757             gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
1758             acquired = gcvTRUE;
1759
1760             /* avoid acquiring again. */
1761             flag &= ~gcvPOWER_FLAG_ACQUIRE;
1762         }
1763     }
1764
1765     if (flag & (gcvPOWER_FLAG_INITIALIZE | gcvPOWER_FLAG_CLOCK_ON))
1766     {
1767         /* Turn on the power. */
1768         gcmkONERROR(gckOS_SetGPUPower(os, gcvCORE_VG, gcvTRUE, gcvTRUE));
1769
1770         /* Mark clock and power as enabled. */
1771         Hardware->clockState = gcvTRUE;
1772         Hardware->powerState = gcvTRUE;
1773     }
1774
1775     /* Get time until powered on. */
1776     gcmkPROFILE_QUERY(time, onTime);
1777
1778     if ((flag & gcvPOWER_FLAG_STALL) && stall)
1779     {
1780         /* Acquire the mutex. */
1781         gcmkONERROR(gckOS_AcquireMutex(
1782             command->os,
1783             command->commitMutex,
1784             gcvINFINITE
1785             ));
1786
1787         commitMutex = gcvTRUE;
1788
1789         gcmkONERROR(_CommandStall(Hardware));
1790     }
1791
1792     /* Get time until stalled. */
1793     gcmkPROFILE_QUERY(time, stallTime);
1794
1795     if (flag & gcvPOWER_FLAG_ACQUIRE)
1796     {
1797         /* Acquire the power management semaphore. */
1798         gcmkONERROR(gckOS_AcquireSemaphore(os, command->powerSemaphore));
1799
1800         acquired = gcvTRUE;
1801     }
1802
1803     if (flag & gcvPOWER_FLAG_STOP)
1804     {
1805     }
1806
1807     /* Get time until stopped. */
1808     gcmkPROFILE_QUERY(time, stopTime);
1809
1810     /* Only process this when hardware is enabled. */
1811     if (Hardware->clockState && Hardware->powerState)
1812     {
1813     }
1814
1815     if (flag & gcvPOWER_FLAG_DELAY)
1816     {
1817         /* Wait for the specified amount of time to settle coming back from
1818         ** power-off or suspend state. */
1819         gcmkONERROR(gckOS_Delay(os, gcdPOWER_CONTROL_DELAY));
1820     }
1821
1822     /* Get time until delayed. */
1823     gcmkPROFILE_QUERY(time, delayTime);
1824
1825     if (flag & gcvPOWER_FLAG_INITIALIZE)
1826     {
1827         gcmkONERROR(gckVGHARDWARE_SetMMU(Hardware, Hardware->kernel->mmu->pageTableLogical));
1828
1829         /* Force the command queue to reload the next context. */
1830         command->currentContext = 0;
1831     }
1832
1833     /* Get time until initialized. */
1834     gcmkPROFILE_QUERY(time, initTime);
1835
1836     if (flag & (gcvPOWER_FLAG_POWER_OFF | gcvPOWER_FLAG_CLOCK_OFF))
1837     {
1838         /* Turn off the GPU power. */
1839         gcmkONERROR(
1840             gckOS_SetGPUPower(os,
1841                               gcvCORE_VG,
1842                               (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
1843                                                                : gcvTRUE,
1844                               (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
1845                                                                : gcvTRUE));
1846
1847         /* Save current hardware power and clock states. */
1848         Hardware->clockState = (flag & gcvPOWER_FLAG_CLOCK_OFF) ? gcvFALSE
1849                                                                 : gcvTRUE;
1850         Hardware->powerState = (flag & gcvPOWER_FLAG_POWER_OFF) ? gcvFALSE
1851                                                                 : gcvTRUE;
1852     }
1853
1854     /* Get time until off. */
1855     gcmkPROFILE_QUERY(time, offTime);
1856
1857     if (flag & gcvPOWER_FLAG_START)
1858     {
1859     }
1860
1861     /* Get time until started. */
1862     gcmkPROFILE_QUERY(time, startTime);
1863
1864     if (flag & gcvPOWER_FLAG_RELEASE)
1865     {
1866         /* Release the power management semaphore. */
1867         gcmkONERROR(gckOS_ReleaseSemaphore(os, command->powerSemaphore));
1868         acquired = gcvFALSE;
1869     }
1870
1871     /* Save the new power state. */
1872     Hardware->chipPowerState = State;
1873
1874     if (global)
1875     {
1876         /* Save the new power state. */
1877         Hardware->chipPowerStateGlobal = State;
1878     }
1879
1880     if (commitMutex)
1881     {
1882         /* Acquire the mutex. */
1883         gcmkVERIFY_OK(gckOS_ReleaseMutex(
1884             command->os,
1885             command->commitMutex
1886             ));
1887     }
1888
1889 #if gcdPOWEROFF_TIMEOUT
1890     /* Reset power off time */
1891     gcmkONERROR(gckOS_GetTicks(&currentTime));
1892
1893     Hardware->powerOffTime = currentTime + Hardware->powerOffTimeout;
1894
1895     if (State == gcvPOWER_IDLE)
1896     {
1897         /* Start a timer to power off GPU when GPU enters IDLE or SUSPEND. */
1898         gcmkVERIFY_OK(gckOS_StartTimer(os,
1899                                        Hardware->powerOffTimer,
1900                                        Hardware->powerOffTimeout));
1901     }
1902     else
1903     {
1904         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE, "Cancel powerOfftimer");
1905
1906         /* Cancel running timer when GPU enters ON or OFF. */
1907         gcmkVERIFY_OK(gckOS_StopTimer(os, Hardware->powerOffTimer));
1908     }
1909 #endif
1910
1911     /* Release the power mutex. */
1912     gcmkONERROR(gckOS_ReleaseMutex(os, Hardware->powerMutex));
1913
1914     /* Get total time. */
1915     gcmkPROFILE_QUERY(time, totalTime);
1916 #if gcdENABLE_PROFILING
1917     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1918                    "PROF(%llu): mutex:%llu on:%llu stall:%llu stop:%llu",
1919                    freq, mutexTime, onTime, stallTime, stopTime);
1920     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HARDWARE,
1921                    "  delay:%llu init:%llu off:%llu start:%llu total:%llu",
1922                    delayTime, initTime, offTime, startTime, totalTime);
1923 #endif
1924
1925     /* Success. */
1926     gcmkFOOTER_NO();
1927     return gcvSTATUS_OK;
1928
1929 OnError:
1930
1931     if (acquired)
1932     {
1933         /* Release semaphore. */
1934         gcmkVERIFY_OK(gckOS_ReleaseSemaphore(Hardware->os,
1935                                              command->powerSemaphore));
1936     }
1937
1938     if (mutexAcquired)
1939     {
1940         gcmkVERIFY_OK(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
1941     }
1942
1943     if (commitMutex)
1944     {
1945         /* Acquire the mutex. */
1946         gcmkVERIFY_OK(gckOS_ReleaseMutex(
1947             command->os,
1948             command->commitMutex
1949             ));
1950     }
1951
1952     /* Return the status. */
1953     gcmkFOOTER();
1954     return status;
1955 }
1956
1957 /*******************************************************************************
1958 **
1959 **  gckHARDWARE_QueryPowerManagementState
1960 **
1961 **  Get GPU power state.
1962 **
1963 **  INPUT:
1964 **
1965 **      gckHARDWARE Harwdare
1966 **          Pointer to an gckHARDWARE object.
1967 **
1968 **      gceCHIPPOWERSTATE* State
1969 **          Power State.
1970 **
1971 */
1972 gceSTATUS
1973 gckVGHARDWARE_QueryPowerManagementState(
1974     IN gckVGHARDWARE Hardware,
1975     OUT gceCHIPPOWERSTATE* State
1976     )
1977 {
1978     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
1979
1980     /* Verify the arguments. */
1981     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
1982     gcmkVERIFY_ARGUMENT(State != gcvNULL);
1983
1984     /* Return the statue. */
1985     *State = Hardware->chipPowerState;
1986
1987     /* Success. */
1988     gcmkFOOTER_ARG("*State=%d", *State);
1989     return gcvSTATUS_OK;
1990 }
1991
1992 /*******************************************************************************
1993 **
1994 **  gckVGHARDWARE_SetPowerManagement
1995 **
1996 **  Configure GPU power management function.
1997 **  Only used in driver initialization stage.
1998 **
1999 **  INPUT:
2000 **
2001 **      gckVGHARDWARE Harwdare
2002 **          Pointer to an gckHARDWARE object.
2003 **
2004 **      gctBOOL PowerManagement
2005 **          Power Mangement State.
2006 **
2007 */
2008 gceSTATUS
2009 gckVGHARDWARE_SetPowerManagement(
2010     IN gckVGHARDWARE Hardware,
2011     IN gctBOOL PowerManagement
2012     )
2013 {
2014     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2015
2016     /* Verify the arguments. */
2017     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2018
2019     Hardware->powerManagement = PowerManagement;
2020
2021     /* Success. */
2022     gcmkFOOTER_NO();
2023     return gcvSTATUS_OK;
2024 }
2025
2026 gceSTATUS
2027 gckVGHARDWARE_SetPowerOffTimeout(
2028     IN gckVGHARDWARE  Hardware,
2029     IN gctUINT32    Timeout
2030     )
2031 {
2032     gcmkHEADER_ARG("Hardware=0x%x Timeout=%d", Hardware, Timeout);
2033
2034     Hardware->powerOffTimeout = Timeout;
2035
2036     gcmkFOOTER_NO();
2037     return gcvSTATUS_OK;
2038 }
2039
2040
2041 gceSTATUS
2042 gckVGHARDWARE_QueryPowerOffTimeout(
2043     IN gckVGHARDWARE  Hardware,
2044     OUT gctUINT32*  Timeout
2045     )
2046 {
2047     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2048
2049     *Timeout = Hardware->powerOffTimeout;
2050
2051     gcmkFOOTER_ARG("*Timeout=%d", *Timeout);
2052     return gcvSTATUS_OK;
2053 }
2054
2055 gceSTATUS
2056 gckVGHARDWARE_QueryIdle(
2057     IN gckVGHARDWARE Hardware,
2058     OUT gctBOOL_PTR IsIdle
2059     )
2060 {
2061     gceSTATUS status;
2062     gctUINT32 idle;
2063
2064     gcmkHEADER_ARG("Hardware=0x%x", Hardware);
2065
2066     /* Verify the arguments. */
2067     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
2068     gcmkVERIFY_ARGUMENT(IsIdle != gcvNULL);
2069
2070     /* We are idle when the power is not ON. */
2071     if (Hardware->chipPowerState != gcvPOWER_ON)
2072     {
2073         *IsIdle = gcvTRUE;
2074     }
2075
2076     else
2077     {
2078         /* Read idle register. */
2079         gcmkONERROR(
2080             gckOS_ReadRegisterEx(Hardware->os, gcvCORE_VG, 0x00004, &idle));
2081
2082         /* Pipe must be idle. */
2083         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)
2084         ||  ((((((gctUINT32) (idle)) >> (0 ? 8:8)) & ((gctUINT32) ((((1 ? 8:8) - (0 ? 8:8) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 8:8) - (0 ? 8:8) + 1)))))) ) != 1)
2085         ||  ((((((gctUINT32) (idle)) >> (0 ? 9:9)) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1)))))) ) != 1)
2086         ||  ((((((gctUINT32) (idle)) >> (0 ? 10:10)) & ((gctUINT32) ((((1 ? 10:10) - (0 ? 10:10) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 10:10) - (0 ? 10:10) + 1)))))) ) != 1)
2087         ||  ((((((gctUINT32) (idle)) >> (0 ? 11:11)) & ((gctUINT32) ((((1 ? 11:11) - (0 ? 11:11) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 11:11) - (0 ? 11:11) + 1)))))) ) != 1)
2088         )
2089         {
2090             /* Something is busy. */
2091             *IsIdle = gcvFALSE;
2092         }
2093
2094         else
2095         {
2096             *IsIdle = gcvTRUE;
2097         }
2098     }
2099
2100     /* Success. */
2101     gcmkFOOTER_NO();
2102     return gcvSTATUS_OK;
2103
2104 OnError:
2105     /* Return the status. */
2106     gcmkFOOTER();
2107     return status;
2108 }
2109 #endif /* gcdENABLE_VG */
2110