Search
lxdream.org :: lxdream/test/pvr.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename test/pvr.c
changeset 185:6755a04c447f
next190: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
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/test/pvr.c Tue Jul 11 01:35:27 2006 +0000
1.3 @@ -0,0 +1,319 @@
1.4 +/**
1.5 + * $Id: pvr.c,v 1.1 2006-07-11 01:35:23 nkeynes Exp $
1.6 + *
1.7 + * PVR support code
1.8 + *
1.9 + * Copyright (c) 2006 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include "lib.h"
1.23 +#include "pvr.h"
1.24 +
1.25 +#define PVR_BASE 0xA05F8000
1.26 +#define PVR_RESET (PVR_BASE+0x008)
1.27 +#define TA_INIT (PVR_BASE+0x144)
1.28 +#define TA_TILESTART (PVR_BASE+0x124)
1.29 +#define TA_OBJSTART (PVR_BASE+0x128)
1.30 +#define TA_TILEEND (PVR_BASE+0x12C)
1.31 +#define TA_OBJEND (PVR_BASE+0x130)
1.32 +#define TA_TILEPOSN (PVR_BASE+0x134)
1.33 +#define TA_OBJPOSN (PVR_BASE+0x138)
1.34 +#define TA_SIZE (PVR_BASE+0x13C)
1.35 +#define TA_TILECFG (PVR_BASE+0x140)
1.36 +#define TA_PLISTSTART (PVR_BASE+0x164)
1.37 +
1.38 +
1.39 +
1.40 +void ta_init( unsigned int hres, unsigned int vres,
1.41 + unsigned int polybuf, unsigned int polybuflen,
1.42 + unsigned int tilebuf, unsigned int tilebuflen )
1.43 +{
1.44 + unsigned int hsegs = ((hres+31) / 32)-1;
1.45 + unsigned int vsegs = ((vres+31) / 32)-1;
1.46 + unsigned int size = (vsegs<<16)|hsegs;
1.47 +
1.48 + fprintf(stderr, "Setting tilemap: %08X\n", size);
1.49 +
1.50 + long_write( PVR_RESET, 1 );
1.51 + long_write( PVR_RESET, 0 );
1.52 +
1.53 + long_write( TA_SIZE, size );
1.54 + long_write( TA_OBJSTART, polybuf & 0x00FFFFFF );
1.55 + long_write( TA_OBJEND, (polybuf + polybuflen) & 0x00FFFFFF );
1.56 + long_write( TA_TILESTART, (tilebuf + tilebuflen) & 0x00FFFFFF );
1.57 + long_write( TA_TILEEND, tilebuf & 0x00FFFFFF );
1.58 + long_write( TA_PLISTSTART, (tilebuf + tilebuflen) & 0x00FFFFFF );
1.59 + long_write( TA_TILECFG, 0x00100002 );
1.60 + long_write( TA_INIT, 0x80000000 );
1.61 +}
1.62 +
1.63 +void ta_dump_regs( FILE *f )
1.64 +{
1.65 + fprintf( stderr, "TA Object start[128]: %08X posn[138]: %08X end[130]: %08X\n",
1.66 + long_read(TA_OBJSTART), long_read(TA_OBJPOSN), long_read(TA_OBJEND) );
1.67 + fprintf( stderr, "TA OPB start[124]: %08X posn[134]: %08X end[12c]: %08X init: %08X\n",
1.68 + long_read(TA_TILESTART), long_read(TA_TILEPOSN), long_read(TA_TILEEND),
1.69 + long_read(TA_PLISTSTART) );
1.70 + fprintf( stderr, "TA Tilesize: %08X config: %08X\n", long_read(TA_SIZE), long_read(TA_TILECFG) );
1.71 +}
1.72 +
1.73 +int pvr_get_objbuf_size( )
1.74 +{
1.75 + return long_read( TA_OBJPOSN ) - long_read( TA_OBJSTART );
1.76 +}
1.77 +
1.78 +void pvr_dump_objbuf( FILE *f )
1.79 +{
1.80 + unsigned int start = long_read( TA_OBJSTART );
1.81 + unsigned int posn = long_read( TA_OBJPOSN );
1.82 + unsigned int end = long_read( TA_OBJEND );
1.83 + char *buf;
1.84 + unsigned int length;
1.85 + if( start < posn ) {
1.86 + buf = (char *)(0xA5000000+start);
1.87 + length = posn-start;
1.88 + } else {
1.89 + buf = (char *)(0xA5000000+end);
1.90 + length = start-posn;
1.91 + }
1.92 +
1.93 + fprintf( f, "Obj buffer: %08X - %08X - %08X\n", start, posn, end );
1.94 + fwrite_dump( f, buf, length );
1.95 +}
1.96 +
1.97 +void pvr_dump_tilebuf( FILE *f )
1.98 +{
1.99 + unsigned int start = long_read( TA_TILESTART );
1.100 + unsigned int posn = long_read( TA_TILEPOSN );
1.101 + unsigned int end = long_read( TA_TILEEND );
1.102 + char *buf;
1.103 + unsigned int length;
1.104 + if( start < posn ) {
1.105 + buf = (char *)(0xA5000000+start);
1.106 + length = posn-start;
1.107 + } else {
1.108 + buf = (char *)(0xA5000000+end);
1.109 + length = start-posn;
1.110 + }
1.111 +
1.112 + fprintf( f, "Tile buffer: %08X - %08X - %08X\n", start, posn, end );
1.113 + fwrite_dump( f, buf, length );
1.114 +}
1.115 +
1.116 +/************** Stolen from TATEST *************/
1.117 +
1.118 +static unsigned int three_d_params[] = {
1.119 + 0x80a8, 0x15d1c951, /* M (Unknown magic value) */
1.120 + 0x80a0, 0x00000020, /* M */
1.121 + 0x8008, 0x00000000, /* TA out of reset */
1.122 + 0x8048, 0x00000009, /* alpha config */
1.123 + 0x8068, 0x02800000, /* pixel clipping x */
1.124 + 0x806c, 0x01e00000, /* pixel clipping y */
1.125 + 0x8110, 0x00093f39, /* M */
1.126 + 0x8098, 0x00800408, /* M */
1.127 + 0x804c, 0x000000a0, /* display align (640*2)/8 */
1.128 + 0x8078, 0x3f800000, /* polygon culling (1.0f) */
1.129 + 0x8084, 0x00000000, /* M */
1.130 + 0x8030, 0x00000101, /* M */
1.131 + 0x80b0, 0x007f7f7f, /* Fog table color */
1.132 + 0x80b4, 0x007f7f7f, /* Fog vertex color */
1.133 + 0x80c0, 0x00000000, /* color clamp min */
1.134 + 0x80bc, 0xffffffff, /* color clamp max */
1.135 + 0x8080, 0x00000007, /* M */
1.136 + 0x8074, 0x00000001, /* cheap shadow */
1.137 + 0x807c, 0x0027df77, /* M */
1.138 + 0x8008, 0x00000001, /* TA reset */
1.139 + 0x8008, 0x00000000, /* TA out of reset */
1.140 + 0x80e4, 0x00000000, /* stride width */
1.141 + 0x6884, 0x00000000, /* Disable all interrupt events */
1.142 + 0x6930, 0x00000000,
1.143 + 0x6938, 0x00000000,
1.144 + 0x6900, 0xffffffff, /* Clear all pending int events */
1.145 + 0x6908, 0xffffffff,
1.146 + 0x6930, 0x002807ec, /* Re-enable some events */
1.147 + 0x6938, 0x0000000e,
1.148 + 0x80b8, 0x0000ff07, /* fog density */
1.149 + 0x80b4, 0x007f7f7f, /* fog vertex color */
1.150 + 0x80b0, 0x007f7f7f, /* fog table color */
1.151 + 0x8108, 0x00000003 /* 32bit palette */
1.152 +};
1.153 +
1.154 +static unsigned int scrn_params[] = {
1.155 + 0x80e8, 0x00160000, /* screen control */
1.156 + 0x8044, 0x00800000, /* pixel mode (vb+0x11) */
1.157 + 0x805c, 0x00000000, /* Size modulo and display lines (vb+0x17) */
1.158 + 0x80d0, 0x00000100, /* interlace flags */
1.159 + 0x80d8, 0x020c0359, /* M */
1.160 + 0x80cc, 0x001501fe, /* M */
1.161 + 0x80d4, 0x007e0345, /* horizontal border */
1.162 + 0x80dc, 0x00240204, /* vertical position */
1.163 + 0x80e0, 0x07d6c63f, /* sync control */
1.164 + 0x80ec, 0x000000a4, /* horizontal position */
1.165 + 0x80f0, 0x00120012, /* vertical border */
1.166 + 0x80c8, 0x03450000, /* set to same as border H in 80d4 */
1.167 + 0x8068, 0x027f0000, /* (X resolution - 1) << 16 */
1.168 + 0x806c, 0x01df0000, /* (Y resolution - 1) << 16 */
1.169 + 0x804c, 0x000000a0, /* display align */
1.170 + 0x8118, 0x00008040, /* M */
1.171 + 0x80f4, 0x00000401, /* anti-aliasing */
1.172 + 0x8048, 0x00000009, /* alpha config */
1.173 + 0x7814, 0x00000000, /* More interrupt control stuff (so it seems)*/
1.174 + 0x7834, 0x00000000,
1.175 + 0x7854, 0x00000000,
1.176 + 0x7874, 0x00000000,
1.177 + 0x78bc, 0x4659404f,
1.178 + 0x8040, 0x00000000 /* border color */
1.179 +};
1.180 +
1.181 +static void set_regs(unsigned int *values, int cnt)
1.182 +{
1.183 + volatile unsigned char *regs = (volatile unsigned char *)(void *)0xa05f0000;
1.184 + unsigned int r, v;
1.185 +
1.186 + while(cnt--) {
1.187 + r = *values++;
1.188 + v = *values++;
1.189 + *(volatile unsigned int *)(regs+r) = v;
1.190 + }
1.191 +}
1.192 +
1.193 +int pvr_check_cable()
1.194 +{
1.195 + volatile unsigned int *porta = (unsigned int *)0xff80002c;
1.196 +
1.197 + /* PORT8 and PORT9 is input */
1.198 + *porta = (*porta & ~0xf0000) | 0xa0000;
1.199 +
1.200 + /* Return PORT8 and PORT9 */
1.201 + return ((*(volatile unsigned short *)(porta+1))>>8)&3;
1.202 +}
1.203 +void pvr_init_video(int cabletype, int mode, int res)
1.204 +{
1.205 + volatile unsigned int *videobase=(volatile unsigned int *)(void*)0xa05f8000;
1.206 + static int bppshifttab[]= { 1,1,0,2 };
1.207 + int shift, lines, modulo, words_per_line, vpos;
1.208 + int laceoffset=0, voffset=0;
1.209 + unsigned int videoflags, attribs;
1.210 + unsigned int hvcounter = (res<2? 0x01060359 : 0x020c0359);
1.211 +
1.212 + mode &= 3;
1.213 + shift = bppshifttab[mode];
1.214 +
1.215 + videobase[8/4]=0;
1.216 + videobase[0x40/4]=0;
1.217 +
1.218 + /* Select pixel clock and colour mode */
1.219 + mode = (mode<<2)|1;
1.220 + lines = 240;
1.221 + if(!(cabletype&2)) {
1.222 +
1.223 + /* VGA mode */
1.224 +
1.225 + if(res < 2)
1.226 + mode |= 2; /* doublescan */
1.227 +
1.228 + hvcounter = 0x020c0359;
1.229 +
1.230 + lines <<= 1;
1.231 + mode |= 0x800000; /* fast pixel clock */
1.232 + }
1.233 + videobase[0x44/4]=mode;
1.234 +
1.235 + /* Set video base address. Short fields will be offset by
1.236 + 640 pixels, regardless of horizontal resolution. */
1.237 + videobase[0x50/4]=0;
1.238 + videobase[0x54/4]=640<<shift;
1.239 +
1.240 + /* Set screen size, modulo, and interlace flag */
1.241 + videoflags = 1<<8;
1.242 + if(res==0)
1.243 + words_per_line=(320/4)<<shift;
1.244 + else
1.245 + words_per_line=(640/4)<<shift;
1.246 + modulo = 1;
1.247 +
1.248 + if(!(cabletype&2))
1.249 + {
1.250 + if(res==0)
1.251 + /* VGA lores -> skip 320 pixels to keep modulo at 640 pixels */
1.252 + modulo += words_per_line;
1.253 + } else {
1.254 + if(res!=1)
1.255 + /* NTSC lores -> skip 320 pixels to keep modulo at 640 pixels */
1.256 + /* _or_ NTSC hires -> skip every other line due to interlace */
1.257 + modulo += words_per_line;
1.258 +
1.259 + if(res==2)
1.260 + /* interlace mode */
1.261 + videoflags |= 1<<4;
1.262 +
1.263 + /* enable NTSC */
1.264 + videoflags |= 1<<6;
1.265 + }
1.266 +
1.267 + /* Write screen size and modulo */
1.268 + videobase[0x5c/4]=(((modulo<<10)+lines-1)<<10)+words_per_line-1;
1.269 +
1.270 + /* Enable video (lace, NTSC) */
1.271 + videobase[0xd0/4]=videoflags;
1.272 +
1.273 + /* Screen and border position */
1.274 +
1.275 + if(!(cabletype&2))
1.276 + /* VGA */
1.277 + voffset += 36;
1.278 + else
1.279 + voffset += 18;
1.280 +
1.281 + vpos=(voffset<<16)|(voffset+laceoffset);
1.282 +
1.283 + videobase[0xf0/4]=vpos; /* V start */
1.284 + videobase[0xdc/4]=vpos+lines; /* start and end border */
1.285 + videobase[0xec/4]=0xa4; /* Horizontal pos */
1.286 + videobase[0xd8/4]=hvcounter; /* HV counter */
1.287 + videobase[0xd4/4]=0x007e0345; /* Horizontal border */
1.288 +
1.289 + /* Select horizontal pixel doubling for lowres */
1.290 + if(res==0)
1.291 + attribs=((22<<8)+1)<<8;
1.292 + else
1.293 + attribs=22<<16;
1.294 + videobase[0xe8/4]=attribs;
1.295 +
1.296 + /* Set up vertical blank event */
1.297 + vpos = 260;
1.298 + if(!(cabletype&2))
1.299 + vpos = 510;
1.300 + videobase[0xcc/4]=(0x21<<16)|vpos;
1.301 +
1.302 + /* Select RGB/CVBS */
1.303 + if(cabletype&1)
1.304 + mode = 3;
1.305 + else
1.306 + mode = 0;
1.307 + *(volatile unsigned int *)(void*)0xa0702c00 = mode << 8;
1.308 +
1.309 + return;
1.310 +}
1.311 +
1.312 +void pvr_init()
1.313 +{
1.314 + volatile unsigned int *vbl = (volatile unsigned int *)(void *)0xa05f810c;
1.315 +
1.316 + set_regs(three_d_params, sizeof(three_d_params)/sizeof(three_d_params[0])/2);
1.317 + while (!(*vbl & 0x01ff));
1.318 + while (*vbl & 0x01ff);
1.319 + set_regs(scrn_params, sizeof(scrn_params)/sizeof(scrn_params[0])/2);
1.320 + pvr_init_video(pvr_check_cable(), 1, 2);
1.321 +}
1.322 +
.