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