1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - GX -
3   File:     gx.c
4 
5   Copyright 2003-2008 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-02-04#$
14   $Rev: 9967 $
15   $Author: kitase_hirotake $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro/gx/gx.h>
19 #include <nitro/mi/dma.h>
20 
21 #ifdef SDK_TWL
22 #include <twl/mi/common/dma.h>
23 #endif
24 
25 #include <nitro/os/common/spinLock.h>
26 #include "../include/gxstate.h"
27 
28 #ifdef  SDK_ARM9
29 #include <nitro/os/ARM9/vramExclusive.h>
30 #include <nitro/spi/ARM9/pm.h>
31 #endif
32 
33 
34 u32     GXi_DmaId = GX_DEFAULT_DMAID;
35 
36 #ifdef  SDK_ARM9
37 vu16    GXi_VRamLockId = 0;
38 #endif
39 
40 /*---------------------------------------------------------------------------*
41   Name:         GX_Init
42 
43   Description:  Initializes the registers for graphics(except 3D).
44 
45   Arguments:    none
46 
47   Returns:      none
48  *---------------------------------------------------------------------------*/
GX_Init()49 void GX_Init()
50 {
51     const u16 bg_mtx_elem_one = 1 << 8;
52 
53     reg_GX_POWCNT |= (1 << REG_GX_POWCNT_DSEL_SHIFT);
54     GX_SetPower(GX_POWER_ALL);
55     GXi_PowerLCD(TRUE);
56     GX_InitGXState();
57 
58 #ifdef  SDK_ARM9
59     {
60         s32     lockResult;
61 
62         while (GXi_VRamLockId == 0)
63         {
64             lockResult = OS_GetLockID();
65             if (lockResult == OS_LOCK_ID_ERROR)
66             {
67                 OS_Panic("Could not get lock ID for VRAM exclusive.\n");
68             }
69             GXi_VRamLockId = (u16)lockResult;
70         }
71     }
72 #endif
73 
74 #if 1
75     // smaller binary size
76 
77     //
78     // Main engine
79     //
80     reg_GX_DISPSTAT = 0;
81     reg_GX_DISPCNT = 0;
82     if (GXi_DmaId != GX_DMA_NOT_USE)
83     {
84 #ifdef SDK_TWL
85         if (GXi_DmaId > 3)
86         {
87             MI_NDmaFill(GXi_DmaId-4, (void *)REG_BG0CNT_ADDR, 0,
88                          REG_DISP_MMEM_FIFO_ADDR - REG_BG0CNT_ADDR);
89             reg_GX_MASTER_BRIGHT = 0;
90             //
91             // Sub engine
92             //
93             MI_NDmaFill(GXi_DmaId-4, (void *)REG_DB_DISPCNT_ADDR, 0,
94                          REG_DB_MASTER_BRIGHT_ADDR - REG_DB_DISPCNT_ADDR + 4);
95         }
96         else
97 #endif
98         {
99             MI_DmaFill32(GXi_DmaId, (void *)REG_BG0CNT_ADDR, 0,
100                          REG_DISP_MMEM_FIFO_ADDR - REG_BG0CNT_ADDR);
101             reg_GX_MASTER_BRIGHT = 0;
102             //
103             // Sub engine
104             //
105             MI_DmaFill32(GXi_DmaId, (void *)REG_DB_DISPCNT_ADDR, 0,
106                          REG_DB_MASTER_BRIGHT_ADDR - REG_DB_DISPCNT_ADDR + 4);
107         }
108     }
109     else
110     {
111         MI_CpuFill32((void *)REG_BG0CNT_ADDR, 0, REG_DISP_MMEM_FIFO_ADDR - REG_BG0CNT_ADDR);
112         reg_GX_MASTER_BRIGHT = 0;
113         //
114         // Sub engine
115         //
116         MI_CpuFill32((void *)REG_DB_DISPCNT_ADDR, 0,
117                      REG_DB_MASTER_BRIGHT_ADDR - REG_DB_DISPCNT_ADDR + 4);
118     }
119 
120 
121     //
122     // Initialize BG matrices as identity ones.
123     //
124     reg_G2_BG2PA = bg_mtx_elem_one;
125     reg_G2_BG2PD = bg_mtx_elem_one;
126     reg_G2_BG3PA = bg_mtx_elem_one;
127     reg_G2_BG3PD = bg_mtx_elem_one;
128     reg_G2S_DB_BG2PA = bg_mtx_elem_one;
129     reg_G2S_DB_BG2PD = bg_mtx_elem_one;
130     reg_G2S_DB_BG3PA = bg_mtx_elem_one;
131     reg_G2S_DB_BG3PD = bg_mtx_elem_one;
132 
133 #else
134     //
135     // Main engine
136     //
137     reg_GX_DISPSTAT = 0;
138     reg_GX_DISPCNT = 0;
139 
140     // init capture register
141     reg_GX_DISPCAPCNT = 0;
142 
143     // init BGxCNT
144     reg_G2_BG0CNT = 0;
145     reg_G2_BG1CNT = 0;
146     reg_G2_BG2CNT = 0;
147     reg_G2_BG3CNT = 0;
148 
149     // reset BG offsets
150     reg_G2_BG0OFS = 0;
151     reg_G2_BG1OFS = 0;
152     reg_G2_BG2OFS = 0;
153     reg_G2_BG3OFS = 0;
154 
155     // init affine BG
156     reg_G2_BG2X = 0;
157     reg_G2_BG2Y = 0;
158     reg_G2_BG3X = 0;
159     reg_G2_BG3Y = 0;
160     reg_G2_BG2PA = bg_mtx_elem_one;
161     reg_G2_BG2PB = 0;
162     reg_G2_BG2PC = 0;
163     reg_G2_BG2PD = bg_mtx_elem_one;
164     reg_G2_BG3PA = bg_mtx_elem_one;
165     reg_G2_BG3PB = 0;
166     reg_G2_BG3PC = 0;
167     reg_G2_BG3PD = bg_mtx_elem_one;
168 
169     // init windows
170     reg_G2_WININ = 0;
171     reg_G2_WINOUT = 0;
172     reg_G2_WIN0H = 0;
173     reg_G2_WIN1H = 0;
174     reg_G2_WIN0V = 0;
175     reg_G2_WIN1V = 0;
176 
177     // init mosaic
178     reg_G2_MOSAIC = 0;
179 
180     // init blending
181     reg_G2_BLDCNT = 0;
182     reg_G2_BLDALPHA = 0;
183     reg_G2_BLDY = 0;
184 
185     // init master brightness
186     reg_GX_MASTER_BRIGHT = 0;
187 
188     //
189     // Sub engine
190     //
191     reg_GXS_DB_DISPCNT = 0;
192 
193     // init BGxCNT
194     reg_G2S_DB_BG0CNT = 0;
195     reg_G2S_DB_BG1CNT = 0;
196     reg_G2S_DB_BG2CNT = 0;
197     reg_G2S_DB_BG3CNT = 0;
198 
199     // reset BG offsets
200     reg_G2S_DB_BG0OFS = 0;
201     reg_G2S_DB_BG1OFS = 0;
202     reg_G2S_DB_BG2OFS = 0;
203     reg_G2S_DB_BG3OFS = 0;
204 
205     // init affine BG
206     reg_G2S_DB_BG2X = 0;
207     reg_G2S_DB_BG2Y = 0;
208     reg_G2S_DB_BG3X = 0;
209     reg_G2S_DB_BG3Y = 0;
210     reg_G2S_DB_BG2PA = bg_mtx_elem_one;
211     reg_G2S_DB_BG2PB = 0;
212     reg_G2S_DB_BG2PC = 0;
213     reg_G2S_DB_BG2PD = bg_mtx_elem_one;
214     reg_G2S_DB_BG3PA = bg_mtx_elem_one;
215     reg_G2S_DB_BG3PB = 0;
216     reg_G2S_DB_BG3PC = 0;
217     reg_G2S_DB_BG3PD = bg_mtx_elem_one;
218 
219     // init windows
220     reg_G2S_DB_WININ = 0;
221     reg_G2S_DB_WINOUT = 0;
222     reg_G2S_DB_WIN0H = 0;
223     reg_G2S_DB_WIN1H = 0;
224     reg_G2S_DB_WIN0V = 0;
225     reg_G2S_DB_WIN1V = 0;
226 
227     // init mosaic
228     reg_G2S_DB_MOSAIC = 0;
229 
230     // init blending
231     reg_G2S_DB_BLDCNT = 0;
232     reg_G2S_DB_BLDALPHA = 0;
233     reg_G2S_DB_BLDY = 0;
234 
235     // init master brightness
236     reg_GXS_DB_MASTER_BRIGHT = 0;
237 #endif
238 }
239 
240 /*---------------------------------------------------------------------------*
241   Name:         GX_SetVCountEqVal
242 
243   Description:  Specifies the V-counter agreement value.
244 
245   Arguments:    val        the value of V-counter
246 
247   Returns:      none
248  *---------------------------------------------------------------------------*/
GX_SetVCountEqVal(s32 val)249 void GX_SetVCountEqVal(s32 val)
250 {
251     SDK_MINMAX_ASSERT(val, 0, 262);
252     reg_GX_DISPSTAT = (u16)((reg_GX_DISPSTAT & (REG_GX_DISPSTAT_VBLK_MASK |
253                                                 REG_GX_DISPSTAT_HBLK_MASK |
254                                                 REG_GX_DISPSTAT_LYC_MASK |
255                                                 REG_GX_DISPSTAT_VBI_MASK |
256                                                 REG_GX_DISPSTAT_HBI_MASK |
257                                                 REG_GX_DISPSTAT_VQI_MASK)) |
258                             ((val & 0xff) << 8) | ((val & 0x100) >> 1));
259 }
260 
261 
262 /*---------------------------------------------------------------------------*
263   Name:         GX_HBlankIntr
264 
265   Description:  Enables/Disables the H-Blank interrupt generation.
266 
267   Arguments:    enable     disable if FALSE, enable otherwise.
268 
269   Returns:      none
270  *---------------------------------------------------------------------------*/
GX_HBlankIntr(BOOL enable)271 s32 GX_HBlankIntr(BOOL enable)
272 {
273     s32     rval = (reg_GX_DISPSTAT & REG_GX_DISPSTAT_HBI_MASK);
274     if (enable)
275     {
276         reg_GX_DISPSTAT |= REG_GX_DISPSTAT_HBI_MASK;
277     }
278     else
279     {
280         reg_GX_DISPSTAT &= ~REG_GX_DISPSTAT_HBI_MASK;
281     }
282     return rval;
283 }
284 
285 
286 /*---------------------------------------------------------------------------*
287   Name:         GX_VBlankIntr
288 
289   Description:  Enables/Disables the V-Blank interrupt generation.
290 
291   Arguments:    enable     disable if FALSE, enable otherwise.
292 
293   Returns:      none
294  *---------------------------------------------------------------------------*/
GX_VBlankIntr(BOOL enable)295 s32 GX_VBlankIntr(BOOL enable)
296 {
297     s32     rval = (reg_GX_DISPSTAT & REG_GX_DISPSTAT_VBI_MASK);
298     if (enable)
299     {
300         reg_GX_DISPSTAT |= REG_GX_DISPSTAT_VBI_MASK;
301     }
302     else
303     {
304         reg_GX_DISPSTAT &= ~REG_GX_DISPSTAT_VBI_MASK;
305     }
306     return rval;
307 }
308 
309 
310 //---------------------------------------------------------------------------
311 // Internal state for GX_DispOff, GX_DispOn, GX_SetGraphicsMode
312 //---------------------------------------------------------------------------
313 // Use u16 to avoid byte access problem(thumb mode).
314 static u16 sDispMode = 0;
315 static u16 sIsDispOn = TRUE;
316 
317 
318 /*---------------------------------------------------------------------------*
319   Name:         GX_IsDispOn
320 
321   Description:  Get displaying state.
322 
323   Arguments:    none
324 
325   Returns:      if disp is ON  then TRUE
326                 else FALSE
327  *---------------------------------------------------------------------------*/
GX_IsDispOn(void)328 BOOL GX_IsDispOn(void)
329 {
330     return sIsDispOn;
331 }
332 
333 
334 /*---------------------------------------------------------------------------*
335   Name:         GX_DispOff
336 
337   Description:  Stops displaying the output of the MAIN engine.
338 
339   Arguments:    none
340 
341   Returns:      none
342  *---------------------------------------------------------------------------*/
GX_DispOff(void)343 void GX_DispOff(void)
344 {
345     u32     tmp = reg_GX_DISPCNT;
346 
347     sIsDispOn = FALSE;
348     sDispMode = (u16)((tmp & REG_GX_DISPCNT_MODE_MASK) >> REG_GX_DISPCNT_MODE_SHIFT);
349 
350     reg_GX_DISPCNT = tmp & ~REG_GX_DISPCNT_MODE_MASK;
351 
352 	//---- record disp off counter
353 	PMi_SetDispOffCount();
354 }
355 
356 
357 /*---------------------------------------------------------------------------*
358   Name:         GX_DispOn
359 
360   Description:  Starts displaying the output of the MAIN engine.
361 
362   Arguments:    none
363 
364   Returns:      none
365  *---------------------------------------------------------------------------*/
GX_DispOn(void)366 void GX_DispOn(void)
367 {
368     sIsDispOn = TRUE;
369     if (sDispMode != (u16)GX_DISPMODE_OFF)
370     {
371         // restore
372         reg_GX_DISPCNT =
373             ((reg_GX_DISPCNT & ~REG_GX_DISPCNT_MODE_MASK) |
374              (sDispMode << REG_GX_DISPCNT_MODE_SHIFT));
375     }
376     else
377     {
378         // GX_DISPMODE_GRAPHICS if sDispMode is GX_DISPMODE_OFF
379         reg_GX_DISPCNT = ((reg_GX_DISPCNT | (GX_DISPMODE_GRAPHICS << REG_GX_DISPCNT_MODE_SHIFT)));
380     }
381 }
382 
383 
384 /*---------------------------------------------------------------------------*
385   Name:         GX_SetGraphicsMode
386 
387   Description:  Specifies display mode and BG mode(MAIN engine).
388 
389   Arguments:    dispMode   display mode
390                 bgMode     BG mode
391                 bg0_2d3D   select 2D/3D for BG #0
392 
393   Returns:      none
394  *---------------------------------------------------------------------------*/
GX_SetGraphicsMode(GXDispMode dispMode,GXBGMode bgMode,GXBG0As bg0_2d3d)395 void GX_SetGraphicsMode(GXDispMode dispMode, GXBGMode bgMode, GXBG0As bg0_2d3d)
396 {
397     u32     cnt = reg_GX_DISPCNT;
398 
399     GX_DISPMODE_ASSERT(dispMode);
400     SDK_WARNING(dispMode != GX_DISPMODE_OFF,
401                 "A parameter GX_DISPMODE_OFF is obsolete. Use GX_DispOff() instead.");
402 
403     sDispMode = (u16)dispMode;
404     if (!sIsDispOn)
405     {
406         dispMode = GX_DISPMODE_OFF;
407     }
408 
409     GX_BGMODE_ASSERT(bgMode);
410     GX_BG0_AS_ASSERT(bg0_2d3d);
411     cnt &= ~(REG_GX_DISPCNT_BGMODE_MASK |
412              REG_GX_DISPCNT_BG02D3D_MASK | REG_GX_DISPCNT_MODE_MASK | REG_GX_DISPCNT_VRAM_MASK);
413 
414     reg_GX_DISPCNT = (u32)(cnt |
415                            (dispMode << REG_GX_DISPCNT_MODE_SHIFT) |
416                            (bgMode << REG_GX_DISPCNT_BGMODE_SHIFT) | (bg0_2d3d <<
417                                                                       REG_GX_DISPCNT_BG02D3D_SHIFT));
418 
419     // needless when GX_DISPMODE_OFF is removed.
420     if (sDispMode == GX_DISPMODE_OFF)
421     {
422         sIsDispOn = FALSE;
423     }
424 }
425 
426 /*---------------------------------------------------------------------------*
427   Name:         GXS_SetGraphicsMode
428 
429   Description:  Specifies BG mode(SUB engine).
430 
431   Arguments:    bgMode     BG mode
432 
433   Returns:      none
434  *---------------------------------------------------------------------------*/
GXS_SetGraphicsMode(GXBGMode bgMode)435 void GXS_SetGraphicsMode(GXBGMode bgMode)
436 {
437     reg_GXS_DB_DISPCNT = ((reg_GXS_DB_DISPCNT & ~REG_GXS_DB_DISPCNT_BGMODE_MASK) |
438                           (bgMode << REG_GXS_DB_DISPCNT_BGMODE_SHIFT));
439 }
440 
441 //
442 // Internal use
443 //
GXx_SetMasterBrightness_(vu16 * reg,int brightness)444 void GXx_SetMasterBrightness_(vu16 *reg, int brightness)
445 {
446     SDK_MINMAX_ASSERT(brightness, -16, 16);
447 
448     if (brightness == 0)
449     {
450         *reg = 0;
451     }
452     else if (brightness > 0)
453     {
454         *reg = (u16)((1 << REG_GX_MASTER_BRIGHT_E_MOD_SHIFT) | brightness);
455     }
456     else
457     {
458         *reg = (u16)((2 << REG_GX_MASTER_BRIGHT_E_MOD_SHIFT) | (-brightness));
459     }
460 }
461 
462 //
463 // Internal use
464 //
GXx_GetMasterBrightness_(vu16 * reg)465 int GXx_GetMasterBrightness_(vu16 *reg)
466 {
467     u16     mode = (u16)(*reg & REG_GX_MASTER_BRIGHT_E_MOD_MASK);
468 
469     if (mode == 0)
470     {
471         return 0;
472     }
473     else if (mode == (1 << REG_GX_MASTER_BRIGHT_E_MOD_SHIFT))
474     {
475         return *reg & REG_GX_MASTER_BRIGHT_E_VALUE_MASK;
476     }
477     else if (mode == (2 << REG_GX_MASTER_BRIGHT_E_MOD_SHIFT))
478     {
479         return -(*reg & REG_GX_MASTER_BRIGHT_E_VALUE_MASK);
480     }
481     else
482     {
483         OS_TWarning("Illegal MasterBright mode!\n");
484         return 0;
485     }
486 }
487 
488 
489 /*---------------------------------------------------------------------------*
490   Name:         GX_SetDefaultDMA
491 
492   Description:  set default DMA channel
493 
494   Arguments:    dma_no           default dma channel for GX
495                                  if out of range(0-3),
496                                  use CpuCopy instead of DMA.
497 
498   Returns:      previous DMA channel.
499  *---------------------------------------------------------------------------*/
GX_SetDefaultDMA(u32 dma_no)500 u32 GX_SetDefaultDMA(u32 dma_no)
501 {
502     u32     previous = GXi_DmaId;
503     OSIntrMode enabled;
504 
505     SDK_ASSERT((dma_no <= MI_DMA_MAX_NUM) || (dma_no == GX_DMA_NOT_USE));
506 
507     if (GXi_DmaId != GX_DMA_NOT_USE)
508     {
509         MI_WaitDma(GXi_DmaId);
510     }
511 
512     enabled = OS_DisableInterrupts();
513 
514     GXi_DmaId = dma_no;
515 
516     (void)OS_RestoreInterrupts(enabled);
517 
518     if (previous > 3)
519     {
520         return GX_DMA_NOT_USE;
521     }
522     return previous;
523 }
524 
525 /*---------------------------------------------------------------------------*
526   Name:         GX_SetDefaultNDMA
527 
528   Description:  set default NDMA channel
529 
530   Arguments:    ndma_no           default ndma channel for GX
531                                  if out of range(0-3),
532                                  use CpuCopy instead of NDMA.
533 
534   Returns:      previous DMA channel.
535  *---------------------------------------------------------------------------*/
536 #ifdef SDK_TWL
GX_SetDefaultNDMA(u32 ndma_no)537 u32 GX_SetDefaultNDMA(u32 ndma_no)
538 {
539     u32     previous = GXi_DmaId;
540     OSIntrMode enabled;
541 
542     if( OS_IsRunOnTwl() )
543     {
544         SDK_ASSERT((ndma_no <= MI_DMA_MAX_NUM) || (ndma_no == GX_DMA_NOT_USE));
545 
546         if (GXi_DmaId != GX_DMA_NOT_USE)
547         {
548             MI_WaitDma(GXi_DmaId);
549         }
550 
551         enabled = OS_DisableInterrupts();
552 
553         GXi_DmaId = ndma_no+4;
554 
555         (void)OS_RestoreInterrupts(enabled);
556 
557         if (previous > 3)
558         {
559             return previous-4;
560         }
561     }
562     return GX_DMA_NOT_USE;
563 }
564 #endif
565