filename | test/pvr.c |
changeset | 185:6755a04c447f |
next | 190:f7653df5e832 |
author | nkeynes |
date | Tue Jul 11 01:35:27 2006 +0000 (14 years ago) |
permissions | -rw-r--r-- |
last change | First commit of system test framework. 3 initial test cases (incomplete): testide, testmath, and testta |
view | annotate | diff | log | raw |
1 /**
2 * $Id: pvr.c,v 1.1 2006-07-11 01:35:23 nkeynes Exp $
3 *
4 * PVR support code
5 *
6 * Copyright (c) 2006 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include "lib.h"
20 #include "pvr.h"
22 #define PVR_BASE 0xA05F8000
23 #define PVR_RESET (PVR_BASE+0x008)
24 #define TA_INIT (PVR_BASE+0x144)
25 #define TA_TILESTART (PVR_BASE+0x124)
26 #define TA_OBJSTART (PVR_BASE+0x128)
27 #define TA_TILEEND (PVR_BASE+0x12C)
28 #define TA_OBJEND (PVR_BASE+0x130)
29 #define TA_TILEPOSN (PVR_BASE+0x134)
30 #define TA_OBJPOSN (PVR_BASE+0x138)
31 #define TA_SIZE (PVR_BASE+0x13C)
32 #define TA_TILECFG (PVR_BASE+0x140)
33 #define TA_PLISTSTART (PVR_BASE+0x164)
37 void ta_init( unsigned int hres, unsigned int vres,
38 unsigned int polybuf, unsigned int polybuflen,
39 unsigned int tilebuf, unsigned int tilebuflen )
40 {
41 unsigned int hsegs = ((hres+31) / 32)-1;
42 unsigned int vsegs = ((vres+31) / 32)-1;
43 unsigned int size = (vsegs<<16)|hsegs;
45 fprintf(stderr, "Setting tilemap: %08X\n", size);
47 long_write( PVR_RESET, 1 );
48 long_write( PVR_RESET, 0 );
50 long_write( TA_SIZE, size );
51 long_write( TA_OBJSTART, polybuf & 0x00FFFFFF );
52 long_write( TA_OBJEND, (polybuf + polybuflen) & 0x00FFFFFF );
53 long_write( TA_TILESTART, (tilebuf + tilebuflen) & 0x00FFFFFF );
54 long_write( TA_TILEEND, tilebuf & 0x00FFFFFF );
55 long_write( TA_PLISTSTART, (tilebuf + tilebuflen) & 0x00FFFFFF );
56 long_write( TA_TILECFG, 0x00100002 );
57 long_write( TA_INIT, 0x80000000 );
58 }
60 void ta_dump_regs( FILE *f )
61 {
62 fprintf( stderr, "TA Object start[128]: %08X posn[138]: %08X end[130]: %08X\n",
63 long_read(TA_OBJSTART), long_read(TA_OBJPOSN), long_read(TA_OBJEND) );
64 fprintf( stderr, "TA OPB start[124]: %08X posn[134]: %08X end[12c]: %08X init: %08X\n",
65 long_read(TA_TILESTART), long_read(TA_TILEPOSN), long_read(TA_TILEEND),
66 long_read(TA_PLISTSTART) );
67 fprintf( stderr, "TA Tilesize: %08X config: %08X\n", long_read(TA_SIZE), long_read(TA_TILECFG) );
68 }
70 int pvr_get_objbuf_size( )
71 {
72 return long_read( TA_OBJPOSN ) - long_read( TA_OBJSTART );
73 }
75 void pvr_dump_objbuf( FILE *f )
76 {
77 unsigned int start = long_read( TA_OBJSTART );
78 unsigned int posn = long_read( TA_OBJPOSN );
79 unsigned int end = long_read( TA_OBJEND );
80 char *buf;
81 unsigned int length;
82 if( start < posn ) {
83 buf = (char *)(0xA5000000+start);
84 length = posn-start;
85 } else {
86 buf = (char *)(0xA5000000+end);
87 length = start-posn;
88 }
90 fprintf( f, "Obj buffer: %08X - %08X - %08X\n", start, posn, end );
91 fwrite_dump( f, buf, length );
92 }
94 void pvr_dump_tilebuf( FILE *f )
95 {
96 unsigned int start = long_read( TA_TILESTART );
97 unsigned int posn = long_read( TA_TILEPOSN );
98 unsigned int end = long_read( TA_TILEEND );
99 char *buf;
100 unsigned int length;
101 if( start < posn ) {
102 buf = (char *)(0xA5000000+start);
103 length = posn-start;
104 } else {
105 buf = (char *)(0xA5000000+end);
106 length = start-posn;
107 }
109 fprintf( f, "Tile buffer: %08X - %08X - %08X\n", start, posn, end );
110 fwrite_dump( f, buf, length );
111 }
113 /************** Stolen from TATEST *************/
115 static unsigned int three_d_params[] = {
116 0x80a8, 0x15d1c951, /* M (Unknown magic value) */
117 0x80a0, 0x00000020, /* M */
118 0x8008, 0x00000000, /* TA out of reset */
119 0x8048, 0x00000009, /* alpha config */
120 0x8068, 0x02800000, /* pixel clipping x */
121 0x806c, 0x01e00000, /* pixel clipping y */
122 0x8110, 0x00093f39, /* M */
123 0x8098, 0x00800408, /* M */
124 0x804c, 0x000000a0, /* display align (640*2)/8 */
125 0x8078, 0x3f800000, /* polygon culling (1.0f) */
126 0x8084, 0x00000000, /* M */
127 0x8030, 0x00000101, /* M */
128 0x80b0, 0x007f7f7f, /* Fog table color */
129 0x80b4, 0x007f7f7f, /* Fog vertex color */
130 0x80c0, 0x00000000, /* color clamp min */
131 0x80bc, 0xffffffff, /* color clamp max */
132 0x8080, 0x00000007, /* M */
133 0x8074, 0x00000001, /* cheap shadow */
134 0x807c, 0x0027df77, /* M */
135 0x8008, 0x00000001, /* TA reset */
136 0x8008, 0x00000000, /* TA out of reset */
137 0x80e4, 0x00000000, /* stride width */
138 0x6884, 0x00000000, /* Disable all interrupt events */
139 0x6930, 0x00000000,
140 0x6938, 0x00000000,
141 0x6900, 0xffffffff, /* Clear all pending int events */
142 0x6908, 0xffffffff,
143 0x6930, 0x002807ec, /* Re-enable some events */
144 0x6938, 0x0000000e,
145 0x80b8, 0x0000ff07, /* fog density */
146 0x80b4, 0x007f7f7f, /* fog vertex color */
147 0x80b0, 0x007f7f7f, /* fog table color */
148 0x8108, 0x00000003 /* 32bit palette */
149 };
151 static unsigned int scrn_params[] = {
152 0x80e8, 0x00160000, /* screen control */
153 0x8044, 0x00800000, /* pixel mode (vb+0x11) */
154 0x805c, 0x00000000, /* Size modulo and display lines (vb+0x17) */
155 0x80d0, 0x00000100, /* interlace flags */
156 0x80d8, 0x020c0359, /* M */
157 0x80cc, 0x001501fe, /* M */
158 0x80d4, 0x007e0345, /* horizontal border */
159 0x80dc, 0x00240204, /* vertical position */
160 0x80e0, 0x07d6c63f, /* sync control */
161 0x80ec, 0x000000a4, /* horizontal position */
162 0x80f0, 0x00120012, /* vertical border */
163 0x80c8, 0x03450000, /* set to same as border H in 80d4 */
164 0x8068, 0x027f0000, /* (X resolution - 1) << 16 */
165 0x806c, 0x01df0000, /* (Y resolution - 1) << 16 */
166 0x804c, 0x000000a0, /* display align */
167 0x8118, 0x00008040, /* M */
168 0x80f4, 0x00000401, /* anti-aliasing */
169 0x8048, 0x00000009, /* alpha config */
170 0x7814, 0x00000000, /* More interrupt control stuff (so it seems)*/
171 0x7834, 0x00000000,
172 0x7854, 0x00000000,
173 0x7874, 0x00000000,
174 0x78bc, 0x4659404f,
175 0x8040, 0x00000000 /* border color */
176 };
178 static void set_regs(unsigned int *values, int cnt)
179 {
180 volatile unsigned char *regs = (volatile unsigned char *)(void *)0xa05f0000;
181 unsigned int r, v;
183 while(cnt--) {
184 r = *values++;
185 v = *values++;
186 *(volatile unsigned int *)(regs+r) = v;
187 }
188 }
190 int pvr_check_cable()
191 {
192 volatile unsigned int *porta = (unsigned int *)0xff80002c;
194 /* PORT8 and PORT9 is input */
195 *porta = (*porta & ~0xf0000) | 0xa0000;
197 /* Return PORT8 and PORT9 */
198 return ((*(volatile unsigned short *)(porta+1))>>8)&3;
199 }
200 void pvr_init_video(int cabletype, int mode, int res)
201 {
202 volatile unsigned int *videobase=(volatile unsigned int *)(void*)0xa05f8000;
203 static int bppshifttab[]= { 1,1,0,2 };
204 int shift, lines, modulo, words_per_line, vpos;
205 int laceoffset=0, voffset=0;
206 unsigned int videoflags, attribs;
207 unsigned int hvcounter = (res<2? 0x01060359 : 0x020c0359);
209 mode &= 3;
210 shift = bppshifttab[mode];
212 videobase[8/4]=0;
213 videobase[0x40/4]=0;
215 /* Select pixel clock and colour mode */
216 mode = (mode<<2)|1;
217 lines = 240;
218 if(!(cabletype&2)) {
220 /* VGA mode */
222 if(res < 2)
223 mode |= 2; /* doublescan */
225 hvcounter = 0x020c0359;
227 lines <<= 1;
228 mode |= 0x800000; /* fast pixel clock */
229 }
230 videobase[0x44/4]=mode;
232 /* Set video base address. Short fields will be offset by
233 640 pixels, regardless of horizontal resolution. */
234 videobase[0x50/4]=0;
235 videobase[0x54/4]=640<<shift;
237 /* Set screen size, modulo, and interlace flag */
238 videoflags = 1<<8;
239 if(res==0)
240 words_per_line=(320/4)<<shift;
241 else
242 words_per_line=(640/4)<<shift;
243 modulo = 1;
245 if(!(cabletype&2))
246 {
247 if(res==0)
248 /* VGA lores -> skip 320 pixels to keep modulo at 640 pixels */
249 modulo += words_per_line;
250 } else {
251 if(res!=1)
252 /* NTSC lores -> skip 320 pixels to keep modulo at 640 pixels */
253 /* _or_ NTSC hires -> skip every other line due to interlace */
254 modulo += words_per_line;
256 if(res==2)
257 /* interlace mode */
258 videoflags |= 1<<4;
260 /* enable NTSC */
261 videoflags |= 1<<6;
262 }
264 /* Write screen size and modulo */
265 videobase[0x5c/4]=(((modulo<<10)+lines-1)<<10)+words_per_line-1;
267 /* Enable video (lace, NTSC) */
268 videobase[0xd0/4]=videoflags;
270 /* Screen and border position */
272 if(!(cabletype&2))
273 /* VGA */
274 voffset += 36;
275 else
276 voffset += 18;
278 vpos=(voffset<<16)|(voffset+laceoffset);
280 videobase[0xf0/4]=vpos; /* V start */
281 videobase[0xdc/4]=vpos+lines; /* start and end border */
282 videobase[0xec/4]=0xa4; /* Horizontal pos */
283 videobase[0xd8/4]=hvcounter; /* HV counter */
284 videobase[0xd4/4]=0x007e0345; /* Horizontal border */
286 /* Select horizontal pixel doubling for lowres */
287 if(res==0)
288 attribs=((22<<8)+1)<<8;
289 else
290 attribs=22<<16;
291 videobase[0xe8/4]=attribs;
293 /* Set up vertical blank event */
294 vpos = 260;
295 if(!(cabletype&2))
296 vpos = 510;
297 videobase[0xcc/4]=(0x21<<16)|vpos;
299 /* Select RGB/CVBS */
300 if(cabletype&1)
301 mode = 3;
302 else
303 mode = 0;
304 *(volatile unsigned int *)(void*)0xa0702c00 = mode << 8;
306 return;
307 }
309 void pvr_init()
310 {
311 volatile unsigned int *vbl = (volatile unsigned int *)(void *)0xa05f810c;
313 set_regs(three_d_params, sizeof(three_d_params)/sizeof(three_d_params[0])/2);
314 while (!(*vbl & 0x01ff));
315 while (*vbl & 0x01ff);
316 set_regs(scrn_params, sizeof(scrn_params)/sizeof(scrn_params[0])/2);
317 pvr_init_video(pvr_check_cable(), 1, 2);
318 }
.