vidreset.c
2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <bcp.h>
#include "vidreset.h"
extern void __osBbDelay(u32 usec);
extern u32 __osDisableInt(void);
extern void __osRestoreInt(u32 mask);
extern void __osBbVideoPllInit(s32 tvType);
/*
* Helper routines for video reset
*/
#define SIGNATURE 0x43210123
static void
sig_put()
{
u32 ctrl = IO_READ(VI_CONTROL_REG);
IO_WRITE(VI_CONTROL_REG, 0x880);
IO_WRITE(VI_SPANADDR_REG, 0);
IO_WRITE(VI_SPANDATA_REG, SIGNATURE);
IO_WRITE(VI_SPANADDR_REG, 1);
IO_WRITE(VI_SPANDATA_REG, 0);
IO_WRITE(VI_SPANADDR_REG, 2);
IO_WRITE(VI_SPANDATA_REG, 0);
IO_WRITE(VI_SPANADDR_REG, 3);
IO_WRITE(VI_SPANDATA_REG, 0);
IO_WRITE(VI_CONTROL_REG, ctrl);
}
static int
sig_check()
{
u32 sig;
u32 ctrl = IO_READ(VI_CONTROL_REG);
IO_WRITE(VI_CONTROL_REG, 0x880);
IO_WRITE(VI_SPANADDR_REG, 0);
sig = IO_READ(VI_SPANDATA_REG);
IO_WRITE(VI_CONTROL_REG, ctrl);
if (sig == SIGNATURE) {
return 1;
} else {
return 0;
}
}
/*
* Note this should return with the VI correctly out of reset and also
* disabled. You can do video set up using libultra routines after this.
* It needs some frame buffer area to work. Right now it should only use
* the first 10 lines of the buffer.
*
* To keep things simple we use a 320 wide x 16 bits/pixel framebuffer
*
* Before this function is called the PLL should be set up.
*
* Interrupts are disabled. It may not matter, but just in case. This routine
* should be called before osInitialize() anyway
*
*/
int vidReset(u16 *cfb)
{
u32 avctrl;
int cnt = 0;
u32 mask;
mask = __osDisableInt();
/*
* Clear a few lines in the Framebuffer first
*/
memset(cfb, 0, 320*10*2);
do {
IO_WRITE(VI_CONTROL_REG, 0x0);
__osBbDelay(10);
// Reset the video subsystem
avctrl = IO_READ(MI_AVCTRL_REG);
avctrl &= ~MI_AVCTRL_AV_RESET;
IO_WRITE(MI_AVCTRL_REG, avctrl);
__osBbDelay(1);
IO_WRITE(MI_AVCTRL_REG, avctrl | MI_AVCTRL_AV_RESET);
// Fill up the registers
IO_WRITE(VI_ORIGIN_REG, cfb);
IO_WRITE(VI_WIDTH_REG, 0x140);
IO_WRITE(VI_INTR_REG, 0x208);
IO_WRITE(VI_BURST_REG, 0x3e52239);
IO_WRITE(VI_V_SYNC_REG, 0x20d);
IO_WRITE(VI_H_SYNC_REG, 0xc15);
IO_WRITE(VI_LEAP_REG, 0xc150c15);
IO_WRITE(VI_H_START_REG, 0x6c02ec);
IO_WRITE(VI_V_START_REG, 0x2501ff);
IO_WRITE(VI_V_BURST_REG, 0xe0204);
IO_WRITE(VI_X_SCALE_REG, 0x200);
IO_WRITE(VI_Y_SCALE_REG, 0x400);
sig_put();
IO_WRITE(VI_CURRENT_REG, 0x0);
IO_WRITE(VI_CONTROL_REG, 0x120e);
/*
* Wait until some active lines have gone by
*/
while (IO_READ(VI_CURRENT_REG) < 0x30) ;
cnt++;
} while (sig_check());
/*
* This leaves things running, but makes the screen black
*/
IO_WRITE(VI_H_START_REG, 0x0);
__osRestoreInt(mask);
return cnt-1;
}