Search
lxdream.org :: lxdream/test/pvr.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/pvr.c
changeset 213:da6b1904f67b
prev190:f7653df5e832
next306:818c11570593
author nkeynes
date Wed Jan 03 09:03:50 2007 +0000 (17 years ago)
permissions -rw-r--r--
last change Fix to actually work (need the write read/write sizes)
Implement the microsecond conversion function
view annotate diff log raw
     1 /**
     2  * $Id: pvr.c,v 1.3 2006-08-18 09:33:19 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_REINIT    (PVR_BASE+0x160)
    34 #define TA_PLISTSTART (PVR_BASE+0x164)
    36 #define RENDER_START    (PVR_BASE+0x014)
    37 #define RENDER_POLYBASE (PVR_BASE+0x020)
    38 #define RENDER_TILEBASE (PVR_BASE+0x02C)
    39 #define RENDER_MODE     (PVR_BASE+0x048)
    40 #define RENDER_SIZE     (PVR_BASE+0x04C)
    41 #define RENDER_ADDR1    (PVR_BASE+0x060)
    42 #define RENDER_ADDR2    (PVR_BASE+0x064)
    43 #define RENDER_HCLIP    (PVR_BASE+0x068)
    44 #define RENDER_VCLIP    (PVR_BASE+0x06C)
    45 #define RENDER_NEARCLIP (PVR_BASE+0x078)
    46 #define RENDER_FARCLIP  (PVR_BASE+0x088)
    47 #define RENDER_BGPLANE  (PVR_BASE+0x08C)
    49 #define DISPLAY_MODE    (PVR_BASE+0x044)
    50 #define DISPLAY_ADDR1   (PVR_BASE+0x050)
    51 #define DISPLAY_ADDR2   (PVR_BASE+0x054)
    52 #define DISPLAY_SIZE    (PVR_BASE+0x05C
    54 void ta_dump_regs( FILE *f )
    55 {
    56     fprintf( stderr, "TA Object start[128]: %08X posn[138]: %08X end[130]: %08X\n",
    57 	     long_read(TA_OBJSTART), long_read(TA_OBJPOSN), long_read(TA_OBJEND) );
    58     fprintf( stderr, "TA OPB start[124]: %08X posn[134]: %08X end[12c]: %08X init: %08X\n",
    59 	     long_read(TA_TILESTART), long_read(TA_TILEPOSN), long_read(TA_TILEEND),
    60 	     long_read(TA_PLISTSTART) );
    61     fprintf( stderr, "TA Tilesize: %08X  config: %08X\n",  long_read(TA_SIZE), long_read(TA_TILECFG) );
    62 }
    65 void ta_init( struct ta_config *config )
    66 {
    67     long_write( PVR_RESET, 1 );
    68     long_write( PVR_RESET, 0 );
    70     long_write( TA_SIZE, config->grid_size );
    71     long_write( TA_OBJSTART, config->obj_start & 0x00FFFFFF );
    72     long_write( TA_OBJEND, config->obj_end & 0x00FFFFFF );
    73     long_write( TA_TILESTART, config->tile_start & 0x00FFFFFF );
    74     long_write( TA_TILEEND, config->tile_end & 0x00FFFFFF );
    75     long_write( TA_PLISTSTART, config->plist_start & 0x00FFFFFF );
    76     long_write( TA_TILECFG, config->ta_cfg );
    77     long_write( TA_INIT, 0x80000000 );
    78 }
    80 void ta_reinit( )
    81 {
    82     long_write( TA_REINIT, 0x80000000 );
    83 }
    85 int pvr_get_objbuf_size( )
    86 {
    87     return long_read( TA_OBJPOSN ) - long_read( TA_OBJSTART );
    88 }
    90 int pvr_get_objbuf_posn( )
    91 {
    92     return long_read( TA_OBJPOSN );
    93 }
    95 int pvr_get_plist_posn( )
    96 {
    97     unsigned int addr = long_read( TA_TILEPOSN ) << 2;
    98     return addr;
    99 }
   101 void pvr_dump_objbuf( FILE *f )
   102 {
   103     unsigned int start = long_read( TA_OBJSTART );
   104     unsigned int posn = long_read( TA_OBJPOSN );
   105     unsigned int end = long_read( TA_OBJEND );
   106     char *buf;
   107     unsigned int length;
   108     if( start < posn ) {
   109 	buf = (char *)(0xA5000000+start);
   110 	length = posn-start;
   111     } else {
   112 	buf = (char *)(0xA5000000+end);
   113 	length = start-posn;
   114     }
   116     fprintf( f, "Obj buffer: %08X - %08X - %08X\n", start, posn, end );
   117     fwrite_dump( f, buf, length );
   118 }
   120 void pvr_dump_tilebuf( FILE *f )
   121 {
   122     unsigned int start = long_read( TA_TILESTART );
   123     unsigned int posn = long_read( TA_TILEPOSN );
   124     unsigned int end = long_read( TA_TILEEND );
   125     char *buf;
   126     unsigned int length;
   127     if( start < posn ) {
   128 	buf = (char *)(0xA5000000+start);
   129 	length = posn-start;
   130     } else {
   131 	buf = (char *)(0xA5000000+end);
   132 	length = start-posn;
   133     }
   135     fprintf( f, "Tile buffer: %08X - %08X - %08X\n", start, posn, end );
   136     fwrite_dump( f, buf, length );
   137 }
   139 static int ta_tile_sizes[4] = { 0, 32, 64, 128 };
   140 #define TILE_SIZE(cfg, tile) ta_tile_sizes[((((cfg->ta_cfg) >> (4*tile))&0x03))]
   141 #define TILE_ENABLED(cfg, tile) ((((cfg->ta_cfg) >> (4*tile))&0x03) != 0)
   142 void pvr_compute_tilematrix_addr( int *tile_ptrs, struct ta_config *config ) {
   143     int tile_sizes[5], i;
   144     int hsegs = (config->grid_size & 0xFFFF)+1;
   145     int vsegs = (config->grid_size >> 16) + 1;
   146     for( i=0; i<5; i++ ) {
   147 	tile_sizes[i] = TILE_SIZE(config,i);
   148     }
   149     tile_ptrs[0] = config->tile_start;
   150     tile_ptrs[1] = tile_ptrs[0] + (hsegs*vsegs*tile_sizes[0]);
   151     tile_ptrs[2] = tile_ptrs[1] + (hsegs*vsegs*tile_sizes[1]);
   152     tile_ptrs[3] = tile_ptrs[2] + (hsegs*vsegs*tile_sizes[2]);
   153     tile_ptrs[4] = tile_ptrs[3] + (hsegs*vsegs*tile_sizes[3]);
   154 }
   156 static uint32_t *pvr_compute_tile_ptrs( uint32_t *target, struct ta_config *config, int x, int y )
   157 {
   158     int i;
   159     int cfg = config->ta_cfg;
   160     int hsegs = (config->grid_size & 0xFFFF)+1;
   161     int vsegs = (config->grid_size >> 16) + 1;
   162     int tilematrix = config->tile_start;
   163     for( i=0; i<5; i++ ) {
   164 	if( cfg & 0x03 ) {
   165 	    int tile_size = ta_tile_sizes[cfg&0x03];
   166 	    *target++ = tilematrix + (((y*hsegs)+x)*tile_size);
   167 	    tilematrix += hsegs*vsegs*tile_size;
   168 	} else {
   169 	    *target++ = 0x80000000;
   170 	}
   171 	cfg = cfg >> 4;
   172     }
   173     return target;
   174 }
   176 void pvr_build_tilemap1( uint32_t addr, struct ta_config *config, uint32_t control_word )
   177 {
   178     uint32_t *dest = (uint32_t *)(PVR_VRAM_BASE+addr);
   179     int w = (config->grid_size & 0x0000FFFF) + 1;
   180     int h = (config->grid_size >> 16) + 1;
   182     int x,y;
   183     memset( (char *)(dest-18), 0, 18*4 );
   184     *dest++ = 0x10000000;
   185     *dest++ = 0x80000000;
   186     *dest++ = 0x80000000;
   187     *dest++ = 0x80000000;
   188     *dest++ = 0x80000000;
   189     *dest++ = 0x80000000;
   190     for( x=0; x<w; x++ ) {
   191 	for( y=0; y<h; y++ ) {
   192 	    *dest++ = control_word | (y << 8) | (x << 2);
   193 	    dest = pvr_compute_tile_ptrs(dest, config, x, y);
   194 	}
   195     }
   196     dest[-6] |= 0x80000000; /* End-of-render */ 
   197 }
   199 void pvr_build_tilemap2( uint32_t addr, struct ta_config *config, uint32_t control_word )
   200 {
   201     uint32_t *dest = (uint32_t *)(PVR_VRAM_BASE+addr);
   202     int w = (config->grid_size & 0x0000FFFF) + 1;
   203     int h = (config->grid_size >> 16) + 1;
   205     int x,y;
   206     *dest++ = 0x10000000;
   207     *dest++ = 0x80000000;
   208     *dest++ = 0x80000000;
   209     *dest++ = 0x80000000;
   210     *dest++ = 0x80000000;
   211     *dest++ = 0x80000000;
   212     for( x=0; x<w; x++ ) {
   213 	for( y=0; y<h; y++ ) {
   214 	    *dest++ = 0x40000000;
   215 	    *dest++ = 0x80000000;
   216 	    *dest++ = 0x80000000;
   217 	    *dest++ = 0x80000000;
   218 	    *dest++ = 0x80000000;
   219 	    *dest++ = 0x80000000;
   220 	    *dest++ = control_word | (y << 8) | (x << 2);
   221 	    dest = pvr_compute_tile_ptrs(dest, config, x, y);
   222 	}
   223     }
   224     dest[-6] |= 0x80000000; /* End-of-render */ 
   225 }
   227 void render_set_backplane( uint32_t mode )
   228 {
   229     long_write( RENDER_BGPLANE, mode );
   230 }
   232 int get_line_size( struct render_config *config )
   233 {
   234     int modulo = config->width;
   235     switch( config->mode & 0x07 ) {
   236     case 4:
   237 	modulo *= 3; /* ??? */
   238 	break;
   239     case 5:
   240     case 6:
   241 	modulo *= 4;
   242 	break;
   243     default:
   244 	modulo *= 2;
   245     } 
   246     return modulo;
   247 }
   249 void render_start( struct render_config *config )
   250 {
   251     int modulo = get_line_size( config );
   252     long_write( RENDER_POLYBASE, config->polybuf );
   253     long_write( RENDER_TILEBASE, config->tilemap );
   254     long_write( RENDER_ADDR1, config->render_addr );
   255     long_write( RENDER_SIZE, modulo >> 3 ); 
   256     long_write( RENDER_ADDR2, config->render_addr + modulo ); /* Not used? */
   257     long_write( RENDER_HCLIP, (config->width - 1) << 16 );
   258     long_write( RENDER_VCLIP, (config->height - 1) << 16 );
   259     long_write( RENDER_MODE, config->mode );
   260     float_write( RENDER_FARCLIP, config->farclip );
   261     float_write( RENDER_NEARCLIP, config->nearclip );
   262     long_write( RENDER_START, 0xFFFFFFFF );
   263 }
   265 void display_render( struct render_config *config )
   266 {
   267     long_write( DISPLAY_ADDR1, config->render_addr );
   268     long_write( DISPLAY_ADDR2, config->render_addr + get_line_size(config) );
   269 }
   271 /************** Stolen from TATEST *************/
   273 static unsigned int three_d_params[] = {
   274         0x80a8, 0x15d1c951,     /* M (Unknown magic value) */
   275         0x80a0, 0x00000020,     /* M */
   276         0x8008, 0x00000000,     /* TA out of reset */
   277         0x8048, 0x00000009,     /* alpha config */
   278         0x8068, 0x02800000,     /* pixel clipping x */
   279         0x806c, 0x01e00000,     /* pixel clipping y */
   280         0x8110, 0x00093f39,     /* M */
   281         0x8098, 0x00800408,     /* M */
   282         0x804c, 0x000000a0,     /* display align (640*2)/8 */
   283         0x8078, 0x3f800000,     /* polygon culling (1.0f) */
   284         0x8084, 0x00000000,     /* M */
   285         0x8030, 0x00000101,     /* M */
   286         0x80b0, 0x007f7f7f,     /* Fog table color */
   287         0x80b4, 0x007f7f7f,     /* Fog vertex color */
   288         0x80c0, 0x00000000,     /* color clamp min */
   289         0x80bc, 0xffffffff,     /* color clamp max */
   290         0x8080, 0x00000007,     /* M */
   291         0x8074, 0x00000001,     /* cheap shadow */
   292         0x807c, 0x0027df77,     /* M */
   293         0x8008, 0x00000001,     /* TA reset */
   294         0x8008, 0x00000000,     /* TA out of reset */
   295         0x80e4, 0x00000000,     /* stride width */
   296         0x6884, 0x00000000,     /* Disable all interrupt events */
   297         0x6930, 0x00000000,
   298         0x6938, 0x00000000,
   299         0x6900, 0xffffffff,     /* Clear all pending int events */
   300         0x6908, 0xffffffff,
   301         0x6930, 0x002807ec,     /* Re-enable some events */
   302         0x6938, 0x0000000e,
   303         0x80b8, 0x0000ff07,     /* fog density */
   304         0x80b4, 0x007f7f7f,     /* fog vertex color */
   305         0x80b0, 0x007f7f7f,     /* fog table color */
   306         0x8108, 0x00000003      /* 32bit palette  */
   307 };
   309 static unsigned int scrn_params[] = {
   310         0x80e8, 0x00160000,     /* screen control */
   311         0x8044, 0x00800000,     /* pixel mode (vb+0x11) */
   312         0x805c, 0x00000000,     /* Size modulo and display lines (vb+0x17) */
   313         0x80d0, 0x00000100,     /* interlace flags */
   314         0x80d8, 0x020c0359,     /* M */
   315         0x80cc, 0x001501fe,     /* M */
   316         0x80d4, 0x007e0345,     /* horizontal border */
   317         0x80dc, 0x00240204,     /* vertical position */
   318         0x80e0, 0x07d6c63f,     /* sync control */
   319         0x80ec, 0x000000a4,     /* horizontal position */
   320         0x80f0, 0x00120012,     /* vertical border */
   321         0x80c8, 0x03450000,     /* set to same as border H in 80d4 */
   322         0x8068, 0x027f0000,     /* (X resolution - 1) << 16 */
   323         0x806c, 0x01df0000,     /* (Y resolution - 1) << 16 */
   324         0x804c, 0x000000a0,     /* display align */
   325         0x8118, 0x00008040,     /* M */
   326         0x80f4, 0x00000401,     /* anti-aliasing */
   327         0x8048, 0x00000009,     /* alpha config */
   328         0x7814, 0x00000000,     /* More interrupt control stuff (so it seems)*/
   329         0x7834, 0x00000000,
   330         0x7854, 0x00000000,
   331         0x7874, 0x00000000,
   332         0x78bc, 0x4659404f,
   333         0x8040, 0x00000000      /* border color */
   334 };
   336 static void set_regs(unsigned int *values, int cnt)
   337 {
   338   volatile unsigned char *regs = (volatile unsigned char *)(void *)0xa05f0000;
   339   unsigned int r, v;
   341   while(cnt--) {
   342     r = *values++;
   343     v = *values++;
   344     *(volatile unsigned int *)(regs+r) = v;
   345   }
   346 }
   348 int pvr_check_cable()
   349 {
   350   volatile unsigned int *porta = (unsigned int *)0xff80002c;
   352   /* PORT8 and PORT9 is input */
   353   *porta = (*porta & ~0xf0000) | 0xa0000;
   355   /* Return PORT8 and PORT9 */
   356   return ((*(volatile unsigned short *)(porta+1))>>8)&3;
   357 }
   358 void pvr_init_video(int cabletype, int mode, int res)
   359 {
   360   volatile unsigned int *videobase=(volatile unsigned int *)(void*)0xa05f8000;
   361   static int bppshifttab[]= { 1,1,0,2 };
   362   int shift, lines, modulo, words_per_line, vpos;
   363   int laceoffset=0, voffset=0;
   364   unsigned int videoflags, attribs;
   365   unsigned int hvcounter = (res<2? 0x01060359 : 0x020c0359);
   367   mode &= 3;
   368   shift = bppshifttab[mode];
   370   videobase[8/4]=0;
   371   videobase[0x40/4]=0;
   373   /* Select pixel clock and colour mode */
   374   mode = (mode<<2)|1;
   375   lines = 240;
   376   if(!(cabletype&2)) {
   378     /* VGA mode */
   380     if(res < 2)
   381       mode |= 2; /* doublescan */
   383     hvcounter = 0x020c0359;
   385     lines <<= 1;
   386     mode |= 0x800000; /* fast pixel clock */
   387   }
   388   videobase[0x44/4]=mode;
   390   /* Set video base address.  Short fields will be offset by
   391      640 pixels, regardless of horizontal resolution.       */
   392   videobase[0x50/4]=0;
   393   videobase[0x54/4]=640<<shift;
   395   /* Set screen size, modulo, and interlace flag */
   396   videoflags = 1<<8;
   397   if(res==0)
   398     words_per_line=(320/4)<<shift;
   399   else
   400     words_per_line=(640/4)<<shift;
   401   modulo = 1;
   403   if(!(cabletype&2))
   404   {
   405     if(res==0)
   406       /* VGA lores -> skip 320 pixels to keep modulo at 640 pixels */
   407       modulo += words_per_line;
   408   } else {
   409     if(res!=1)
   410       /* NTSC lores -> skip 320 pixels to keep modulo at 640 pixels */
   411       /* _or_ NTSC hires -> skip every other line due to interlace  */
   412       modulo += words_per_line;
   414     if(res==2)
   415       /* interlace mode */
   416       videoflags |= 1<<4;
   418     /* enable NTSC */
   419     videoflags |= 1<<6;
   420   }
   422   /* Write screen size and modulo */
   423   videobase[0x5c/4]=(((modulo<<10)+lines-1)<<10)+words_per_line-1;
   425   /* Enable video (lace, NTSC) */
   426   videobase[0xd0/4]=videoflags;
   428   /* Screen and border position */
   430   if(!(cabletype&2))
   431     /* VGA */
   432     voffset += 36;
   433   else
   434     voffset += 18;
   436   vpos=(voffset<<16)|(voffset+laceoffset);
   438   videobase[0xf0/4]=vpos;       /* V start              */
   439   videobase[0xdc/4]=vpos+lines; /* start and end border */
   440   videobase[0xec/4]=0xa4;       /* Horizontal pos       */
   441   videobase[0xd8/4]=hvcounter;  /* HV counter           */
   442   videobase[0xd4/4]=0x007e0345; /* Horizontal border    */
   444   /* Select horizontal pixel doubling for lowres */
   445   if(res==0)
   446     attribs=((22<<8)+1)<<8;
   447   else
   448     attribs=22<<16;
   449   videobase[0xe8/4]=attribs;
   451   /* Set up vertical blank event */
   452   vpos = 260;
   453   if(!(cabletype&2))
   454     vpos = 510;
   455   videobase[0xcc/4]=(0x21<<16)|vpos;
   457   /* Select RGB/CVBS */
   458   if(cabletype&1)
   459     mode = 3;
   460   else
   461     mode = 0;
   462   *(volatile unsigned int *)(void*)0xa0702c00 = mode << 8;
   464   return;
   465 }
   467 void pvr_init()
   468 {
   469   volatile unsigned int *vbl = (volatile unsigned int *)(void *)0xa05f810c;
   471   set_regs(three_d_params, sizeof(three_d_params)/sizeof(three_d_params[0])/2);
   472   while (!(*vbl & 0x01ff));
   473   while (*vbl & 0x01ff);
   474   set_regs(scrn_params, sizeof(scrn_params)/sizeof(scrn_params[0])/2);
   475   pvr_init_video(pvr_check_cable(), 1, 2);
   476 }
.