Search
lxdream.org :: lxdream/test/testdisp.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/testdisp.c
changeset 561:533f6b478071
prev272:fb6be85235e8
author nkeynes
date Thu Jul 24 07:27:48 2008 +0000 (11 years ago)
permissions -rw-r--r--
last change Halt emulation after reporting an error
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Display (2D) tests. Mainly tests video timing / sync (obviously
     5  * it can't actually test display output since there's no way of
     6  * reading the results)
     7  *
     8  * These tests use TMU2 to determine absolute time
     9  * Copyright (c) 2006 Nathan Keynes.
    10  *
    11  * This program is free software; you can redistribute it and/or modify
    12  * it under the terms of the GNU General Public License as published by
    13  * the Free Software Foundation; either version 2 of the License, or
    14  * (at your option) any later version.
    15  *
    16  * This program is distributed in the hope that it will be useful,
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19  * GNU General Public License for more details.
    20  */
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include "lib.h"
    24 #include "asic.h"
    26 #define PVR_BASE 0xA05F8000
    28 #define BORDERCOL   (PVR_BASE+0x040)
    29 #define DISPCFG1 (PVR_BASE+0x044)
    30 #define DISPADDR1 (PVR_BASE+0x050)
    31 #define DISPADDR2 (PVR_BASE+0x054)
    32 #define DISPSIZE (PVR_BASE+0x05C)
    33 #define HPOSEVENT (PVR_BASE+0x0C8)
    34 #define VPOSEVENT (PVR_BASE+0x0CC)
    35 #define DISPCFG2 (PVR_BASE+0x0D0)
    36 #define HBORDER (PVR_BASE+0x0D4)
    37 #define DISPTOTAL (PVR_BASE+0x0D8)
    38 #define VBORDER (PVR_BASE+0x0DC)
    39 #define SYNCTIME (PVR_BASE+0x0E0)
    40 #define DISPCFG3 (PVR_BASE+0x0E8)
    41 #define HPOS     (PVR_BASE+0x0EC)
    42 #define VPOS     (PVR_BASE+0x0F0)
    43 #define SYNCSTAT (PVR_BASE+0x10C)
    45 #define MAX_FRAME_WAIT 0x50000
    47 #define EVENT_RETRACE 5
    49 #define WAIT_LINE( a ) if( wait_line(a) != 0 ) { fprintf(stderr, "Timeout at %s:%d:%s() waiting for line %d\n", __FILE__, __LINE__, __func__, a ); return -1; }
    50 #define WAIT_LASTLINE( a ) if( wait_lastline(a) != 0 ) { fprintf(stderr, "Last line check failed at %s:%d:%s() waiting for line %d\n", __FILE__, __LINE__, __func__, a ); return -1; }
    52 void dump_display_regs( FILE *out )
    53 {
    54     fprintf( out, "%08X DISPCFG1:  %08X\n", DISPCFG1, long_read(DISPCFG1) );
    55     fprintf( out, "%08X DISPCFG2:  %08X\n", DISPCFG2, long_read(DISPCFG2) );
    56     fprintf( out, "%08X DISPCFG3:  %08X\n", DISPCFG3, long_read(DISPCFG3) );
    57     fprintf( out, "%08X DISPSIZE:  %08X\n", DISPSIZE, long_read(DISPSIZE) );
    58     fprintf( out, "%08X HBORDER:   %08X\n", HBORDER, long_read(HBORDER) );
    59     fprintf( out, "%08X VBORDER:   %08X\n", VBORDER, long_read(VBORDER) );
    60     fprintf( out, "%08X SYNCTIME:  %08X\n", SYNCTIME, long_read(SYNCTIME) );
    61     fprintf( out, "%08X DISPTOTAL: %08X\n", DISPTOTAL, long_read(DISPTOTAL) );
    62     fprintf( out, "%08X DISPADDR1: %08X\n", DISPADDR1, long_read(DISPADDR1) );
    63     fprintf( out, "%08X DISPADDR2: %08X\n", DISPADDR2, long_read(DISPADDR2) );
    64     fprintf( out, "%08X HPOSEVENT: %08X\n", HPOSEVENT, long_read(HPOSEVENT) );
    65     fprintf( out, "%08X VPOSEVENT: %08X\n", VPOSEVENT, long_read(VPOSEVENT) );
    66     fprintf( out, "%08X HPOS:      %08X\n", HPOS, long_read(HPOS) );
    67     fprintf( out, "%08X VPOS:      %08X\n", VPOS, long_read(VPOS) );
    68     fprintf( out, "%08X SYNCSTAT:  %08X\n", SYNCSTAT, long_read(SYNCSTAT) );
    69 }
    71 uint32_t pal_settings[] = {
    72     DISPCFG1, 0x00000001,
    73     DISPCFG2, 0x00000150,
    74     DISPCFG3, 0x00160000,
    75     DISPSIZE, 0x1413BD3F,
    76     HBORDER, 0x008D034B,
    77     VBORDER, 0x00120102,
    78     DISPTOTAL, 0x0270035F,
    79     SYNCTIME, 0x07D6A53F,
    80     HPOS, 0x000000A4,
    81     VPOS, 0x00120012,
    82     VPOSEVENT, 0x00150136,
    83     0, 0 };
    85 uint32_t ntsc_settings[] = {
    86     DISPCFG1, 0x00000001,
    87     DISPCFG2, 0x00000150,
    88     DISPCFG3, 0x00160000,
    89     DISPSIZE, 0x1413BD3F,
    90     HBORDER, 0x007e0345,
    91     VBORDER, 0x00120102,
    92     DISPTOTAL, 0x020C0359,
    93     SYNCTIME, 0x07d6c63f,
    94     HPOS, 0x000000A4,
    95     VPOS, 0x00120012,
    96     VPOSEVENT, 0x001501FE,
    97     0, 0 };
   100 struct timing {
   101     uint32_t interlaced;
   102     uint32_t total_lines;
   103     uint32_t vsync_lines;
   104     uint32_t line_time_us;
   105     uint32_t field_time_us;
   106     uint32_t hsync_width_us;
   107     uint32_t front_porch_us;
   108     uint32_t back_porch_us;
   109 };
   111 struct timing ntsc_timing = { 1, 525, 6, 31, 16641, 4, 12, 4 };
   112 struct timing pal_timing = { 1, 625, 5, 31, 19949, 4, 12, 4 };
   114 void apply_display_settings( uint32_t *regs ) {
   115     int i;
   116     for( i=0; regs[i] != 0; i+=2 ) {
   117 	long_write( regs[i], regs[i+1] );
   118     }
   119 }
   121 /**
   122  * Wait until the given line is being displayed (ie is set in the syncstat
   123  * register).
   124  * @return 0 if the line is reached before timeout, otherwise -1.
   125  */
   126 int wait_line( int line )
   127 {
   128     int i;
   129     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   130 	uint32_t sync = long_read(SYNCSTAT) & 0x03FF;
   131 	if( sync == line ) {
   132 	    return 0;
   133 	}
   134     }
   135     return -1;
   136 }
   138 /**
   139  * Wait until just after the last line of the frame is being displayed (according
   140  * to the syncstat register). After this function the current line will be 0.
   141  * @return 0 if the last line is the given line, otherwise -1.
   142  */
   143 int wait_lastline( int line )
   144 {
   145     int lastline = 0, i;
   146     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   147 	uint32_t sync = long_read(SYNCSTAT) & 0x03FF;
   148 	if( sync == 0 && lastline != 0 ) {
   149 	    CHECK_IEQUALS( line, lastline );
   150 	    return 0;
   151 	}
   152 	lastline = sync;
   153     }
   154     fprintf( stderr, "Timeout waiting for line %d\n", line );
   155     return -1;
   156 }
   158 int check_events_interlaced( ) 
   159 {
   160     uint32_t status1, status2, status3;
   161     int i;
   162     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   163 	status1 = long_read(SYNCSTAT) & 0x07FF;
   164 	if( status1 == 0x04FF ) {
   165 	    break;
   166 	}
   167     }    
   168     asic_clear();
   169     asic_wait(EVENT_RETRACE);
   170     status1 = long_read(SYNCSTAT);
   171     asic_clear();
   172     asic_wait(EVENT_SCANLINE2);
   173     status2 = long_read(SYNCSTAT);
   174     asic_clear();
   175     asic_wait(EVENT_SCANLINE1);
   176     status3 = long_read(SYNCSTAT);
   177     CHECK_IEQUALS( 0x0000, status1 );
   178     CHECK_IEQUALS( 0x202A, status2 );
   179     CHECK_IEQUALS( 0x226C, status3 );
   181     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   182 	status1 = long_read(SYNCSTAT) & 0x07FF;
   183 	if( status1 == 0x00FF ) {
   184 	    break;
   185 	}
   186     }    
   187     asic_clear();
   188     asic_wait(EVENT_RETRACE);
   189     status1 = long_read(SYNCSTAT);
   190     asic_clear();
   191     asic_wait(EVENT_SCANLINE2);
   192     status2 = long_read(SYNCSTAT);
   193     asic_clear();
   194     asic_wait(EVENT_SCANLINE1);
   195     status3 = long_read(SYNCSTAT);
   196     fprintf( stderr, "%08X, %08X, %08X\n", status1, status2, status3 );
   197     CHECK_IEQUALS( 0x1400, status1 );
   198     CHECK_IEQUALS( 0x242B, status2 );
   199     CHECK_IEQUALS( 0x266D, status3 );
   201     return 0;
   202 }
   204 int check_timing( struct timing *t ) {
   205     uint32_t line_time, field_time;
   206     uint32_t stat;
   207     uint32_t last_line = t->total_lines - 1;
   208     int i;
   210     timer_init();
   211     WAIT_LINE( t->total_lines - 1 );
   212     for( i=0; i< MAX_FRAME_WAIT; i++ ) {
   213 	stat = long_read(SYNCSTAT) & 0x07FF;
   214 	if( stat == 0 ) {
   215 	    break;
   216 	} else if( (stat & 0x03FF) != last_line ) {
   217 	    last_line = stat & 0x03FF;
   218 	}
   219     }
   220     if( stat != 0 ) {
   221 	fprintf( stderr, "Timeout waiting for line 0 field 0\n" );
   222 	return -1;
   223     }
   224     timer_run();
   225     CHECK_IEQUALS( stat, 0 ); /* VSYNC, HSYNC, no display */
   227     uint32_t start_of_line = 0;
   228     uint32_t laststat = stat;
   229     uint32_t lastline = 0;
   230     int hsync_count = 0;
   231     while(1) { /* for each line */
   232 	stat = long_read(SYNCSTAT);
   233 	if( stat != laststat ) {
   234 	    uint32_t cur_time = timer_gettime_us();
   235 	    uint32_t time = cur_time - start_of_line;
   236 	    uint32_t line = stat & 0x03FF;
   237 	    if( line != lastline ) {
   238 		if( time != t->line_time_us && /* Allow variance of +1 us */
   239 		    time-1 != t->line_time_us ) {
   240 		    fprintf( stderr, "Assertion failed: Expected line time %dus on line %d but was %dus: %d, %d, %d\n",
   241 			     t->line_time_us, lastline, time, start_of_line, cur_time, line );
   242 		    return -1;
   243 		}
   244 		if( line == 0 ) {
   245 		    CHECK_IEQUALS( t->total_lines-1, lastline );
   246 		    break;
   247 		}
   248 		start_of_line = cur_time;
   249 		lastline = line;
   250 	    } else if( (stat ^ laststat) == 0x1000 && (stat&0x1000) ) {
   251 		hsync_count++;
   252 		if( time != t->hsync_width_us &&
   253 		    time-1 != t->hsync_width_us ) {
   254 		    fprintf( stderr, "Assertion failed: Expected hsync width %dus on line %d but was %dus, stat = %08X, count=%d\n", 
   255 			     t->hsync_width_us, lastline, time, stat, hsync_count );
   256 		    return -1;
   257 		}
   258 	    } else {
   259 		//		fprintf( stderr, "Change %08X to %08X\n", laststat, stat );
   260 	    }
   261 	    laststat = stat;
   262 	}
   263     }
   265     field_time = timer_gettime_us();
   267     if( field_time != t->field_time_us ) {
   268 	fprintf( stderr, "Assertion failed: Expected field time %dus but was %dus\n",
   269 		 t->field_time_us, field_time );
   270 	return -1;
   271     }
   272     return 0;
   273 }
   275 int test_ntsc_timing() {
   276     apply_display_settings( ntsc_settings );
   277     //    check_events_interlaced();
   278     asic_clear();
   279     uint32_t result = check_timing( &ntsc_timing );
   280     dump_display_regs( stdout );
   281     return result;
   282 }
   285 int test_pal_timing() 
   286 {
   287     uint32_t line_time, field_time;
   288     /* Set PAL display mode */
   289     apply_display_settings( pal_settings );
   291     check_events_interlaced();
   292     asic_clear();
   293     uint32_t result = check_timing( &pal_timing );
   294     dump_display_regs( stdout );
   295     return result;
   296 }
   299 /********************************* Main **************************************/
   301 typedef int (*test_func_t)();
   303 test_func_t test_fns[] = { test_ntsc_timing, test_pal_timing,
   304 			   NULL };
   306 int main() 
   307 {
   308     return run_tests( test_fns );
   309 }
.