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 Sun Aug 06 06:13:51 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change First pass at implementing the tile clip. Reasonably accurate wrt basic
understanding of how its supposed to work, not so accurate wrt actual
hardware behaviour
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
.