filename | test/testdisp.c |
changeset | 272:fb6be85235e8 |
prev | 267:e59e36950761 |
next | 561:533f6b478071 |
author | nkeynes |
date | Thu Jan 11 06:53:31 2007 +0000 (16 years ago) |
permissions | -rw-r--r-- |
last change | Fix hsync timing checks Add timer_init and timer_run to preset the timer ahead of time |
view | annotate | diff | log | raw |
1 /**
2 * $Id: testdisp.c,v 1.3 2007-01-11 06:53:31 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 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 }
.