1/* Authors:
2   Mark Watson 2000,
3   Rudolf Cornelissen 1/2003-12/2003
4
5   Thanx to Petr Vandrovec for writing matroxfb.
6*/
7
8#define MODULE_BIT 0x00100000
9
10#include "std.h"
11
12typedef struct {
13	uint32 h_total;
14	uint32 h_display;
15	uint32 h_sync_length;
16	uint32 front_porch;
17	uint32 back_porch;
18	uint32 color_burst;
19	uint32 v_total;
20	float chroma_subcarrier;
21} gx50_maven_timing;
22
23void gxx0_maventv_PAL_init(uint8* buffer);
24void gxx0_maventv_NTSC_init(uint8* buffer);
25void gx50_maventv_PAL_timing(gx50_maven_timing *m_timing);
26void gx50_maventv_NTSC_timing(gx50_maven_timing *m_timing);
27
28//fixme: setup fixed CRTC2 modes for all modes and block other modes:
29// 		- 640x480, 800x600, 1024x768 NTSC and PAL overscan compensated modes (desktop)
30// 		- 640x480, 720x480 NTSC and 768x576, 720x576 non-overscan compensated modes (video)
31//fixme: try to implement 'fast' and 'slow' settings for all modes,
32//       so buffer duplication or skipping won't be neccesary for realtime video.
33//fixme: try to setup the CRTC2 in interlaced mode for the video modes on <= G400MAX cards.
34
35/* find 'exact' valid video PLL setting */
36status_t g100_g400max_maventv_vid_pll_find(
37	display_mode target, unsigned int * ht_new, unsigned int * ht_last_line,
38	uint8 * m_result, uint8 * n_result, uint8 * p_result)
39{
40	int m = 0, n = 0, p = 0, m_max;
41	float diff, diff_smallest = 999999999;
42	int best[5] = {0}, h_total_mod;
43	float fields_sec, f_vco;
44	/* We need to be exact, so work with clockperiods per field instead of with frequency.
45	 * Make sure however we truncate these clocks to be integers!
46	 * (The NTSC field frequency would otherwise prevent the 'whole number of clocks per field'
47	 *  check done in this routine later on...) */
48	uint32 vco_clks_field, max_pclks_field, req_pclks_field;
49	/* We need this variable to be a float, because we need to be able to verify if this
50	 * represents a whole number of clocks per field later on! */
51	float calc_pclks_field;
52
53	LOG(2,("MAVENTV: searching for EXACT videoclock match\n"));
54
55	/* determine the max. reference-frequency postscaler setting for the current card */
56	//fixme: check G100 and G200 m_max if exist and possible...
57	switch(si->ps.card_type)
58	{
59/*	case G100:
60		LOG(2,("MAVENTV: G100 restrictions apply\n"));
61		m_max = 32;
62		break;
63	case G200:
64		LOG(2,("MAVENTV: G200 restrictions apply\n"));
65		m_max = 32;
66		break;
67*/	default:
68		LOG(2,("MAVENTV: G400/G400MAX restrictions apply\n"));
69		m_max = 32;
70		break;
71	}
72
73	/* set number of fields per second to generate */
74	if ((target.flags & TV_BITS) == TV_PAL)
75		fields_sec = 50.0;
76	else
77		fields_sec = 59.94;
78
79	/* determine the max. pixelclock for the current videomode */
80	switch (target.space)
81	{
82		case B_RGB16_LITTLE:
83			max_pclks_field = (si->ps.max_dac2_clock_16 * 1000000) / fields_sec;
84			break;
85		case B_RGB32_LITTLE:
86			max_pclks_field = (si->ps.max_dac2_clock_32 * 1000000) / fields_sec;
87			break;
88		default:
89			/* use fail-safe value */
90			max_pclks_field = (si->ps.max_dac2_clock_32 * 1000000) / fields_sec;
91			break;
92	}
93	/* if some dualhead mode is active, an extra restriction might apply */
94	if ((target.flags & DUALHEAD_BITS) && (target.space == B_RGB32_LITTLE))
95		max_pclks_field = (si->ps.max_dac2_clock_32dh * 1000000) / fields_sec;
96
97	/* Checkout all possible Htotal settings within the current granularity step
98	 * of CRTC2 to get a real close videoclock match!
99	 * (The MAVEN apparantly has a granularity of 1 pixel, while CRTC2 has 8 pixels) */
100	for (h_total_mod = 0; h_total_mod < 8; h_total_mod++)
101	{
102		LOG(2,("MAVENTV: trying h_total modification of +%d...\n", h_total_mod));
103
104		/* Calculate videoclock to be a bit to high so we can compensate for an exact
105		 * match via h_total_lastline.. */
106		*ht_new = target.timing.h_total + h_total_mod + 2;
107
108		/* Make sure the requested pixelclock is within the PLL's operational limits */
109		/* lower limit is min_video_vco divided by highest postscaler-factor */
110		req_pclks_field = *ht_new * target.timing.v_total;
111		if (req_pclks_field < (((si->ps.min_video_vco * 1000000) / fields_sec) / 8.0))
112		{
113			req_pclks_field = (((si->ps.min_video_vco * 1000000) / fields_sec) / 8.0);
114			LOG(4,("MAVENTV: WARNING, clamping at lowest possible videoclock\n"));
115		}
116		/* upper limit is given by pins in combination with current active mode */
117		if (req_pclks_field > max_pclks_field)
118		{
119			req_pclks_field = max_pclks_field;
120			LOG(4,("MAVENTV: WARNING, clamping at highest possible videoclock\n"));
121		}
122
123		/* iterate through all valid PLL postscaler settings */
124		for (p=0x01; p < 0x10; p = p<<1)
125		{
126			/* calc the needed number of VCO clocks per field for this postscaler setting */
127			vco_clks_field = req_pclks_field * p;
128
129			/* check if this is within range of the VCO specs */
130			if ((vco_clks_field >= ((si->ps.min_video_vco * 1000000) / fields_sec)) &&
131				(vco_clks_field <= ((si->ps.max_video_vco * 1000000) / fields_sec)))
132			{
133				/* iterate trough all valid reference-frequency postscaler settings */
134				for (m = 2; m <= m_max; m++)
135				{
136					/* calculate VCO postscaler setting for current setup.. */
137					n = (int)(((vco_clks_field * m) / ((si->ps.f_ref * 1000000) / fields_sec)) + 0.5);
138					/* ..and check for validity */
139					if ((n < 8) || (n > 128))	continue;
140
141					/* special TVmode stuff starts here (rest is in fact standard): */
142					/* calculate number of videoclocks per field */
143					calc_pclks_field =
144						(((uint32)((si->ps.f_ref * 1000000) / fields_sec)) * n) / ((float)(m * p));
145
146					/* we need a whole number of clocks per field, otherwise it won't work correctly.
147					 * (TVout will flicker, green fields will occur) */
148					if (calc_pclks_field != (uint32)calc_pclks_field) continue;
149
150					/* check if we have the min. needed number of clocks per field for a sync lock */
151					if (calc_pclks_field < ((*ht_new * (target.timing.v_total - 1)) + 2)) continue;
152
153					/* calc number of clocks we have for the last field line */
154					*ht_last_line = calc_pclks_field - (*ht_new * (target.timing.v_total - 1));
155
156					/* check if we haven't got too much clocks in the last field line for a sync lock */
157					if (*ht_last_line > *ht_new) continue;
158
159					/* we have a match! */
160					/* calculate the difference between a full line and the last line */
161					diff = *ht_new - *ht_last_line;
162
163					/* if this last_line comes closer to a full line than earlier 'hits' then use it */
164					if (diff < diff_smallest)
165					{
166						/* log results */
167						if (diff_smallest == 999999999)
168							LOG(2,("MAVENTV: MATCH, "));
169						else
170							LOG(2,("MAVENTV: better MATCH,"));
171						f_vco = (si->ps.f_ref / m) * n;
172						LOG(2,("found vid VCO freq %fMhz, pixclk %fMhz\n", f_vco, (f_vco / p)));
173						LOG(2,("MAVENTV: mnp(ex. filter) 0x%02x 0x%02x 0x%02x, h_total %d, ht_lastline %d\n",
174							(m - 1), (n - 1), (p - 1), (*ht_new - 2), (*ht_last_line - 2)));
175
176						/* remember this best match */
177						diff_smallest = diff;
178						best[0] = m;
179						best[1] = n;
180						best[2] = p;
181						/* h_total to use for this setting:
182						 * exclude the 'calculate clock a bit too high' trick */
183						best[3] = *ht_new - 2;
184						/* ht_last_line to use for this setting:
185						 * exclude the 'calculate clock a bit too high' trick */
186						best[4] = *ht_last_line - 2;
187					}
188				}
189			}
190		}
191	}
192	LOG(2,("MAVENTV: search completed.\n"));
193
194	/* setup the scalers programming values for found optimum setting */
195	m = best[0] - 1;
196	n = best[1] - 1;
197	p = best[2] - 1;
198
199	/* if no match was found set fixed PLL frequency so we have something valid at least */
200	if (diff_smallest == 999999999)
201	{
202		LOG(4,("MAVENTV: WARNING, no MATCH found!\n"));
203
204		if (si->ps.f_ref == 27.000)
205		{
206			/* set 13.5Mhz */
207			m = 0x03;
208			n = 0x07;
209			p = 0x03;
210		}
211		else
212		{
213			/* set 14.31818Mhz */
214			m = 0x01;
215			n = 0x07;
216			p = 0x03;
217		}
218		best[3] = target.timing.h_total;
219		best[4] = target.timing.h_total;
220	}
221
222	/* calc the needed PLL loopbackfilter setting belonging to current VCO speed */
223	f_vco = (si->ps.f_ref / (m + 1)) * (n + 1);
224	LOG(2,("MAVENTV: using vid VCO frequency %fMhz\n", f_vco));
225
226	switch(si->ps.card_type)
227	{
228/*	case G100:
229	case G200:
230		for(;;)
231		{
232			if (f_vco >= 180) {p |= (0x03 << 3); break;};
233			if (f_vco >= 140) {p |= (0x02 << 3); break;};
234			if (f_vco >= 100) {p |= (0x01 << 3); break;};
235			break;
236		}
237		break;
238*/	default:
239		for(;;)
240		{
241			if (f_vco >= 240) {p |= (0x03 << 3); break;};
242			if (f_vco >= 170) {p |= (0x02 << 3); break;};
243			if (f_vco >= 110) {p |= (0x01 << 3); break;};
244			break;
245		}
246		break;
247	}
248
249	/* return results */
250	*m_result = m;
251	*n_result = n;
252	*p_result = p;
253	*ht_new = best[3];
254	*ht_last_line = best[4];
255
256	/* display the found pixelclock values */
257	LOG(2,("MAVENTV: vid PLL check: got %fMHz, mnp 0x%02x 0x%02x 0x%02x\n",
258		(f_vco / ((p & 0x07) + 1)), m, n, p));
259	LOG(2,("MAVENTV: new h_total %d, ht_lastline %d\n", *ht_new, *ht_last_line));
260
261	/* return status */
262	if (diff_smallest == 999999999) return B_ERROR;
263	return B_OK;
264}
265
266	/* Notes about timing:
267	 * Note:
268	 * all horizontal timing is measured in pixelclock periods;
269	 * all? vertical timing is measured in field? lines.  */
270
271	/* Note:
272	 * <= G400MAX cards have a fixed 27Mhz(?) clock for TV timing register values,
273	 * while on G450/G550 these need to be calculated based on the video pixelclock. */
274
275
276	/* Notes about signal strengths:
277	 * Note:
278	 * G400 and earlier cards have a fixed reference voltage of +2.6 Volt;
279	 * G450 and G550 cards MAVEN DACs have a switchable ref voltage of +1.5/+2.0 Volt.
280	 *
281	 * This voltage is used to feed the videosignals:
282	 * - Hsync pulse level;
283	 * - Lowest active video output level;
284	 * - Highest active video output level.
285	 * These actual voltages are set via 10bit DACs.
286	 *
287	 * G450/G550:
288	 * The color burst amplitude videosignal is fed by 80% of the above mentioned
289	 * ref. voltage, and is set via an 8bit DAC.
290	 * On G400 and earlier cards the ref. voltage is different, and also differs
291	 * for PAL and NTSC mode. */
292
293	/* Note:
294	 * Increasing the distance between the highest and lowest active video output
295	 * level increases contrast; decreasing it decreases contrast. */
296
297	/* Note:
298	 * Increasing both the highest and lowest active video output level with the
299	 * same amount increases brightness; decreasing it decreases brightness. */
300
301	/* Note:
302	 * Increasing the Hsync pulse level increases the black level, so decreases
303	 * brightness and contrast. */
304
305/* Preset maven PAL output (625lines, 50Hz mode) */
306void gxx0_maventv_PAL_init(uint8* buffer)
307{
308	uint16 value;
309
310	/* Chroma subcarrier divider */
311	buffer[0x00] = 0x2A;
312	buffer[0x01] = 0x09;
313	buffer[0x02] = 0x8A;
314	buffer[0x03] = 0xCB;
315
316	buffer[0x04] = 0x00;
317	buffer[0x05] = 0x00;
318	buffer[0x06] = 0xF9;
319	buffer[0x07] = 0x00;
320	/* Hsync pulse length */
321	buffer[0x08] = 0x7E;
322	/* color burst length */
323	buffer[0x09] = 0x44;
324	/* back porch length */
325	buffer[0x0a] = 0x9C;
326
327	/* color burst amplitude */
328/*	if (si->ps.card_type <= G400MAX)
329	{
330		buffer[0x0b] = 0x3e;
331	}
332	else
333	{
334*/		buffer[0x0b] = 0x48;
335//	}
336
337	buffer[0x0c] = 0x21;
338	buffer[0x0d] = 0x00;
339
340//	if (si->ps.card_type <= G400MAX)
341//	{
342		/* Lowest active video output level.
343		 * Warning: make sure this stays above (or equals) the sync pulse level! */
344//		value = 0x0ea;
345//		buffer[0x0e] = ((value >> 2) & 0xff);
346//		buffer[0x0f] = (value & 0x03);
347		/* horizontal sync pulse level */
348//		buffer[0x10] = ((value >> 2) & 0xff);
349//		buffer[0x11] = (value & 0x03);
350//	}
351//	else
352	{
353		/* Lowest active video output level.
354		 * Warning: make sure this stays above (or equals) the sync pulse level! */
355		value = 0x130;
356		buffer[0x0e] = ((value >> 2) & 0xff);
357		buffer[0x0f] = (value & 0x03);
358		/* horizontal sync pulse level */
359		buffer[0x10] = ((value >> 2) & 0xff);
360		buffer[0x11] = (value & 0x03);
361	}
362
363	buffer[0x12] = 0x1A;
364	buffer[0x13] = 0x2A;
365
366	/* functional unit */
367	buffer[0x14] = 0x1C;
368	buffer[0x15] = 0x3D;
369	buffer[0x16] = 0x14;
370
371	/* vertical total */ //(=625)
372	/* b9-2 */
373	buffer[0x17] = 0x9C;
374	/* b1-0 in b1-0 */
375	buffer[0x18] = 0x01;
376
377	buffer[0x19] = 0x00;
378	buffer[0x1a] = 0xFE;
379	buffer[0x1b] = 0x7E;
380	buffer[0x1c] = 0x60;
381	buffer[0x1d] = 0x05;
382
383	/* Highest active video output level.
384	 * Warning: make sure this stays above the lowest active video output level! */
385/*	if (si->ps.card_type <= G400MAX)
386	{
387		value = 0x24f;
388		buffer[0x1e] = ((value >> 2) & 0xff);
389		buffer[0x1f] = (value & 0x03);
390	}
391	else
392*/	{
393		value = 0x300;
394		buffer[0x1e] = ((value >> 2) & 0xff);
395		buffer[0x1f] = (value & 0x03);
396	}
397
398	/* saturation (field?) #1 */
399//	if (si->ps.card_type <= G400MAX)
400//		buffer[0x20] = 0x72;
401//	else
402		buffer[0x20] = 0xA5;
403
404	buffer[0x21] = 0x07;
405
406	/* saturation (field?) #2 */
407//	if (si->ps.card_type <= G400MAX)
408//		buffer[0x22] = 0x72;
409//	else
410		buffer[0x22] = 0xA5;
411
412	buffer[0x23] = 0x00;
413	buffer[0x24] = 0x00;
414	/* hue? */
415	buffer[0x25] = 0x00;
416
417	buffer[0x26] = 0x08;
418	buffer[0x27] = 0x04;
419	buffer[0x28] = 0x00;
420	buffer[0x29] = 0x1A;
421
422	/* functional unit */
423	buffer[0x2a] = 0x55;
424	buffer[0x2b] = 0x01;
425
426	/* front porch length */
427	buffer[0x2c] = 0x26;
428
429	/* functional unit */
430	buffer[0x2d] = 0x07;
431	buffer[0x2e] = 0x7E;
432
433	/* functional unit */
434	buffer[0x2f] = 0x02;
435	buffer[0x30] = 0x54;
436
437	/* horizontal visible */
438	value = 0x580;
439	buffer[0x31] = ((value >> 3) & 0xff);
440	buffer[0x32] = (value & 0x07);
441
442	/* upper blanking (in field lines) */
443	buffer[0x33] = 0x14; //=((v_total - v_sync_end)/2) -1
444
445	buffer[0x34] = 0x49;
446	buffer[0x35] = 0x00;
447	buffer[0x36] = 0x00;
448	buffer[0x37] = 0xA3;
449	buffer[0x38] = 0xC8;
450	buffer[0x39] = 0x22;
451	buffer[0x3a] = 0x02;
452	buffer[0x3b] = 0x22;
453
454	/* functional unit */
455	buffer[0x3c] = 0x3F;
456	buffer[0x3d] = 0x03;
457}
458
459/* Preset maven NTSC output (525lines, 59.94Hz mode) */
460void gxx0_maventv_NTSC_init(uint8* buffer)
461{
462	uint16 value;
463
464	/* Chroma subcarrier frequency */
465	buffer[0x00] = 0x21;
466	buffer[0x01] = 0xF0;
467	buffer[0x02] = 0x7C;
468	buffer[0x03] = 0x1F;
469
470	buffer[0x04] = 0x00;
471	buffer[0x05] = 0x00;//b1 = ON enables colorbar testimage
472	buffer[0x06] = 0xF9;//b0 = ON enables MAVEN TV output
473	buffer[0x07] = 0x00;//influences the colorburst signal amplitude somehow
474
475	/* Hsync pulse length */
476	buffer[0x08] = 0x7E;
477	/* color burst length */
478	buffer[0x09] = 0x43;
479	/* back porch length */
480	buffer[0x0a] = 0x7E;
481
482	/* color burst amplitude */
483//	if (si->ps.card_type <= G400MAX)
484//	{
485//		buffer[0x0b] = 0x46;
486//	}
487//	else
488	{
489		buffer[0x0b] = 0x48;
490	}
491
492	buffer[0x0c] = 0x00;
493	buffer[0x0d] = 0x00;
494
495//	if (si->ps.card_type <= G400MAX)
496//	{
497		/* Lowest active video output level.
498		 * Warning: make sure this stays above (or equals) the sync pulse level! */
499//		value = 0x0ea;
500//		buffer[0x0e] = ((value >> 2) & 0xff);
501//		buffer[0x0f] = (value & 0x03);
502		/* horizontal sync pulse level */
503//		buffer[0x10] = ((value >> 2) & 0xff);
504//		buffer[0x11] = (value & 0x03);
505//	}
506//	else
507	{
508		/* Lowest active video output level.
509		 * Warning: make sure this stays above (or equals) the sync pulse level! */
510		value = 0x130;
511		buffer[0x0e] = ((value >> 2) & 0xff);
512		buffer[0x0f] = (value & 0x03);
513		/* horizontal sync pulse level */
514		buffer[0x10] = ((value >> 2) & 0xff);
515		buffer[0x11] = (value & 0x03);
516	}
517
518	buffer[0x12] = 0x17;
519	buffer[0x13] = 0x21;
520
521	/* functional unit */
522	buffer[0x14] = 0x1B;
523	buffer[0x15] = 0x1B;
524	buffer[0x16] = 0x24;
525
526	/* vertical total */
527	/* b9-2 */
528	buffer[0x17] = 0x83;
529	/* b1-0 in b1-0 */
530	buffer[0x18] = 0x01;
531
532	buffer[0x19] = 0x00;//mv register?
533	buffer[0x1a] = 0x0F;
534	buffer[0x1b] = 0x0F;
535	buffer[0x1c] = 0x60;
536	buffer[0x1d] = 0x05;
537
538	/* Highest active video output level.
539	 * Warning: make sure this stays above the lowest active video output level! */
540/*	if (si->ps.card_type <= G400MAX)
541	{
542		value = 0x24f;
543		buffer[0x1e] = ((value >> 2) & 0xff);
544		buffer[0x1f] = (value & 0x03);
545	}
546	else
547*/	{
548		value = 0x300;
549		buffer[0x1e] = ((value >> 2) & 0xff);
550		buffer[0x1f] = (value & 0x03);
551	}
552
553	/* color saturation #1 (Y-B ?) */
554//	if (si->ps.card_type <= G400MAX)
555//		buffer[0x20] = 0x5F;
556//	else
557		buffer[0x20] = 0x9C;
558
559	buffer[0x21] = 0x04;
560
561	/* color saturation #2 (Y-R ?) */
562//	if (si->ps.card_type <= G400MAX)
563//		buffer[0x22] = 0x5F;
564//	else
565		buffer[0x22] = 0x9C;
566
567	buffer[0x23] = 0x01;
568	buffer[0x24] = 0x02;
569
570	/* hue: preset at 0 degrees */
571	buffer[0x25] = 0x00;
572
573	buffer[0x26] = 0x0A;
574	buffer[0x27] = 0x05;//sync stuff
575	buffer[0x28] = 0x00;
576	buffer[0x29] = 0x10;//field line-length stuff
577
578	/* functional unit */
579	buffer[0x2a] = 0xFF;
580	buffer[0x2b] = 0x03;
581
582	/* front porch length */
583	buffer[0x2c] = 0x24;
584
585	/* functional unit */
586	buffer[0x2d] = 0x0F;
587	buffer[0x2e] = 0x78;
588
589	/* functional unit */
590	buffer[0x2f] = 0x00;
591	buffer[0x30] = 0x00;
592
593	/* horizontal visible */
594	/* b10-3 */
595	buffer[0x31] = 0xB2;
596	/* b2-0 in b2-0 */
597	buffer[0x32] = 0x04;
598
599	/* upper blanking (in field lines) */
600	buffer[0x33] = 0x14;
601
602	buffer[0x34] = 0x02;//colorphase or so stuff.
603	buffer[0x35] = 0x00;
604	buffer[0x36] = 0x00;
605	buffer[0x37] = 0xA3;
606	buffer[0x38] = 0xC8;
607	buffer[0x39] = 0x15;
608	buffer[0x3a] = 0x05;
609	buffer[0x3b] = 0x3B;
610
611	/* functional unit */
612	buffer[0x3c] = 0x3C;
613	buffer[0x3d] = 0x00;
614}
615
616void gx50_maventv_PAL_timing(gx50_maven_timing *m_timing)
617{
618	/* values are given in picoseconds */
619	m_timing->h_total = 64000000;
620	/* the sum of the signal duration below should match h_total! */
621	m_timing->h_display = 52148148;
622	m_timing->h_sync_length = 4666667;
623	m_timing->front_porch = 1407407;
624	m_timing->back_porch = 5777778;
625	/* colorburst is 'superimposed' on the above timing */
626	m_timing->color_burst = 2518518;
627	/* number of lines per frame */
628	m_timing->v_total = 625;
629	/* color carrier frequency in Mhz */
630	m_timing->chroma_subcarrier = 4.43361875;
631}
632
633void gx50_maventv_NTSC_timing(gx50_maven_timing *m_timing)
634{
635	/* values are given in picoseconds */
636	m_timing->h_total = 63555556;
637	/* the sum of the signal duration below should match h_total! */
638	m_timing->h_display = 52888889;
639	m_timing->h_sync_length = 4666667;
640	m_timing->front_porch = 1333333;
641	m_timing->back_porch = 4666667;
642	/* colorburst is 'superimposed' on the above timing */
643	m_timing->color_burst = 2418418;
644	/* number of lines per frame */
645	m_timing->v_total = 525;
646	/* color carrier frequency in Mhz */
647	m_timing->chroma_subcarrier = 3.579545454;
648}
649
650int maventv_init(display_mode target)
651{
652	uint8 val;
653	uint8 m_result, n_result, p_result;
654	unsigned int ht_new, ht_last_line;
655	float calc_pclk = 0;
656	/* use a display_mode copy because we might tune it for TVout compatibility */
657	display_mode tv_target = target;
658	/* used as buffer for TVout signal to generate */
659	uint8 maventv_regs[64];
660	/* used in G450/G550 to calculate TVout signal timing dependant on pixelclock;
661	 * <= G400MAX use fixed settings because base-clock here is the fixed crystal
662	 * frequency. */
663	//fixme: if <=G400 cards with MAVEN and crystal of 14.31818Mhz exist, modify!?!
664	gx50_maven_timing m_timing;
665
666	/* preset new TVout mode */
667	if ((tv_target.flags & TV_BITS) == TV_PAL)
668	{
669		LOG(4, ("MAVENTV: PAL TVout\n"));
670		gxx0_maventv_PAL_init(maventv_regs);
671		gx50_maventv_PAL_timing(&m_timing);
672	}
673	else
674	{
675		LOG(4, ("MAVENTV: NTSC TVout\n"));
676		gxx0_maventv_NTSC_init(maventv_regs);
677		gx50_maventv_NTSC_timing(&m_timing);
678	}
679
680	/* enter mode-program mode */
681//	if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x01);
682//	else
683//	{
684//		DXIW(TVO_IDX, ENMAV_PGM);
685//		DXIW(TVO_DATA, 0x01);
686//	}
687
688	/* tune new TVout mode */
689//	if (si->ps.card_type <= G400MAX)
690	{
691		/* setup TV-mode 'copy' of CRTC2, setup PLL, inputs, outputs and sync-locks */
692//		MAVW(MONSET, 0x00);
693//		MAVW(MONEN, 0xA2);
694
695		/* xmiscctrl */
696		//unknown regs:
697//		MAVWW(WREG_0X8E_L, 0x1EFF);
698//		MAVW(BREG_0XC6, 0x01);
699
700//		MAVW(LOCK, 0x01);
701//		MAVW(OUTMODE, 0x08);
702//		MAVW(LUMA, 0x78);
703//		MAVW(STABLE, 0x02);
704//		MAVW(MONEN, 0xB3);
705
706		/* setup video PLL */
707		g100_g400max_maventv_vid_pll_find(
708			tv_target, &ht_new, &ht_last_line, &m_result, &n_result, &p_result);
709//		MAVW(PIXPLLM, m_result);
710//		MAVW(PIXPLLN, n_result);
711//		MAVW(PIXPLLP, (p_result | 0x80));
712
713//		MAVW(MONSET, 0x20);
714
715//		MAVW(TEST, 0x10);
716
717		/* htotal - 2 */
718//		MAVWW(HTOTALL, ht_new);
719
720		/* last line in field can have different length */
721		/* hlen - 2 */
722//		MAVWW(LASTLINEL, ht_last_line);
723
724		/* horizontal vidrst pos: 0 <= vidrst pos <= htotal - 2 */
725//		MAVWW(HVIDRSTL, (ht_last_line - si->crtc_delay -
726//						(tv_target.timing.h_sync_end - tv_target.timing.h_sync_start)));
727		//ORG (does the same but with limit checks but these limits should never occur!):
728//		slen = tv_target.timing.h_sync_end - tv_target.timing.h_sync_start;
729//		hcrt = tv_target.timing.h_total - slen - si->crtc_delay;
730//		if (ht_last_line < tv_target.timing.h_total) hcrt += ht_last_line;
731//		if (hcrt > tv_target.timing.h_total) hcrt -= tv_target.timing.h_total;
732//		if (hcrt + 2 > tv_target.timing.h_total) hcrt = 0;	/* or issue warning? */
733//		MAVWW(HVIDRSTL, hcrt);
734
735		/* who knows */
736//		MAVWW(HSYNCSTRL, 0x0004);//must be 4!!
737
738		/* hblanking end: 100% */
739//		MAVWW(HSYNCLENL, (tv_target.timing.h_total - tv_target.timing.h_sync_end));
740
741		/* vertical line count - 1 */
742//		MAVWW(VTOTALL, (tv_target.timing.v_total - 1));
743
744		/* vertical vidrst pos */
745//		MAVWW(VVIDRSTL, (tv_target.timing.v_total - 2));
746
747		/* something end... [A6]+1..[A8] */
748//		MAVWW(VSYNCSTRL, 0x0001);
749
750		/* vblanking end: stop vblanking */
751//		MAVWW(VSYNCLENL, (tv_target.timing.v_sync_end - tv_target.timing.v_sync_start - 1));
752		//org: no visible diff:
753		//MAVWW(VSYNCLENL, (tv_target.timing.v_total - tv_target.timing.v_sync_start - 1));
754
755		/* something start... 0..[A4]-1 */
756//		MAVWW(VDISPLAYL, 0x0000);
757		//std setmode (no visible difference)
758		//MAVWW(VDISPLAYL, (tv_target.timing.v_total - 1));
759
760		/* ... */
761//		MAVWW(WREG_0X98_L, 0x0000);
762
763		/* moves picture up/down and so on... */
764//		MAVWW(VSOMETHINGL, 0x0001); /* Fix this... 0..VTotal */
765
766		{
767			uint32 h_display_tv;
768			uint8 h_scale_tv;
769
770			unsigned int ib_min_length;
771			unsigned int ib_length;
772			int index;
773
774			/* calc hor scale-back factor from input to output picture (in 1.7 format)
775			 * the MAVEN has 736 pixels fixed visible? outputline length for TVout */
776			//fixme: shouldn't this be 768 (= PAL 1:1 output 4:3 ratio format)?!?
777			h_scale_tv = (736 << 7) / tv_target.timing.h_total;//should be PLL corrected
778			LOG(4,("MAVENTV: horizontal scale-back factor is: %f\n", (h_scale_tv / 128.0)));
779
780			/* limit values to MAVEN capabilities (scale-back factor is 0.5-1.0) */
781			//fixme: how about lowres upscaling?
782			if (h_scale_tv > 0x80)
783			{
784				h_scale_tv = 0x80;
785				LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0)));
786			}
787			if (h_scale_tv < 0x40)
788			{
789				h_scale_tv = 0x40;
790				LOG(4,("MAVENTV: limiting horizontal scale-back factor to: %f\n", (h_scale_tv / 128.0)));
791			}
792			/* make sure we get no round-off error artifacts on screen */
793			h_scale_tv--;
794
795			/* calc difference in (wanted output picture width (excl. hsync_length)) and
796			 * (fixed total output line length (=768)),
797			 * based on input picture and scaling factor */
798			/* (MAVEN trick (part 1) to get output picture width to fit into just 8 bits) */
799			h_display_tv = ((768 - 1) << 7) -
800				(((tv_target.timing.h_total - tv_target.timing.h_sync_end)	/* is left margin */
801				 + tv_target.timing.h_display - 8)
802				 * h_scale_tv);
803			/* convert result from 25.7 to 32.0 format */
804			h_display_tv = h_display_tv >> 7;
805			LOG(4,("MAVENTV: displaying output on %d picture pixels\n",
806				((768 - 1) - h_display_tv)));
807
808			/* half result: MAVEN trick (part 2)
809			 * (258 - 768 pixels, only even number per line is possible) */
810			h_display_tv = h_display_tv >> 1;
811			/* limit value to register contraints */
812			if (h_display_tv > 0xFF) h_display_tv = 0xFF;
813//			MAVW(HSCALETV, h_scale_tv);
814//			MAVW(HDISPLAYTV, h_display_tv);
815
816
817			/* calculate line inputbuffer length */
818			/* It must be between (including):
819			 * ((input picture left margin) + (input picture hor. resolution) + 4)
820			 * AND
821			 * (input picture total line length) (PLL corrected) */
822
823			/* calculate minimal line input buffer length */
824			ib_min_length = ((tv_target.timing.h_total - tv_target.timing.h_sync_end) +
825				 			  tv_target.timing.h_display + 4);
826
827			/* calculate optimal line input buffer length (so top of picture is OK too) */
828			/* The following formula applies:
829			 * optimal buffer length = ((((0x78 * i) - R) / hor. scaling factor) + Q)
830			 *
831			 * where (in 4.8 format!)
832		     * R      Qmin  Qmax
833			 * 0x0E0  0x5AE 0x5BF
834			 * 0x100  0x5CF 0x5FF
835			 * 0x180  0x653 0x67F
836			 * 0x200  0x6F8 0x6FF
837			 */
838			index = 1;
839			do
840			{
841				ib_length = ((((((0x7800 << 7) * index) - (0x100 << 7)) / h_scale_tv) + 0x05E7) >> 8);
842				index++;
843			} while (ib_length < ib_min_length);
844			LOG(4,("MAVENTV: optimal line inputbuffer length: %d\n", ib_length));
845
846			if (ib_length >= ht_new + 2)
847			{
848				ib_length = ib_min_length;
849				LOG(4,("MAVENTV: limiting line inputbuffer length, setting minimal usable: %d\n", ib_length));
850			}
851//			MAVWW(HDISPLAYL, ib_length);
852		}
853
854		{
855			uint16 t_scale_tv;
856			uint32 v_display_tv;
857
858			/* calc total scale-back factor from input to output picture */
859			{
860				uint32 out_clocks;
861				uint32 in_clocks;
862
863				//takes care of green stripes:
864				/* calc output clocks per frame */
865				out_clocks = m_timing.v_total * (ht_new + 2);
866
867				/* calc input clocks per frame */
868				in_clocks = (tv_target.timing.v_total - 1) * (ht_new + 2) +	ht_last_line + 2;
869
870				/* calc total scale-back factor from input to output picture in 1.15 format */
871				t_scale_tv = ((((uint64)out_clocks) << 15) / in_clocks);
872				LOG(4,("MAVENTV: total scale-back factor is: %f\n", (t_scale_tv / 32768.0)));
873
874				/* min. scale-back factor is 1.0 for 1:1 output */
875				if (t_scale_tv > 0x8000)
876				{
877					t_scale_tv = 0x8000;
878					LOG(4,("MAVENTV: limiting total scale-back factor to: %f\n", (t_scale_tv / 32768.0)));
879				}
880			}
881
882			/*calc output picture height based on input picture and scaling factor */
883			//warning: v_display was 'one' lower originally!
884			v_display_tv =
885				((tv_target.timing.v_sync_end - tv_target.timing.v_sync_start) 	/* is sync length */
886				 + (tv_target.timing.v_total - tv_target.timing.v_sync_end) 	/* is upper margin */
887				 + tv_target.timing.v_display)
888				 * t_scale_tv;
889			/* convert result from 17.15 to 32.0 format */
890			v_display_tv = (v_display_tv >> 15);
891			LOG(4,("MAVENTV: displaying output on %d picture frame-lines\n", v_display_tv));
892
893			/* half result, and compensate for internal register offset
894			 * (MAVEN trick to get it to fit into just 8 bits).
895			 * (allowed output frame height is 292 - 802 lines, only even numbers) */
896			v_display_tv = (v_display_tv >> 1) - 146;
897			/* limit value to register contraints */
898			if (v_display_tv > 0xFF) v_display_tv = 0xFF;
899			/* make sure we get no round-off error artifacts on screen */
900			t_scale_tv--;
901
902//			MAVWW(TSCALETVL, t_scale_tv);
903//			MAVW(VDISPLAYTV, v_display_tv);
904		}
905
906//		MAVW(TEST, 0x00);
907
908		/* gamma correction registers */
909//		MAVW(GAMMA1, 0x00);
910//		MAVW(GAMMA2, 0x00);
911//		MAVW(GAMMA3, 0x00);
912//		MAVW(GAMMA4, 0x1F);
913//		MAVW(GAMMA5, 0x10);
914//		MAVW(GAMMA6, 0x10);
915//		MAVW(GAMMA7, 0x10);
916//		MAVW(GAMMA8, 0x64);	/* 100 */
917//		MAVW(GAMMA9, 0xC8);	/* 200 */
918
919		/* set flickerfilter */
920		/* OFF: is dependant on MAVEN chip version(?): ENG_TVO_B = $40, else $00.
921		 * ON : always set $a2. */
922//		MAVW(FFILTER, 0xa2);
923
924		/* 0x10 or anything ored with it */
925		//fixme? linux uses 0x14...
926//		MAVW(TEST, (MAVR(TEST) & 0x10));
927
928		/* output: SVideo/Composite */
929//		MAVW(OUTMODE, 0x08);
930	}
931//	else /* card_type is >= G450 */
932	{
933		//fixme: setup an intermediate buffer if vertical res is different than settings below!
934		//fixme: setup 2D or 3D engine to do screen_to_screen_scaled_filtered_blit between the buffers
935		//       during vertical retrace!
936		if ((tv_target.flags & TV_BITS) == TV_PAL)
937		{
938			int diff;
939
940			/* defined by the PAL standard */
941			tv_target.timing.v_total = m_timing.v_total;
942			/* we need to center the image on TV vertically.
943			 * note that 576 is the maximum supported resolution for the PAL standard,
944			 * this is already overscanning by approx 8-10% */
945			diff = 576 - tv_target.timing.v_display;
946			/* if we cannot display the current vertical resolution fully, clip it */
947			if (diff < 0)
948			{
949				tv_target.timing.v_display = 576;
950				diff = 0;
951			}
952			/* now center the image on TV by centering the vertical sync pulse */
953			tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2);
954			tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1;
955		}
956		else
957		{
958			int diff;
959
960			/* defined by the NTSC standard */
961			tv_target.timing.v_total = m_timing.v_total;
962			/* we need to center the image on TV vertically.
963			 * note that 480 is the maximum supported resolution for the NTSC standard,
964			 * this is already overscanning by approx 8-10% */
965			diff = 480 - tv_target.timing.v_display;
966			/* if we cannot display the current vertical resolution fully, clip it */
967			if (diff < 0)
968			{
969				tv_target.timing.v_display = 480;
970				diff = 0;
971			}
972			/* now center the image on TV by centering the vertical sync pulse */
973			tv_target.timing.v_sync_start = tv_target.timing.v_display + 1 + (diff / 2);
974			tv_target.timing.v_sync_end = tv_target.timing.v_sync_start + 1;
975		}
976
977		/* setup video PLL for G450/G550:
978		 * this can be done in the normal way because the MAVEN works in slave mode!
979		 * NOTE: must be done before programming CRTC2, or interlaced startup may fail. */
980
981		//fixme: make sure videoPLL is powered up: XPWRCTRL b1=1
982		{
983			uint16 front_porch, back_porch, h_sync_length, burst_length, h_total, h_display;
984			uint32 chromasc;
985			uint64 pix_period;
986			uint16 h_total_wanted, leftover;
987
988			/* calculate tv_h_display in 'half pixelclocks' and adhere to MAVEN restrictions.
989			 * ('half pixelclocks' exist because the MAVEN uses them...) */
990			h_display = (((tv_target.timing.h_display << 1) + 3) & ~0x03);
991			if (h_display > 2044) h_display = 2044;
992			/* copy result to MAVEN TV mode */
993			maventv_regs[0x31] = (h_display >> 3);
994			maventv_regs[0x32] = (h_display & 0x07);
995
996			/* calculate needed video pixelclock in kHz.
997			 * NOTE:
998			 * The clock calculated is based on MAVEN output, so each pixelclock period
999			 * is in fact a 'half pixelclock' period compared to monitor mode use. */
1000			tv_target.timing.pixel_clock =
1001				((((uint64)h_display) * 1000000000) / m_timing.h_display);
1002
1003			/* tune display_mode adhering to CRTC2 restrictions */
1004			/* (truncate h_display to 'whole pixelclocks') */
1005			tv_target.timing.h_display = ((h_display >> 1) & ~0x07);
1006			tv_target.timing.h_sync_start = tv_target.timing.h_display + 8;
1007
1008//			g450_g550_maven_vid_pll_find(tv_target, &calc_pclk, &m_result, &n_result, &p_result, 1);
1009			/* adjust mode to actually used pixelclock */
1010			tv_target.timing.pixel_clock = (calc_pclk * 1000);
1011
1012			/* program videoPLL */
1013//			DXIW(VIDPLLM, m_result);
1014//			DXIW(VIDPLLN, n_result);
1015//			DXIW(VIDPLLP, p_result);
1016
1017			/* calculate videoclock 'half' period duration in picoseconds */
1018			pix_period = (1000000000 / ((float)tv_target.timing.pixel_clock)) + 0.5;
1019			LOG(4,("MAVENTV: TV videoclock period is %d picoseconds\n", pix_period));
1020
1021			/* calculate number of 'half' clocks per line according to pixelclock set */
1022			/* fixme: try to setup the modes in such a way that
1023			 * (h_total_clk % 16) == 0 because of the CRTC2 restrictions:
1024			 * we want to loose the truncating h_total trick below if possible! */
1025			/* Note:
1026			 * This is here so we can see the wanted and calc'd timing difference. */
1027			h_total_wanted = ((m_timing.h_total / ((float)pix_period)) + 0.5);
1028			LOG(4,("MAVENTV: TV h_total should be %d units\n", h_total_wanted));
1029
1030			/* calculate chroma subcarrier value to setup:
1031			 * do this as exact as possible because this signal is very sensitive.. */
1032			chromasc =
1033				((((uint64)0x100000000) * (m_timing.chroma_subcarrier / calc_pclk)) + 0.5);
1034			/* copy result to MAVEN TV mode */
1035			maventv_regs[0] = ((chromasc >> 24) & 0xff);
1036			maventv_regs[1] = ((chromasc >> 16) & 0xff);
1037			maventv_regs[2] = ((chromasc >>  8) & 0xff);
1038			maventv_regs[3] = ((chromasc >>  0) & 0xff);
1039			LOG(4,("MAVENTV: TV chroma subcarrier divider set is $%08x\n", chromasc));
1040
1041			/* calculate front porch in 'half pixelclocks' */
1042			/* we always round up because of the h_total truncating 'trick' below,
1043			 * which works in combination with the existing difference between
1044			 * h_total_clk and h_total */
1045			//fixme: prevent this if possible!
1046			front_porch = ((m_timing.front_porch / ((float)pix_period)) + 1);
1047			/* value must be even */
1048			front_porch &= ~0x01;
1049
1050			/* calculate back porch in 'half pixelclocks' */
1051			/* we always round up because of the h_total truncating 'trick' below,
1052			 * which works in combination with the existing difference between
1053			 * h_total_clk and h_total */
1054			//fixme: prevent this if possible!
1055			back_porch = ((m_timing.back_porch / ((float)pix_period)) + 1);
1056			/* value must be even */
1057			back_porch &= ~0x01;
1058
1059			/* calculate h_sync length in 'half pixelclocks' */
1060			/* we always round up because of the h_total truncating 'trick' below,
1061			 * which works in combination with the existing difference between
1062			 * h_total_clk and h_total */
1063			//fixme: prevent this if possible!
1064			h_sync_length = ((m_timing.h_sync_length / ((float)pix_period)) + 1);
1065			/* value must be even */
1066			h_sync_length &= ~0x01;
1067
1068			/* calculate h_total in 'half pixelclocks' */
1069			h_total = h_display + front_porch + back_porch + h_sync_length;
1070
1071			LOG(4,("MAVENTV: TV front_porch is %d clocks\n", front_porch));
1072			LOG(4,("MAVENTV: TV back_porch is %d clocks\n", back_porch));
1073			LOG(4,("MAVENTV: TV h_sync_length is %d clocks\n", h_sync_length));
1074			LOG(4,("MAVENTV: TV h_display is %d clocks \n", h_display));
1075			LOG(4,("MAVENTV: TV h_total is %d clocks\n", h_total));
1076
1077			/* calculate color_burst length in 'half pixelclocks' */
1078			burst_length = (((m_timing.color_burst /*- 1*/) / ((float)pix_period)) + 0.5);
1079			LOG(4,("MAVENTV: TV color_burst is %d clocks.\n", burst_length));
1080
1081			/* copy result to MAVEN TV mode */
1082			maventv_regs[0x09] = burst_length;
1083
1084			/* Calculate line length 'rest' that remains after truncating
1085			 * h_total to adhere to the CRTC2 timing restrictions. */
1086			leftover = h_total & 0x0F;
1087			/* if some 'rest' exists, we need to compensate for it... */
1088			/* Note:
1089			 * It's much better to prevent this from happening because this
1090			 * 'trick' will decay TVout timing! (timing is nolonger official) */
1091			if (leftover)
1092			{
1093				/* truncate line length to adhere to CRTC2 restrictions */
1094				front_porch -= leftover;
1095				h_total -= leftover;
1096
1097				/* now set line length to closest CRTC2 valid match */
1098				if (leftover < 3)
1099				{
1100					/* 1 <= old rest <= 2:
1101					 * Truncated line length is closest match. */
1102					LOG(4,("MAVENTV: CRTC2 h_total leftover discarded (< 3)\n"));
1103				}
1104				else
1105				{
1106					if (leftover < 10)
1107					{
1108						/* 3 <= old rest <= 9:
1109						 * We use the NTSC killer circuitry to get closest match.
1110						 * (The 'g400_crtc2_set_timing' routine will enable it
1111						 *  because of the illegal h_total timing we create here.) */
1112						front_porch += 4;
1113						h_total += 4;
1114						LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via killer (> 2, < 10)\n"));
1115					}
1116					else
1117					{
1118						/* 10 <= old rest <= 15:
1119						 * Set closest valid CRTC2 match. */
1120						front_porch += 16;
1121						h_total += 16;
1122						LOG(4,("MAVENTV: CRTC2 h_total leftover corrected via increase (> 9, < 16)\n"));
1123					}
1124				}
1125			}
1126
1127			/* (linux) fixme: maybe MAVEN has requirement 800 < h_total < 1184 */
1128			maventv_regs[0x2C] = front_porch;
1129			maventv_regs[0x0A] = back_porch;
1130			maventv_regs[0x08] = h_sync_length;
1131
1132			/* change h_total to represent 'whole pixelclocks' */
1133			h_total = h_total >> 1;
1134
1135			/* tune display_mode adhering to CRTC2 restrictions */
1136			tv_target.timing.h_sync_end = (h_total & ~0x07) - 8;
1137			/* h_total is checked before being programmed! (NTSC killer circuitry) */
1138			tv_target.timing.h_total = h_total;
1139		}
1140
1141		/* output Y/C and CVBS signals (| $40 needed for SCART) */
1142//		DXIW(TVO_IDX, 0x80);
1143//		DXIW(TVO_DATA, 0x03);
1144
1145		/* select input colorspace */
1146		//fixme?: has no effect on output picture on monitor or TV...
1147		//DXIW(TVO_IDX, 0x81);
1148		//DXIW(TVO_DATA, 0x00);
1149
1150		/* calculate vertical sync point */
1151		{
1152			int upper;
1153
1154			/* set 625 lines for PAL or 525 lines for NTSC */
1155			maventv_regs[0x17] = m_timing.v_total / 4;
1156			maventv_regs[0x18] = m_timing.v_total & 3;
1157
1158			/* calculate upper blanking range in field lines */
1159			upper = (m_timing.v_total - tv_target.timing.v_sync_end) >> 1;
1160
1161			/* blank TVout above the line number calculated */
1162			maventv_regs[0x33] = upper - 1;
1163
1164			/* set calculated vertical sync point */
1165//			DXIW(TVO_IDX, 0x82);
1166//			DXIW(TVO_DATA, (upper & 0xff));
1167//			DXIW(TVO_IDX, 0x83);
1168//			DXIW(TVO_DATA, ((upper >> 8) & 0xff));
1169			LOG(4,("MAVENTV: TV upper blanking range set is %d\n", upper));
1170		}
1171
1172		/* set fized horizontal sync point */
1173//		DXIW(TVO_IDX, 0x84);
1174//		DXIW(TVO_DATA, 0x01);
1175//		DXIW(TVO_IDX, 0x85);
1176//		DXIW(TVO_DATA, 0x00);
1177
1178		/* connect DAC1 to CON1, CRTC2/'DAC2' to CON2 (TVout mode) */
1179//		DXIW(OUTPUTCONN,0x0d);
1180	}
1181
1182	/* program new TVout mode */
1183	for (val = 0x00; val <= 0x3D; val++)
1184	{
1185/*		if (si->ps.card_type <= G400MAX)
1186		{
1187			i2c_maven_write(val, maventv_regs[val]);
1188		}
1189		else
1190*/		{
1191//			DXIW(TVO_IDX, val);
1192//			DXIW(TVO_DATA, maventv_regs[val]);
1193		}
1194	}
1195
1196	/* leave mode-program mode */
1197//	if (si->ps.card_type <= G400MAX) MAVW(PGM, 0x00);
1198//	else
1199//	{
1200//		DXIW(TVO_IDX, ENMAV_PGM);
1201//		DXIW(TVO_DATA, 0x00);
1202
1203		/* Select 2.0 Volt MAVEN DAC ref. so we have enough contrast/brightness range */
1204//		DXIW(GENIOCTRL, DXIR(GENIOCTRL) | 0x40);
1205//		DXIW(GENIODATA, 0x00);
1206//	}
1207
1208	/* setup CRTC2 timing */
1209	head2_set_timing(tv_target);
1210
1211	/* start whole thing if needed */
1212//	if (si->ps.card_type <= G400MAX) MAVW(RESYNC, 0x20);
1213
1214	return 0;
1215}
1216