Search
lxdream.org :: lxdream/test/pvr.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/pvr.c
changeset 190:f7653df5e832
prev185:6755a04c447f
next213:da6b1904f67b
author nkeynes
date Wed Aug 02 04:13:15 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change Add many more TA test cases (a couple of corner cases aren't 100% correct
yet, TBA)
Add new test "testregs" to check register masks (currently just PVR registers)
view annotate diff log raw
     1 /**
     2  * $Id: pvr.c,v 1.2 2006-08-02 04:13:15 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)
    36 void ta_dump_regs( FILE *f )
    37 {
    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) );
    44 }
    47 void ta_init( struct ta_config *config )
    48 {
    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 );
    60 }
    62 int pvr_get_objbuf_size( )
    63 {
    64     return long_read( TA_OBJPOSN ) - long_read( TA_OBJSTART );
    65 }
    67 int pvr_get_plist_posn( )
    68 {
    69     unsigned int addr = long_read( TA_TILEPOSN ) << 2;
    70     return addr;
    71 }
    73 void pvr_dump_objbuf( FILE *f )
    74 {
    75     unsigned int start = long_read( TA_OBJSTART );
    76     unsigned int posn = long_read( TA_OBJPOSN );
    77     unsigned int end = long_read( TA_OBJEND );
    78     char *buf;
    79     unsigned int length;
    80     if( start < posn ) {
    81 	buf = (char *)(0xA5000000+start);
    82 	length = posn-start;
    83     } else {
    84 	buf = (char *)(0xA5000000+end);
    85 	length = start-posn;
    86     }
    88     fprintf( f, "Obj buffer: %08X - %08X - %08X\n", start, posn, end );
    89     fwrite_dump( f, buf, length );
    90 }
    92 void pvr_dump_tilebuf( FILE *f )
    93 {
    94     unsigned int start = long_read( TA_TILESTART );
    95     unsigned int posn = long_read( TA_TILEPOSN );
    96     unsigned int end = long_read( TA_TILEEND );
    97     char *buf;
    98     unsigned int length;
    99     if( start < posn ) {
   100 	buf = (char *)(0xA5000000+start);
   101 	length = posn-start;
   102     } else {
   103 	buf = (char *)(0xA5000000+end);
   104 	length = start-posn;
   105     }
   107     fprintf( f, "Tile buffer: %08X - %08X - %08X\n", start, posn, end );
   108     fwrite_dump( f, buf, length );
   109 }
   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 */
   137         0x6930, 0x00000000,
   138         0x6938, 0x00000000,
   139         0x6900, 0xffffffff,     /* Clear all pending int events */
   140         0x6908, 0xffffffff,
   141         0x6930, 0x002807ec,     /* Re-enable some events */
   142         0x6938, 0x0000000e,
   143         0x80b8, 0x0000ff07,     /* fog density */
   144         0x80b4, 0x007f7f7f,     /* fog vertex color */
   145         0x80b0, 0x007f7f7f,     /* fog table color */
   146         0x8108, 0x00000003      /* 32bit palette  */
   147 };
   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)*/
   169         0x7834, 0x00000000,
   170         0x7854, 0x00000000,
   171         0x7874, 0x00000000,
   172         0x78bc, 0x4659404f,
   173         0x8040, 0x00000000      /* border color */
   174 };
   176 static void set_regs(unsigned int *values, int cnt)
   177 {
   178   volatile unsigned char *regs = (volatile unsigned char *)(void *)0xa05f0000;
   179   unsigned int r, v;
   181   while(cnt--) {
   182     r = *values++;
   183     v = *values++;
   184     *(volatile unsigned int *)(regs+r) = v;
   185   }
   186 }
   188 int pvr_check_cable()
   189 {
   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;
   197 }
   198 void pvr_init_video(int cabletype, int mode, int res)
   199 {
   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);
   207   mode &= 3;
   208   shift = bppshifttab[mode];
   210   videobase[8/4]=0;
   211   videobase[0x40/4]=0;
   213   /* Select pixel clock and colour mode */
   214   mode = (mode<<2)|1;
   215   lines = 240;
   216   if(!(cabletype&2)) {
   218     /* VGA mode */
   220     if(res < 2)
   221       mode |= 2; /* doublescan */
   223     hvcounter = 0x020c0359;
   225     lines <<= 1;
   226     mode |= 0x800000; /* fast pixel clock */
   227   }
   228   videobase[0x44/4]=mode;
   230   /* Set video base address.  Short fields will be offset by
   231      640 pixels, regardless of horizontal resolution.       */
   232   videobase[0x50/4]=0;
   233   videobase[0x54/4]=640<<shift;
   235   /* Set screen size, modulo, and interlace flag */
   236   videoflags = 1<<8;
   237   if(res==0)
   238     words_per_line=(320/4)<<shift;
   239   else
   240     words_per_line=(640/4)<<shift;
   241   modulo = 1;
   243   if(!(cabletype&2))
   244   {
   245     if(res==0)
   246       /* VGA lores -> skip 320 pixels to keep modulo at 640 pixels */
   247       modulo += words_per_line;
   248   } else {
   249     if(res!=1)
   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;
   254     if(res==2)
   255       /* interlace mode */
   256       videoflags |= 1<<4;
   258     /* enable NTSC */
   259     videoflags |= 1<<6;
   260   }
   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 */
   270   if(!(cabletype&2))
   271     /* VGA */
   272     voffset += 36;
   273   else
   274     voffset += 18;
   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 */
   285   if(res==0)
   286     attribs=((22<<8)+1)<<8;
   287   else
   288     attribs=22<<16;
   289   videobase[0xe8/4]=attribs;
   291   /* Set up vertical blank event */
   292   vpos = 260;
   293   if(!(cabletype&2))
   294     vpos = 510;
   295   videobase[0xcc/4]=(0x21<<16)|vpos;
   297   /* Select RGB/CVBS */
   298   if(cabletype&1)
   299     mode = 3;
   300   else
   301     mode = 0;
   302   *(volatile unsigned int *)(void*)0xa0702c00 = mode << 8;
   304   return;
   305 }
   307 void pvr_init()
   308 {
   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);
   316 }
.