nkeynes@263: /** nkeynes@263: * $Id: testdisp.c,v 1.1 2007-01-03 09:05:13 nkeynes Exp $ nkeynes@263: * nkeynes@263: * Display (2D) tests. Mainly tests video timing / sync (obviously nkeynes@263: * it can't actually test display output since there's no way of nkeynes@263: * reading the results) nkeynes@263: * nkeynes@263: * These tests use TMU2 to determine absolute time nkeynes@263: * Copyright (c) 2006 Nathan Keynes. nkeynes@263: * nkeynes@263: * This program is free software; you can redistribute it and/or modify nkeynes@263: * it under the terms of the GNU General Public License as published by nkeynes@263: * the Free Software Foundation; either version 2 of the License, or nkeynes@263: * (at your option) any later version. nkeynes@263: * nkeynes@263: * This program is distributed in the hope that it will be useful, nkeynes@263: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@263: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@263: * GNU General Public License for more details. nkeynes@263: */ nkeynes@263: #include nkeynes@263: #include nkeynes@263: #include "lib.h" nkeynes@263: #include "asic.h" nkeynes@263: nkeynes@263: #define PVR_BASE 0xA05F8000 nkeynes@263: nkeynes@263: #define BORDERCOL (PVR_BASE+0x040) nkeynes@263: #define DISPCFG1 (PVR_BASE+0x044) nkeynes@263: #define DISPADDR1 (PVR_BASE+0x050) nkeynes@263: #define DISPADDR2 (PVR_BASE+0x054) nkeynes@263: #define DISPSIZE (PVR_BASE+0x05C) nkeynes@263: #define HPOSEVENT (PVR_BASE+0x0C8) nkeynes@263: #define VPOSEVENT (PVR_BASE+0x0CC) nkeynes@263: #define DISPCFG2 (PVR_BASE+0x0D0) nkeynes@263: #define HBORDER (PVR_BASE+0x0D4) nkeynes@263: #define VSYNC (PVR_BASE+0x0D8) nkeynes@263: #define VBORDER (PVR_BASE+0x0DC) nkeynes@263: #define HSYNC (PVR_BASE+0x0E0) nkeynes@263: #define DISPCFG3 (PVR_BASE+0x0E8) nkeynes@263: #define HPOS (PVR_BASE+0x0EC) nkeynes@263: #define VPOS (PVR_BASE+0x0F0) nkeynes@263: #define SYNCSTAT (PVR_BASE+0x10C) nkeynes@263: nkeynes@263: #define MAX_FRAME_WAIT 0x10000000 nkeynes@263: nkeynes@263: #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; } nkeynes@263: #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; } nkeynes@263: nkeynes@263: void dump_display_regs( FILE *out ) nkeynes@263: { nkeynes@263: fprintf( out, "%08X DISPCFG1: %08X\n", DISPCFG1, long_read(DISPCFG1) ); nkeynes@263: fprintf( out, "%08X DISPCFG2: %08X\n", DISPCFG2, long_read(DISPCFG2) ); nkeynes@263: fprintf( out, "%08X DISPCFG3: %08X\n", DISPCFG3, long_read(DISPCFG3) ); nkeynes@263: fprintf( out, "%08X DISPSIZE: %08X\n", DISPSIZE, long_read(DISPSIZE) ); nkeynes@263: fprintf( out, "%08X HBORDER: %08X\n", HBORDER, long_read(HBORDER) ); nkeynes@263: fprintf( out, "%08X VBORDER: %08X\n", VBORDER, long_read(VBORDER) ); nkeynes@263: fprintf( out, "%08X HSYNC: %08X\n", HSYNC, long_read(HSYNC) ); nkeynes@263: fprintf( out, "%08X VSYNC: %08X\n", VSYNC, long_read(VSYNC) ); nkeynes@263: fprintf( out, "%08X DISPADDR1: %08X\n", DISPADDR1, long_read(DISPADDR1) ); nkeynes@263: fprintf( out, "%08X DISPADDR2: %08X\n", DISPADDR2, long_read(DISPADDR2) ); nkeynes@263: fprintf( out, "%08X HPOSEVENT: %08X\n", HPOSEVENT, long_read(HPOSEVENT) ); nkeynes@263: fprintf( out, "%08X VPOSEVENT: %08X\n", VPOSEVENT, long_read(VPOSEVENT) ); nkeynes@263: fprintf( out, "%08X HPOS: %08X\n", HPOS, long_read(HPOS) ); nkeynes@263: fprintf( out, "%08X VPOS: %08X\n", VPOS, long_read(VPOS) ); nkeynes@263: fprintf( out, "%08X SYNCSTAT: %08X\n", SYNCSTAT, long_read(SYNCSTAT) ); nkeynes@263: } nkeynes@263: nkeynes@263: uint32_t pal_settings[] = { nkeynes@263: DISPCFG1, 0x00000001, nkeynes@263: DISPCFG2, 0x00000150, nkeynes@263: DISPCFG3, 0x00160000, nkeynes@263: DISPSIZE, 0x1413BD3F, nkeynes@263: HBORDER, 0x008D034B, nkeynes@263: VBORDER, 0x00120102, nkeynes@263: VSYNC, 0x0270035F, nkeynes@263: HSYNC, 0x07D6A53F, nkeynes@263: HPOS, 0x000000A4, nkeynes@263: VPOS, 0x00120012, nkeynes@263: 0, 0 }; nkeynes@263: nkeynes@263: void apply_display_settings( uint32_t *regs ) { nkeynes@263: int i; nkeynes@263: for( i=0; regs[i] != 0; i+=2 ) { nkeynes@263: long_write( regs[i], regs[i+1] ); nkeynes@263: } nkeynes@263: } nkeynes@263: nkeynes@263: /** nkeynes@263: * Wait until the given line is being displayed (ie is set in the syncstat nkeynes@263: * register). nkeynes@263: * @return 0 if the line is reached before timeout, otherwise -1. nkeynes@263: */ nkeynes@263: int wait_line( int line ) nkeynes@263: { nkeynes@263: int i; nkeynes@263: for( i=0; i< MAX_FRAME_WAIT; i++ ) { nkeynes@263: uint32_t sync = long_read(SYNCSTAT) & 0x03FF; nkeynes@263: if( sync == line ) { nkeynes@263: return 0; nkeynes@263: } nkeynes@263: } nkeynes@263: return -1; nkeynes@263: } nkeynes@263: nkeynes@263: /** nkeynes@263: * Wait until just after the last line of the frame is being displayed (according nkeynes@263: * to the syncstat register). After this function the current line will be 0. nkeynes@263: * @return 0 if the last line is the given line, otherwise -1. nkeynes@263: */ nkeynes@263: int wait_lastline( int line ) nkeynes@263: { nkeynes@263: int lastline = -1, i; nkeynes@263: for( i=0; i< MAX_FRAME_WAIT; i++ ) { nkeynes@263: uint32_t sync = long_read(SYNCSTAT) & 0x03FF; nkeynes@263: if( sync == 0 && lastline != -1 ) { nkeynes@263: CHECK_IEQUALS( line, lastline ); nkeynes@263: return 0; nkeynes@263: } nkeynes@263: lastline = sync; nkeynes@263: } nkeynes@263: fprintf( stderr, "Timeout waiting for line %d\n", line ); nkeynes@263: return -1; nkeynes@263: } nkeynes@263: nkeynes@263: int test_ntsc_timing() { nkeynes@263: nkeynes@263: return 0; nkeynes@263: } nkeynes@263: nkeynes@263: nkeynes@263: int test_pal_timing() nkeynes@263: { nkeynes@263: uint32_t line_time, field_time; nkeynes@263: /* Set PAL display mode */ nkeynes@263: apply_display_settings( pal_settings ); nkeynes@263: nkeynes@263: asic_clear(); nkeynes@263: nkeynes@263: /* Check basic frame timings: 31.919 us per line, 19.945 ms per field */ nkeynes@263: /* Wait for a line 0 (either frame) */ nkeynes@263: WAIT_LINE(0); nkeynes@263: timer_start(); nkeynes@263: WAIT_LINE(1); nkeynes@263: line_time = timer_gettime_us(); nkeynes@263: WAIT_LASTLINE(624); nkeynes@263: field_time = timer_gettime_us(); nkeynes@263: fprintf( stdout, "Line time: %dus, frame time: %dus\n", line_time, field_time ); nkeynes@263: // CHECK_IEQUALS( 31, line_time ); nkeynes@263: CHECK_IEQUALS( 19949, field_time ); nkeynes@263: dump_display_regs( stdout ); nkeynes@263: return 0; nkeynes@263: } nkeynes@263: nkeynes@263: nkeynes@263: /********************************* Main **************************************/ nkeynes@263: nkeynes@263: typedef int (*test_func_t)(); nkeynes@263: nkeynes@263: test_func_t test_fns[] = { test_ntsc_timing, test_pal_timing, nkeynes@263: NULL }; nkeynes@263: nkeynes@263: int main() nkeynes@263: { nkeynes@263: return run_tests( test_fns ); nkeynes@263: }