2 * $Id: pvr.c,v 1.2 2006-08-02 04:13:15 nkeynes Exp $
6 * Copyright (c) 2006 Nathan Keynes.
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.
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.
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)
36 void ta_dump_regs( FILE *f )
38 fprintf( stderr, "TA Object start[128]: %08X posn[138]: %08X end[130]: %08X\n",
39 long_read(TA_OBJSTART), long_read(TA_OBJPOSN), long_read(TA_OBJEND) );
40 fprintf( stderr, "TA OPB start[124]: %08X posn[134]: %08X end[12c]: %08X init: %08X\n",
41 long_read(TA_TILESTART), long_read(TA_TILEPOSN), long_read(TA_TILEEND),
42 long_read(TA_PLISTSTART) );
43 fprintf( stderr, "TA Tilesize: %08X config: %08X\n", long_read(TA_SIZE), long_read(TA_TILECFG) );
47 void ta_init( struct ta_config *config )
49 long_write( PVR_RESET, 1 );
50 long_write( PVR_RESET, 0 );
52 long_write( TA_SIZE, config->grid_size );
53 long_write( TA_OBJSTART, config->obj_start & 0x00FFFFFF );
54 long_write( TA_OBJEND, config->obj_end & 0x00FFFFFF );
55 long_write( TA_TILESTART, config->tile_start & 0x00FFFFFF );
56 long_write( TA_TILEEND, config->tile_end & 0x00FFFFFF );
57 long_write( TA_PLISTSTART, config->plist_start & 0x00FFFFFF );
58 long_write( TA_TILECFG, config->ta_cfg );
59 long_write( TA_INIT, 0x80000000 );
62 int pvr_get_objbuf_size( )
64 return long_read( TA_OBJPOSN ) - long_read( TA_OBJSTART );
67 int pvr_get_plist_posn( )
69 unsigned int addr = long_read( TA_TILEPOSN ) << 2;
73 void pvr_dump_objbuf( FILE *f )
75 unsigned int start = long_read( TA_OBJSTART );
76 unsigned int posn = long_read( TA_OBJPOSN );
77 unsigned int end = long_read( TA_OBJEND );
81 buf = (char *)(0xA5000000+start);
84 buf = (char *)(0xA5000000+end);
88 fprintf( f, "Obj buffer: %08X - %08X - %08X\n", start, posn, end );
89 fwrite_dump( f, buf, length );
92 void pvr_dump_tilebuf( FILE *f )
94 unsigned int start = long_read( TA_TILESTART );
95 unsigned int posn = long_read( TA_TILEPOSN );
96 unsigned int end = long_read( TA_TILEEND );
100 buf = (char *)(0xA5000000+start);
103 buf = (char *)(0xA5000000+end);
107 fprintf( f, "Tile buffer: %08X - %08X - %08X\n", start, posn, end );
108 fwrite_dump( f, buf, length );
111 /************** Stolen from TATEST *************/
113 static unsigned int three_d_params[] = {
114 0x80a8, 0x15d1c951, /* M (Unknown magic value) */
115 0x80a0, 0x00000020, /* M */
116 0x8008, 0x00000000, /* TA out of reset */
117 0x8048, 0x00000009, /* alpha config */
118 0x8068, 0x02800000, /* pixel clipping x */
119 0x806c, 0x01e00000, /* pixel clipping y */
120 0x8110, 0x00093f39, /* M */
121 0x8098, 0x00800408, /* M */
122 0x804c, 0x000000a0, /* display align (640*2)/8 */
123 0x8078, 0x3f800000, /* polygon culling (1.0f) */
124 0x8084, 0x00000000, /* M */
125 0x8030, 0x00000101, /* M */
126 0x80b0, 0x007f7f7f, /* Fog table color */
127 0x80b4, 0x007f7f7f, /* Fog vertex color */
128 0x80c0, 0x00000000, /* color clamp min */
129 0x80bc, 0xffffffff, /* color clamp max */
130 0x8080, 0x00000007, /* M */
131 0x8074, 0x00000001, /* cheap shadow */
132 0x807c, 0x0027df77, /* M */
133 0x8008, 0x00000001, /* TA reset */
134 0x8008, 0x00000000, /* TA out of reset */
135 0x80e4, 0x00000000, /* stride width */
136 0x6884, 0x00000000, /* Disable all interrupt events */
139 0x6900, 0xffffffff, /* Clear all pending int events */
141 0x6930, 0x002807ec, /* Re-enable some events */
143 0x80b8, 0x0000ff07, /* fog density */
144 0x80b4, 0x007f7f7f, /* fog vertex color */
145 0x80b0, 0x007f7f7f, /* fog table color */
146 0x8108, 0x00000003 /* 32bit palette */
149 static unsigned int scrn_params[] = {
150 0x80e8, 0x00160000, /* screen control */
151 0x8044, 0x00800000, /* pixel mode (vb+0x11) */
152 0x805c, 0x00000000, /* Size modulo and display lines (vb+0x17) */
153 0x80d0, 0x00000100, /* interlace flags */
154 0x80d8, 0x020c0359, /* M */
155 0x80cc, 0x001501fe, /* M */
156 0x80d4, 0x007e0345, /* horizontal border */
157 0x80dc, 0x00240204, /* vertical position */
158 0x80e0, 0x07d6c63f, /* sync control */
159 0x80ec, 0x000000a4, /* horizontal position */
160 0x80f0, 0x00120012, /* vertical border */
161 0x80c8, 0x03450000, /* set to same as border H in 80d4 */
162 0x8068, 0x027f0000, /* (X resolution - 1) << 16 */
163 0x806c, 0x01df0000, /* (Y resolution - 1) << 16 */
164 0x804c, 0x000000a0, /* display align */
165 0x8118, 0x00008040, /* M */
166 0x80f4, 0x00000401, /* anti-aliasing */
167 0x8048, 0x00000009, /* alpha config */
168 0x7814, 0x00000000, /* More interrupt control stuff (so it seems)*/
173 0x8040, 0x00000000 /* border color */
176 static void set_regs(unsigned int *values, int cnt)
178 volatile unsigned char *regs = (volatile unsigned char *)(void *)0xa05f0000;
184 *(volatile unsigned int *)(regs+r) = v;
188 int pvr_check_cable()
190 volatile unsigned int *porta = (unsigned int *)0xff80002c;
192 /* PORT8 and PORT9 is input */
193 *porta = (*porta & ~0xf0000) | 0xa0000;
195 /* Return PORT8 and PORT9 */
196 return ((*(volatile unsigned short *)(porta+1))>>8)&3;
198 void pvr_init_video(int cabletype, int mode, int res)
200 volatile unsigned int *videobase=(volatile unsigned int *)(void*)0xa05f8000;
201 static int bppshifttab[]= { 1,1,0,2 };
202 int shift, lines, modulo, words_per_line, vpos;
203 int laceoffset=0, voffset=0;
204 unsigned int videoflags, attribs;
205 unsigned int hvcounter = (res<2? 0x01060359 : 0x020c0359);
208 shift = bppshifttab[mode];
213 /* Select pixel clock and colour mode */
221 mode |= 2; /* doublescan */
223 hvcounter = 0x020c0359;
226 mode |= 0x800000; /* fast pixel clock */
228 videobase[0x44/4]=mode;
230 /* Set video base address. Short fields will be offset by
231 640 pixels, regardless of horizontal resolution. */
233 videobase[0x54/4]=640<<shift;
235 /* Set screen size, modulo, and interlace flag */
238 words_per_line=(320/4)<<shift;
240 words_per_line=(640/4)<<shift;
246 /* VGA lores -> skip 320 pixels to keep modulo at 640 pixels */
247 modulo += words_per_line;
250 /* NTSC lores -> skip 320 pixels to keep modulo at 640 pixels */
251 /* _or_ NTSC hires -> skip every other line due to interlace */
252 modulo += words_per_line;
262 /* Write screen size and modulo */
263 videobase[0x5c/4]=(((modulo<<10)+lines-1)<<10)+words_per_line-1;
265 /* Enable video (lace, NTSC) */
266 videobase[0xd0/4]=videoflags;
268 /* Screen and border position */
276 vpos=(voffset<<16)|(voffset+laceoffset);
278 videobase[0xf0/4]=vpos; /* V start */
279 videobase[0xdc/4]=vpos+lines; /* start and end border */
280 videobase[0xec/4]=0xa4; /* Horizontal pos */
281 videobase[0xd8/4]=hvcounter; /* HV counter */
282 videobase[0xd4/4]=0x007e0345; /* Horizontal border */
284 /* Select horizontal pixel doubling for lowres */
286 attribs=((22<<8)+1)<<8;
289 videobase[0xe8/4]=attribs;
291 /* Set up vertical blank event */
295 videobase[0xcc/4]=(0x21<<16)|vpos;
297 /* Select RGB/CVBS */
302 *(volatile unsigned int *)(void*)0xa0702c00 = mode << 8;
309 volatile unsigned int *vbl = (volatile unsigned int *)(void *)0xa05f810c;
311 set_regs(three_d_params, sizeof(three_d_params)/sizeof(three_d_params[0])/2);
312 while (!(*vbl & 0x01ff));
313 while (*vbl & 0x01ff);
314 set_regs(scrn_params, sizeof(scrn_params)/sizeof(scrn_params[0])/2);
315 pvr_init_video(pvr_check_cable(), 1, 2);
.