Search
lxdream.org :: lxdream/test/testdisp.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/testdisp.c
changeset 267:e59e36950761
prev263:6f641270b2aa
next272:fb6be85235e8
author nkeynes
date Sat Jan 06 04:08:11 2007 +0000 (14 years ago)
permissions -rw-r--r--
last change Add test for NTSC timing, retrace/scanline events
view annotate diff log raw
     1 /**
     2  * $Id: testdisp.c,v 1.2 2007-01-06 04:08:11 nkeynes Exp $
     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     WAIT_LINE( t->total_lines - 1 );
   211     asic_clear();
   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 	    asic_clear();
   218 	    last_line = stat & 0x03FF;
   219 	}
   220     }
   221     if( stat != 0 ) {
   222 	fprintf( stderr, "Timeout waiting for line 0 field 0\n" );
   223 	return -1;
   224     }
   225     timer_start();
   226     asic_clear();
   227     if( asic_check( EVENT_RETRACE ) != 0 ) {
   228 	fprintf( stderr, "Failed to clear retrace event ?\n" );
   229 	return -1;
   230     }
   231     CHECK_IEQUALS( stat, 0 ); /* VSYNC, HSYNC, no display */
   232     WAIT_LINE(1);
   233     line_time = timer_gettime_us();
   234     WAIT_LASTLINE(t->total_lines-1);
   235     field_time = timer_gettime_us();
   237     if( line_time != t->line_time_us ||
   238 	field_time != t->field_time_us ) {
   239 	fprintf( stderr, "Assertion failed: Expected Timing %d,%d but was %d,%d\n",
   240 		 t->line_time_us, t->field_time_us, line_time, field_time );
   241 	return -1;
   242     }
   243     return 0;
   244 }
   246 int test_ntsc_timing() {
   247     apply_display_settings( ntsc_settings );
   248     //    check_events_interlaced();
   249     asic_clear();
   250     uint32_t result = check_timing( &ntsc_timing );
   251     dump_display_regs( stdout );
   252     return result;
   253 }
   256 int test_pal_timing() 
   257 {
   258     uint32_t line_time, field_time;
   259     /* Set PAL display mode */
   260     apply_display_settings( pal_settings );
   262     check_events_interlaced();
   263     asic_clear();
   264     uint32_t result = check_timing( &pal_timing );
   265     dump_display_regs( stdout );
   266     return result;
   267 }
   270 /********************************* Main **************************************/
   272 typedef int (*test_func_t)();
   274 test_func_t test_fns[] = { test_ntsc_timing, test_pal_timing,
   275 			   NULL };
   277 int main() 
   278 {
   279     return run_tests( test_fns );
   280 }
.