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