1/*
2	Author:
3	Rudolf Cornelissen 4/2002-11/2005
4*/
5
6#define MODULE_BIT 0x00100000
7
8#include "nv_std.h"
9
10#define PRADR	0x88
11#define SCADR	0x8a
12#define WR		0x00
13#define RD		0x01
14
15enum
16{	// TVoutput mode to set
17	NOT_SUPPORTED = 0,
18	NTSC640_TST,
19	NTSC640,
20	NTSC800,
21	PAL800_TST,
22	PAL640,
23	PAL800,
24	NTSC720,
25	PAL720,
26	NTSC640_OS,
27	PAL800_OS
28};
29
30/* Dirk Thierbach's Macro setup for registers 0xda-0xfe.
31 * (also see http://sourceforge.net/projects/nv-tv-out/) */
32static uint8 BtNtscMacro0 [] = {
33  0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
34  0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x00,0x00};
35static uint8 BtNtscMacro1 [] = {
36  0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
37  0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x63,0x00};
38static uint8 BtNtscMacro2 [] = {
39  0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
40  0xbd,0x6c,0x31,0x92,0x32,0xdd,0xe3,0x00};
41static uint8 BtNtscMacro3 [] = {
42  0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
43  0xbd,0x66,0xb5,0x90,0xb2,0x7d,0xe3,0x00};
44
45static uint8 BtPalMacro0 [] = {
46  0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05,
47  0xd3,0x78,0xa2,0x25,0x54,0xa5,0x00,0x00};
48static uint8 BtPalMacro1 [] = {
49  0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05,
50  0xd3,0x78,0xa2,0x25,0x54,0xa5,0x63,0x00};
51
52static uint8 BT_set_macro (int std, int mode)
53{
54	uint8 stat;
55	uint8 buffer[21];
56
57	LOG(4,("Brooktree: Setting Macro:\n"));
58
59	if ((std < 0) | (std > 1) | (mode < 0) | (mode > 3))
60	{
61		LOG(4,("Brooktree: Non existing mode or standard selected, aborting.\n"));
62		return 0x80;
63	}
64
65	switch (std)
66	{
67	case 0:
68		/* NTSC */
69		switch (mode)
70		{
71		case 0:
72			/* disabled */
73			LOG(4,("Brooktree: NTSC, disabled\n"));
74			memcpy(&buffer[2], &BtNtscMacro0, 19);
75			break;
76		case 1:
77			/* enabled mode 1 */
78			LOG(4,("Brooktree: NTSC, mode 1\n"));
79			memcpy(&buffer[2], &BtNtscMacro1, 19);
80			break;
81		case 2:
82			/* enabled mode 2 */
83			LOG(4,("Brooktree: NTSC, mode 2\n"));
84			memcpy(&buffer[2], &BtNtscMacro2, 19);
85			break;
86		case 3:
87			/* enabled mode 3 */
88			LOG(4,("Brooktree: NTSC, mode 3\n"));
89			memcpy(&buffer[2], &BtNtscMacro3, 19);
90			break;
91		}
92		break;
93	case 1:
94		/* PAL */
95		switch (mode)
96		{
97		case 0:
98			/* disabled */
99			LOG(4,("Brooktree: PAL, disabled\n"));
100			memcpy(&buffer[2], &BtPalMacro0, 19);
101			break;
102		case 1:
103		case 2:
104		case 3:
105			/* enabled */
106			LOG(4,("Brooktree: PAL, enabled\n"));
107			memcpy(&buffer[2], &BtPalMacro1, 19);
108			break;
109		}
110		break;
111	}
112
113	buffer[0] = si->ps.tv_encoder.adress + WR;
114	/* select first register to write to */
115	buffer[1] = 0xda;
116
117	/* reset status */
118	i2c_flag_error (-1);
119
120	i2c_bstart(si->ps.tv_encoder.bus);
121	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
122	i2c_bstop(si->ps.tv_encoder.bus);
123	/* log on errors */
124	stat = i2c_flag_error(0);
125	if (stat)
126		LOG(4,("Brooktree: I2C errors occurred while setting Macro\n"));
127
128	return stat;
129}//end BT_set_macro.
130
131/*
132 see if a (possible) BT/CX chip resides at the given adress.
133 Return zero if no errors occurred.
134*/
135static uint8 BT_check (uint8 bus, uint8 adress)
136{
137	uint8 buffer[3];
138
139	buffer[0] = adress + WR;
140	/* set ESTATUS at b'00'; and enable bt chip-outputs
141	 * WARNING:
142	 * If bit0 = 0 is issued below (EN_OUT = disabled), the BT will lock SDA
143	 * after writing adress $A0 (setting EN_XCLK)!!!
144	 * Until a reboot the corresponding I2C bus will be inacessable then!!! */
145	buffer[1] = 0xc4;
146	/* fixme: if testimage 'was' active txbuffer[3] should become 0x05...
147	 * (currently this cannot be detected in a 'foolproof' way so don't touch...) */
148	/* (ESTATUS b'0x' means: RX ID and VERSION info later..) */
149	buffer[2] = 0x01;
150
151	/* reset status */
152	i2c_flag_error (-1);
153
154	/* do check */
155	i2c_bstart(bus);
156	i2c_writebuffer(bus, buffer, sizeof(buffer));
157	i2c_bstop(bus);
158	return i2c_flag_error(0);
159}
160
161/* identify chiptype */
162static uint8 BT_read_type (void)
163{
164	uint8 id, type, stat;
165	uint8 buffer[3];
166
167	/* Make sure a CX (Conexant) chip (if this turns out to be there) is set to
168	 * BT-compatibility mode! (This command will do nothing on a BT chip...) */
169	buffer[0] = si->ps.tv_encoder.adress + WR;
170	/* select CX reg. for BT-compatible readback, video still off */
171	buffer[1] = 0x6c;
172	/* set it up */
173	buffer[2] = 0x02;
174
175	/* reset status */
176	i2c_flag_error (-1);
177
178	i2c_bstart(si->ps.tv_encoder.bus);
179	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
180	i2c_bstop(si->ps.tv_encoder.bus);
181	/* abort on errors */
182	stat = i2c_flag_error(0);
183	if (stat) return stat;
184
185	/* Do actual readtype command */
186	i2c_bstart(si->ps.tv_encoder.bus);
187	/* issue I2C read command */
188	i2c_writebyte(si->ps.tv_encoder.bus, si->ps.tv_encoder.adress + RD);
189	/* receive 1 byte;
190	 * ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec). */
191	/* note:
192	 * While the BT's don't care, CX chips will block the SDA line if
193	 * an ACK gets sent! */
194	id = i2c_readbyte(si->ps.tv_encoder.bus, true);
195	i2c_bstop(si->ps.tv_encoder.bus);
196	/* abort on errors */
197	stat = i2c_flag_error(0);
198	if (stat) return stat;
199
200	/* check type to be supported one */
201	type = (id & 0xe0) >> 5;
202	if (type > 3)
203	{
204		LOG(4,("Brooktree: Found unsupported encoder type %d, aborting.\n", type));
205		return 0x80;
206	}
207
208	/* inform driver about TV encoder found */
209	si->ps.tvout = true;
210	si->ps.tv_encoder.type = BT868 + type;
211	si->ps.tv_encoder.version = id & 0x1f;
212
213	return stat;
214}
215
216bool BT_probe()
217{
218	uint8 bus;
219	bool btfound = false;
220	bool *i2c_bus = &(si->ps.i2c_bus0);
221
222	LOG(4,("Brooktree: Checking wired I2C bus(ses) for first possible TV encoder...\n"));
223	for (bus = 0; bus < 3; bus++)
224	{
225		if (i2c_bus[bus] && !btfound)
226		{
227			/* try primary adress on bus */
228			if (!BT_check(bus, PRADR))
229			{
230				btfound = true;
231				si->ps.tv_encoder.adress = PRADR;
232				si->ps.tv_encoder.bus = bus;
233			}
234			else
235			{
236				/* try secondary adress on bus */
237				if (!BT_check(bus, SCADR))
238				{
239					btfound = true;
240					si->ps.tv_encoder.adress = SCADR;
241					si->ps.tv_encoder.bus = bus;
242				}
243			}
244		}
245	}
246
247	/* identify exact TV encoder type */
248	if (btfound)
249	{
250		/* if errors are found, retry */
251		/* note:
252		 * NACK: occurs on some ASUS V7700 GeForce cards!
253		 * (apparantly the video-in chip or another chip resides at 'BT' adresses
254		 * there..) */
255		uint8 stat;
256		uint8 cnt = 0;
257		while ((stat = BT_read_type()) && (cnt < 3))
258		{
259			/* don't retry on unsupported chiptype */
260			if (stat == 0x80)
261			{
262				btfound = 0;
263				break;
264			}
265			cnt++;
266		}
267		if (stat & 0x7f)
268		{
269			LOG(4,("Brooktree: Too much errors occurred, aborting.\n"));
270			btfound = 0;
271		}
272	}
273
274	if (btfound)
275		LOG(4,("Brooktree: Found TV encoder on bus %d, adress $%02x\n",
276			si->ps.tv_encoder.bus, si->ps.tv_encoder.adress));
277	else
278		LOG(4,("Brooktree: No TV encoder Found\n"));
279
280	return btfound;
281}
282
283static uint8 BT_init_PAL640()
284{
285	uint8 stat;
286
287	uint8 buffer[35];
288
289	LOG(4,("Brooktree: Setting PAL 640x480 desktop mode\n"));
290
291	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
292	buffer[1] = 0x76;			//select first bt register to write to
293	buffer[2] = 0x60;
294	buffer[3] = 0x80;
295	buffer[4] = 0x8a;
296	buffer[5] = 0xa6;
297	buffer[6] = 0x68;
298	buffer[7] = 0xc1;
299	buffer[8] = 0x2e;
300	buffer[9] = 0xf2;
301	buffer[10] = 0x27;
302	buffer[11] = 0x00;
303	buffer[12] = 0xb0;
304	buffer[13] = 0x0a;
305	buffer[14] = 0x0b;
306	buffer[15] = 0x71;
307	buffer[16] = 0x5a;
308	buffer[17] = 0xe0;
309	buffer[18] = 0x36;
310	buffer[19] = 0x00;
311	buffer[20] = 0x50;
312	buffer[21] = 0x72;
313	buffer[22] = 0x1c;
314	buffer[23] = 0x8d;		//chip-pin CLKI is pixel clock (only non-default here!)
315	buffer[24] = 0x24;
316	buffer[25] = 0xf0;
317	buffer[26] = 0x58;
318	buffer[27] = 0x81;
319	buffer[28] = 0x49;
320	buffer[29] = 0x8c;
321	buffer[30] = 0x0c;
322	buffer[31] = 0x8c;
323	buffer[32] = 0x79;
324	buffer[33] = 0x26;
325	buffer[34] = 0x00;
326
327	/* reset status */
328	i2c_flag_error (-1);
329
330	i2c_bstart(si->ps.tv_encoder.bus);
331	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
332	i2c_bstop(si->ps.tv_encoder.bus);
333	/* log on errors */
334	stat = i2c_flag_error(0);
335	if (stat)
336		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL640\n"));
337
338	return stat;
339}//end BT_init_PAL640.
340
341static uint8 BT_init_PAL800()
342{
343	uint8 stat;
344
345	uint8 buffer[35];
346
347	LOG(4,("Brooktree: Setting PAL 800x600 desktop mode\n"));
348
349	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
350	buffer[1] = 0x76;			//select first bt register to write to
351	buffer[2] = 0x00;
352	buffer[3] = 0x20;
353	buffer[4] = 0xaa;
354	buffer[5] = 0xca;
355	buffer[6] = 0x9a;
356	buffer[7] = 0x0d;
357	buffer[8] = 0x29;
358	buffer[9] = 0xfc;
359	buffer[10] = 0x39;
360	buffer[11] = 0x00;
361	buffer[12] = 0xc0;
362	buffer[13] = 0x8c;
363	buffer[14] = 0x03;
364	buffer[15] = 0xee;
365	buffer[16] = 0x5f;
366	buffer[17] = 0x58;
367	buffer[18] = 0x3a;
368	buffer[19] = 0x66;
369	buffer[20] = 0x96;
370	buffer[21] = 0x00;
371	buffer[22] = 0x00;
372	buffer[23] = 0x90;		//chip-pin CLKI is pixel clock (only non-default here!)
373	buffer[24] = 0x24;
374	buffer[25] = 0xf0;
375	buffer[26] = 0x57;
376	buffer[27] = 0x80;
377	buffer[28] = 0x48;
378	buffer[29] = 0x8c;
379	buffer[30] = 0x18;
380	buffer[31] = 0x28;
381	buffer[32] = 0x87;
382	buffer[33] = 0x1f;
383	buffer[34] = 0x00;
384
385	/* reset status */
386	i2c_flag_error (-1);
387
388	i2c_bstart(si->ps.tv_encoder.bus);
389	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
390	i2c_bstop(si->ps.tv_encoder.bus);
391	/* log on errors */
392	stat = i2c_flag_error(0);
393	if (stat)
394		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n"));
395
396	return stat;
397}//end BT_init_PAL800.
398
399static uint8 BT_init_NTSC640()
400{
401	uint8 stat;
402
403	uint8 buffer[35];
404
405	LOG(4,("Brooktree: Setting NTSC 640x480 desktop mode\n"));
406
407	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
408	buffer[1] = 0x76;			//select first bt register to write to
409	buffer[2] = 0x00;
410	buffer[3] = 0x80;
411	buffer[4] = 0x84;
412	buffer[5] = 0x96;
413	buffer[6] = 0x60;
414	buffer[7] = 0x7d;
415	buffer[8] = 0x22;
416	buffer[9] = 0xd4;
417	buffer[10] = 0x27;
418	buffer[11] = 0x00;
419	buffer[12] = 0x10;
420	buffer[13] = 0x7e;
421	buffer[14] = 0x03;
422	buffer[15] = 0x58;
423	buffer[16] = 0x4b;
424	buffer[17] = 0xe0;
425	buffer[18] = 0x36;
426	buffer[19] = 0x92;
427	buffer[20] = 0x54;
428	buffer[21] = 0x0e;
429	buffer[22] = 0x88;
430	buffer[23] = 0x8c;		//chip-pin CLKI is pixel clock (only non-default here!)
431	buffer[24] = 0x0a;
432	buffer[25] = 0xe5;
433	buffer[26] = 0x76;
434	buffer[27] = 0x79;
435	buffer[28] = 0x44;
436	buffer[29] = 0x85;
437	buffer[30] = 0x00;
438	buffer[31] = 0x00;
439	buffer[32] = 0x80;
440	buffer[33] = 0x20;
441	buffer[34] = 0x00;
442
443	/* reset status */
444	i2c_flag_error (-1);
445
446	i2c_bstart(si->ps.tv_encoder.bus);
447	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
448	i2c_bstop(si->ps.tv_encoder.bus);
449	/* log on errors */
450	stat = i2c_flag_error(0);
451	if (stat)
452		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640\n"));
453
454	return stat;
455}//end BT_init_NTSC640.
456
457static uint8 BT_init_NTSC800()
458{
459	uint8 stat;
460
461	uint8 buffer[35];
462
463	LOG(4,("Brooktree: Setting NTSC 800x600 desktop mode\n"));
464
465	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
466	buffer[1] = 0x76;			//select first bt register to write to
467	buffer[2] = 0xa0;
468	buffer[3] = 0x20;
469	buffer[4] = 0xb6;
470	buffer[5] = 0xce;
471	buffer[6] = 0x84;
472	buffer[7] = 0x55;
473	buffer[8] = 0x20;
474	buffer[9] = 0xd8;
475	buffer[10] = 0x39;
476	buffer[11] = 0x00;
477	buffer[12] = 0x70;
478	buffer[13] = 0x42;
479	buffer[14] = 0x03;
480	buffer[15] = 0xdf;
481	buffer[16] = 0x56;
482	buffer[17] = 0x58;
483	buffer[18] = 0x3a;
484	buffer[19] = 0xcd;
485	buffer[20] = 0x9c;
486	buffer[21] = 0x14;
487	buffer[22] = 0x3b;
488	buffer[23] = 0x91;		//chip-pin CLKI is pixel clock (only non-default here!)
489	buffer[24] = 0x0a;
490	buffer[25] = 0xe5;
491	buffer[26] = 0x74;
492	buffer[27] = 0x77;
493	buffer[28] = 0x43;
494	buffer[29] = 0x85;
495	buffer[30] = 0xba;
496	buffer[31] = 0xe8;
497	buffer[32] = 0xa2;
498	buffer[33] = 0x17;
499	buffer[34] = 0x00;
500
501	/* reset status */
502	i2c_flag_error (-1);
503
504	i2c_bstart(si->ps.tv_encoder.bus);
505	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
506	i2c_bstop(si->ps.tv_encoder.bus);
507	/* log on errors */
508	stat = i2c_flag_error(0);
509	if (stat)
510		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n"));
511
512	return stat;
513}//end BT_init_NTSC800.
514
515static uint8 BT_init_PAL720()
516{
517	uint8 stat;
518
519	uint8 buffer[35];
520
521	LOG(4,("Brooktree: Setting PAL 720x576 overscanning DVD mode\n"));
522
523	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
524	buffer[1] = 0x76;			//select first bt register to write to
525	buffer[2] = 0xf0;
526	buffer[3] = 0xd0;
527	buffer[4] = 0x82;
528	buffer[5] = 0x9c;
529	buffer[6] = 0x5a;
530	buffer[7] = 0x31;
531	buffer[8] = 0x16;
532	buffer[9] = 0x22;
533	buffer[10] = 0xa6;
534	buffer[11] = 0x00;
535	buffer[12] = 0x78;
536	buffer[13] = 0x93;
537	buffer[14] = 0x03;
538	buffer[15] = 0x71;
539	buffer[16] = 0x2a;
540	buffer[17] = 0x40;
541	buffer[18] = 0x0a;
542	buffer[19] = 0x00;
543	buffer[20] = 0x50;
544	buffer[21] = 0x55;
545	buffer[22] = 0x55;
546	buffer[23] = 0x8c;		//chip-pin CLKI is pixel clock (only non-default here!)
547	buffer[24] = 0x24;
548	buffer[25] = 0xf0;
549	buffer[26] = 0x59;
550	buffer[27] = 0x82;
551	buffer[28] = 0x49;
552	buffer[29] = 0x8c;
553	buffer[30] = 0x8e;
554	buffer[31] = 0xb0;
555	buffer[32] = 0xe6;
556	buffer[33] = 0x28;
557	buffer[34] = 0x00;
558
559	/* reset status */
560	i2c_flag_error (-1);
561
562	i2c_bstart(si->ps.tv_encoder.bus);
563	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
564	i2c_bstop(si->ps.tv_encoder.bus);
565	/* log on errors */
566	stat = i2c_flag_error(0);
567	if (stat)
568		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL720\n"));
569
570	return stat;
571}//end BT_init_PAL720.
572
573static uint8 BT_init_NTSC720()
574{
575	uint8 stat;
576
577	uint8 buffer[35];
578
579	LOG(4,("Brooktree: Setting NTSC 720x480 overscanning DVD mode\n"));
580
581	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
582	buffer[1] = 0x76;		//select first bt register to write to.
583	buffer[2] = 0xf0;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
584	buffer[3] = 0xd0;		//lsb h_active: h_active = 720 pixels wide port
585	buffer[4] = 0x83;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
586	buffer[5] = 0x98;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
587	buffer[6] = 0x5e;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
588
589	//How to find the correct values for h_blank_o and v_blank_o:
590	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
591	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
592	//    horizontal position is about OK;
593	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
594	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
595	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
596	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
597	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
598
599	if (si->ps.tv_encoder.type >= CX25870)//set CX value
600	{
601		/* confirmed on NV11 using 4:3 TV and 16:9 TV */
602		buffer[7] = 0x0c;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
603							//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
604	}
605	else //set BT value
606	{
607		/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
608		buffer[7] = 0x28;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
609							//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
610	}
611	buffer[8] = 0x18;	//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
612
613	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
614	buffer[10] = 0x26;		//lsn = msn h_clk_o;
615							//b4-5 = msbits h_active;
616							//b7 = b8 v_avtive_o.
617	buffer[11] = 0x00;		//h_fract is always 0.
618	buffer[12] = 0x78;		//lsb h_clk_i: h_clk_i is horizontal total = 888.
619	buffer[13] = 0x90; 	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
620	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
621						//try-out: b3 = msn h_blank_i;
622							//b4 = vblankdly is always 0.
623	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
624	buffer[16] = 0x1a; 	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
625						//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
626	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
627	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
628							//b3-2 = msn v_active_i;
629							//b5-4 = ylpf = 3;
630							//b7-6 = clpf = 0.
631	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
632	buffer[20] = 0x50;		//b5-0 = msn v_scale;
633						//scope: tuned. b7-6 = msn h_blank_o.
634							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
635	buffer[21] = 0x98;		//lsb PLL fract: PLL fract = 0x6e98
636	buffer[22] = 0x6e;		//msb PLL fract
637	buffer[23] = 0x8c;		//b5-0 = PLL int: PLL int = 0x0c;
638							//b6 = by_pll: by_pll = 0;
639							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
640	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
641							//b1 = setup = 1 for NTSC;
642							//b2 = 625line = 0 for NTSC;
643							//b3 = vsync_dur = 1 for NTSC;
644							//b4 = dic_screset is always 0;
645							//b5 = pal_md = 0 for NTSC;
646							//b6 = eclip is always 0;
647							//b7 = reserved (en_scart) is always 0.
648	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
649	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
650	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
651	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
652	buffer[29] = 0x85;		//my: y $85 for NTSC
653	buffer[30] = 0x3c;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
654	buffer[31] = 0x91;		//msc = $20c2913c
655	buffer[32] = 0xc2;
656	buffer[33] = 0x20;		//msb msc.
657	buffer[34] = 0x00;		//phase_off always $00
658
659	/* reset status */
660	i2c_flag_error (-1);
661
662	i2c_bstart(si->ps.tv_encoder.bus);
663	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
664	i2c_bstop(si->ps.tv_encoder.bus);
665	/* log on errors */
666	stat = i2c_flag_error(0);
667	if (stat)
668		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC720\n"));
669
670	return stat;
671}//end BT_init_NTSC720.
672
673static uint8 BT_init_PAL800_OS()
674{
675	uint8 stat;
676
677	uint8 buffer[35];
678
679	LOG(4,("Brooktree: Setting PAL 800x600 overscanning VCD mode\n"));
680
681	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
682	buffer[1] = 0x76;		//select first bt register to write to.
683	buffer[2] = 0x60;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
684	buffer[3] = 0x20;		//lsb h_active: h_active = 800 pixels wide port
685	buffer[4] = 0x8b;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 64.0uS = 4.70uS for PAL
686	buffer[5] = 0xa5;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 64.0uS = 5.6uS for PAL
687	buffer[6] = 0x6b;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 64.0uS = 7.97uS for PAL
688
689	//How to find the correct values for h_blank_o and v_blank_o:
690	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
691	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
692	//    horizontal position is about OK;
693	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
694	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
695	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
696	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
697	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
698
699	if (si->ps.tv_encoder.type >= CX25870)//set CX value
700	{
701		/* confirmed on NV11 using 4:3 TV and 16:9 TV */
702		buffer[7] = 0xf0;
703		buffer[8] = 0x17;
704	}
705	else //set BT value
706	{
707		/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
708		buffer[7] = 0xd0;//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
709						//(guideline for initial setting: (h_blank_o / h_clk_0) * 64.0uS = 10.0uS for PAL)
710		buffer[8] = 0x18;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
711	}
712
713	buffer[9] = 0x2e;		//v_active_o: = (active output lines + 2) / field (on TV)
714	buffer[10] = 0xb7;		//lsn = msn h_clk_o;
715							//b4-5 = msbits h_active;
716							//b7 = b8 v_avtive_o.
717	buffer[11] = 0x00;		//h_fract is always 0.
718	buffer[12] = 0xb0;		//lsb h_clk_i: h_clk_i is horizontal total = 944.
719
720	if (si->ps.tv_encoder.type >= CX25870)//set CX value
721		buffer[13] = 0x20;
722	else //set BT value
723		buffer[13] = 0x14;//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
724
725	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
726					 	//try-out: b3 = msn h_blank_i;
727							//b4 = vblankdly is always 0.
728	buffer[15] = 0x71;		//lsb v_lines_i: v_lines_i = 625
729
730	if (si->ps.tv_encoder.type >= CX25870)//set CX value
731		buffer[16] = 0x08;
732	else				//set BT value
733		buffer[16] = 0x2a;//try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
734					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
735
736	buffer[17] = 0x58;		//lsb v_active_i: v_active_i = 600
737	buffer[18] = 0x3a;		//b1-0 = msn v_lines_i;
738							//b3-2 = msn v_active_i;
739							//b5-4 = ylpf = 3;
740							//b7-6 = clpf = 0.
741	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
742	buffer[20] = 0x10;		//b5-0 = msn v_scale;
743						//scope: tuned. b7-6 = msn h_blank_o.
744							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 50Hz)
745	buffer[21] = 0x72;		//lsb PLL fract: PLL fract = 0x1c72
746	buffer[22] = 0x1c;		//msb PLL fract
747	buffer[23] = 0x8d;		//b5-0 = PLL int: PLL int = 0x0d;
748							//b6 = by_pll: by_pll = 0;
749							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
750	buffer[24] = 0x24;		//b0 = ni_out is always 0;
751							//b1 = setup = 0 for PAL;
752							//b2 = 625line = 1 for PAL;
753							//b3 = vsync_dur = 0 for PAL;
754							//b4 = dic_screset is always 0;
755							//b5 = pal_md = 1 for PAL;
756							//b6 = eclip is always 0;
757							//b7 = reserved (en_scart) is always 0.
758	buffer[25] = 0xf0;		//sync_amp $f0 for PAL
759	buffer[26] = 0x57;		//bst_amp $57-$58 for PAL
760	buffer[27] = 0x80;		//mcr: r-y $80-$81 for PAL
761	buffer[28] = 0x48;		//mcb: b-y $48-$49 for PAL
762	buffer[29] = 0x8c;		//my: y $8c for PAL
763	buffer[30] = 0x31;		//lsb msc: msc b31-0: PAL formula: ((4433619 / pixelclk) * 2^32) = MSC
764	buffer[31] = 0x8c;		//msc = $26798c31
765	buffer[32] = 0x79;
766	buffer[33] = 0x26;		//msb msc.
767	buffer[34] = 0x00;		//phase_off always $00
768
769	/* reset status */
770	i2c_flag_error (-1);
771
772	i2c_bstart(si->ps.tv_encoder.bus);
773	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
774	i2c_bstop(si->ps.tv_encoder.bus);
775	/* log on errors */
776	stat = i2c_flag_error(0);
777	if (stat)
778		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800 OS\n"));
779
780	return stat;
781}//end BT_init_PAL800_OS.
782
783static uint8 BT_init_NTSC640_OS()
784{
785	uint8 stat;
786
787	uint8 buffer[35];
788
789	LOG(4,("Brooktree: Setting NTSC 640x480 overscanning VCD mode\n"));
790
791	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
792	buffer[1] = 0x76;		//select first bt register to write to.
793	buffer[2] = 0x20;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
794	buffer[3] = 0x80;		//lsb h_active: h_active = 640 pixels wide port
795	buffer[4] = 0x74;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
796	buffer[5] = 0x83;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
797	buffer[6] = 0x44;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
798
799	//How to find the correct values for h_blank_o and v_blank_o:
800	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
801	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
802	//    horizontal position is about OK;
803	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
804	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
805	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
806	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
807	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
808
809	buffer[7] = 0xf7;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV:
810						//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
811
812	if (si->ps.tv_encoder.type >= CX25870)//set CX value
813		buffer[8] = 0x1d;
814	else //set BT value
815		buffer[8] = 0x1c;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
816
817	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
818	buffer[10] = 0x26;		//lsn = msn h_clk_o;
819							//b4-5 = msbits h_active;
820							//b7 = b8 v_avtive_o.
821	buffer[11] = 0x00;		//h_fract is always 0.
822	buffer[12] = 0x10;		//lsb h_clk_i: h_clk_i is horizontal total = 784.
823	buffer[13] = 0x14;	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
824	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
825						//try-out: b3 = msn h_blank_i;
826							//b4 = vblankdly is always 0.
827	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
828	buffer[16] = 0x18;	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
829					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
830	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
831	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
832							//b3-2 = msn v_active_i;
833							//b5-4 = ylpf = 3;
834							//b7-6 = clpf = 0.
835	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
836	buffer[20] = 0x10;		//b5-0 = msn v_scale;
837						//scope: tuned. b7-6 = msn h_blank_o.
838							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
839	buffer[21] = 0xdb;		//lsb PLL fract: PLL fract = 0xf9db
840	buffer[22] = 0xf9;		//msb PLL fract
841	buffer[23] = 0x8a;		//b5-0 = PLL int: PLL int = 0x0a;
842							//b6 = by_pll: by_pll = 0;
843							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
844	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
845							//b1 = setup = 1 for NTSC;
846							//b2 = 625line = 0 for NTSC;
847							//b3 = vsync_dur = 1 for NTSC;
848							//b4 = dic_screset is always 0;
849							//b5 = pal_md = 0 for NTSC;
850							//b6 = eclip is always 0;
851							//b7 = reserved (en_scart) is always 0.
852	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
853	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
854	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
855	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
856	buffer[29] = 0x85;		//my: y $85 for NTSC
857	buffer[30] = 0x37;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
858	buffer[31] = 0x12;		//msc = $251b1237
859	buffer[32] = 0x1b;
860	buffer[33] = 0x25;		//msb msc.
861	buffer[34] = 0x00;		//phase_off always $00
862
863	/* reset status */
864	i2c_flag_error (-1);
865
866	i2c_bstart(si->ps.tv_encoder.bus);
867	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
868	i2c_bstop(si->ps.tv_encoder.bus);
869	/* log on errors */
870	stat = i2c_flag_error(0);
871	if (stat)
872		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640 OS\n"));
873
874	return stat;
875}//end BT_init_NTSC640_OS.
876
877static uint8 BT_testsignal(void)
878{
879	uint8 stat;
880
881	uint8 buffer[3];
882
883	LOG(4,("Brooktree: Enabling testsignal\n"));
884
885	buffer[0] = si->ps.tv_encoder.adress + WR;
886	/* select bt register for enabling colorbars and outputs */
887	buffer[1] = 0xc4;
888	/* issue the actual command */
889	buffer[2] = 0x05;
890
891	/* reset status */
892	i2c_flag_error (-1);
893
894	i2c_bstart(si->ps.tv_encoder.bus);
895	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
896	i2c_bstop(si->ps.tv_encoder.bus);
897	/* log on errors */
898	stat = i2c_flag_error(0);
899	if (stat)
900		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
901
902	return stat;
903}//end BT_testsignal.
904
905static uint8 BT_setup_output(uint8 monstat, uint8 output, uint8 ffilter)
906{
907	uint8 stat;
908
909	uint8 buffer[7];
910
911	buffer[0] = si->ps.tv_encoder.adress + WR;
912	/* select first TV config register to write */
913	buffer[1] = 0xc6;
914	/* input is 24bit mpx'd RGB, BLANK = out, sync = act. hi */
915	buffer[2] = 0x98;
916	/* disable all filters, exept flicker filter */
917	buffer[3] = 0x98;
918	if (!ffilter)
919	{
920		/* disable flicker filter */
921		buffer[3] = 0xc0;
922		LOG(4,("Brooktree: Disabling flickerfilter\n"));
923	}
924	else
925		LOG(4,("Brooktree: Enabling flickerfilter\n"));
926
927	/* (disable filters) */
928	buffer[4] = 0xc0;
929	/* (disable filters) */
930	buffer[5] = 0xc0;
931	switch (output)
932	/* Description of ELSA Erazor III hardware layout:
933	 * (This is the default (recommended) layout by NVIDIA)
934	 * DAC A = CVBS
935	 * DAC B = C (chrominance)
936	 * DAC C = Y (luminance) */
937
938	/* Description of Diamond VIPER550:
939	 * DAC A = Not connected
940	 * DAC B = C (chrominance)
941	 * DAC C = Y (luminance)
942	 * To be able to connect to CVBS TV's a special cable is supplied:
943	 * This cable connects the Y (DAC C) output to the TV CVBS input. */
944	{
945	case 1:
946		LOG(4,("Brooktree: Forcing both Y/C and CVBS signals where supported by hardware\n"));
947		buffer[6] = 0x18;	// Y/C and CVBS out if all ports implemented
948							// in hardware, else only Y/C or CVBS out.
949		break;
950	case 2:
951		LOG(4,("Brooktree: Forcing CVBS signals on all outputs\n"));
952		buffer[6] = 0x00;	// put CVBS on all outputs. Used for cards
953		break;				// with only Y/C out and 'translation cable'.
954	default:
955		LOG(4,("Brooktree: Outputting signals according to autodetect status:\n"));
956		switch (monstat)	// only 'autodetect' remains...
957		{
958		case 1:
959			LOG(4,("Brooktree: Only Y connected, outputting CVBS on all outputs\n"));
960			buffer[6] = 0x00;	//only Y connected: must be CVBS!
961			break;
962		case 2:
963			LOG(4,("Brooktree: Only C connected, outputting CVBS on all outputs\n"));
964			buffer[6] = 0x00;	//only C connected: must be CVBS!
965			break;				//(though cable is wired wrong...)
966		case 5:
967			LOG(4,("Brooktree: CVBS and only Y connected, outputting CVBS on all outputs\n"));
968			buffer[6] = 0x00;	//CVBS and only Y connected: 2x CVBS!
969			break;			   	//(officially not supported...)
970		case 6:
971			LOG(4,("Brooktree: CVBS and only C connected, outputting CVBS on all outputs\n"));
972			buffer[6] = 0x00;	//CVBS and only C connected: 2x CVBS!
973			break;			   	//(officially not supported...)
974		default:
975			LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n"));
976			buffer[6] = 0x18;	//nothing, or
977							 	//Y/C only, or
978							 	//CVBS only (but on CVBS output), or
979							 	//Y/C and CVBS connected:
980							 	//So activate recommended signals.
981		}
982	}
983
984	/* reset status */
985	i2c_flag_error (-1);
986
987	i2c_bstart(si->ps.tv_encoder.bus);
988	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
989	i2c_bstop(si->ps.tv_encoder.bus);
990	/* log on errors */
991	stat = i2c_flag_error(0);
992	if (stat)
993		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
994
995	return stat;
996}//end BT_setup_output.
997
998static uint8 BT_setup_hphase(uint8 mode)
999{
1000	uint8 stat, hoffset;
1001
1002	uint8 buffer[7];
1003
1004	LOG(4,("Brooktree: Tuning horizontal phase\n"));
1005
1006	/* CX needs timing reset (advised on BT also), first 1mS delay needed! */
1007	snooze(1000);
1008
1009	/* values below are all tested on TNT1, TNT2 and GeForce2MX */
1010	buffer[0] = si->ps.tv_encoder.adress + WR;
1011	/* select first TV output timing register to write */
1012	buffer[1] = 0x6c;
1013	/* turn on active video & generate timing reset on CX chips! */
1014	buffer[2] = 0x86;
1015	/* (set fail save values...) */
1016	buffer[3] = 0x00;		//set default horizontal sync offset
1017	buffer[4] = 0x02;		//set default horizontal sync width
1018	buffer[5] = 0x00;		//set default vertical sync offset
1019
1020	/* do specific timing setup for all chips and modes: */
1021	switch (si->ps.card_type)
1022	{
1023	case NV05:
1024	case NV05M64:
1025	case NV15:
1026		/* confirmed TNT2, TNT2M64, GeForce2Ti.
1027		 * (8 pixels delayed hpos, so picture more to the right) */
1028		hoffset = 8;
1029		break;
1030	default:
1031		/* confirmed TNT1, GeForce256, GeForce2MX.
1032		 * (std hpos)
1033		 * NOTE: It might be that GeForce needs TNT2 offset:
1034		 * for now CX chips get seperate extra offset, until sure.
1035		 * (CX is only found AFAIK on GeForce cards, no BT tested
1036		 * on GeForce yet. CH was tested on GeForce and seemed to
1037		 * indicate TNT1 offset was needed.) */
1038		hoffset = 0;
1039		break;
1040	}
1041
1042	switch (mode)
1043	{
1044	case NTSC640_TST:
1045	case NTSC640:
1046		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1047		/* confirmed on TNT1 with BT869 using 4:3 TV and 16:9 TV */
1048		buffer[3] = (0x1e + hoffset);	//set horizontal sync offset
1049		break;
1050	case NTSC800:
1051		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1052		buffer[3] = (0xe1 + hoffset);	//set horizontal sync offset
1053		buffer[4] = 0xc2;
1054		//Vsync offset reg. does not exist on CX: mode is checked and OK.
1055		buffer[5] = 0x40;				//set VSync offset (on BT's only)
1056		break;
1057	case PAL640:
1058		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1059		buffer[3] = (0xa8 + hoffset);
1060		break;
1061	case PAL800_TST:
1062	case PAL800:
1063		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1064		buffer[3] = (0x2c + hoffset);
1065		break;
1066	case NTSC720:
1067		if (si->ps.tv_encoder.type >= CX25870)
1068			buffer[3] = (0xb2 + hoffset); //set horizontal sync offset CX
1069		else
1070			buffer[3] = (0xd0 + hoffset); //set horizontal sync offset BT
1071		buffer[4] = 0xff;				//hsync width = max:
1072		break;							//to prevent vertical image 'shivering'.
1073	case PAL720:
1074		buffer[3] = (0xd4 + hoffset);
1075		buffer[4] = 0xff;
1076		break;
1077	case NTSC640_OS:
1078		buffer[3] = (0xc8 + hoffset);
1079		buffer[4] = 0xff;
1080		break;
1081	case PAL800_OS:
1082		if (si->ps.tv_encoder.type >= CX25870)
1083			buffer[3] = (0x78 + hoffset); //set horizontal sync offset CX
1084		else
1085			buffer[3] = (0xc4 + hoffset); //set horizontal sync offset BT
1086		buffer[4] = 0xff;
1087		break;
1088	default: //nothing to be done here...
1089		break;
1090	}
1091
1092	buffer[6] = 0x01;		//set default vertical sync width
1093
1094	/* reset status */
1095	i2c_flag_error (-1);
1096
1097	i2c_bstart(si->ps.tv_encoder.bus);
1098	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1099	i2c_bstop(si->ps.tv_encoder.bus);
1100	/* log on errors */
1101	stat = i2c_flag_error(0);
1102	if (stat)
1103		LOG(4,("Brooktree: I2C errors occurred while setting up h_phase\n"));
1104
1105	return stat;
1106}//end BT_setup_hphase.
1107
1108static uint8 BT_read_monstat(uint8* monstat)
1109{
1110	uint8 stat;
1111	uint8 buffer[3];
1112
1113	/* make sure we have the recommended failsafe selected */
1114	*monstat = 0;
1115
1116	LOG(4,("Brooktree: Autodetecting connected output devices\n"));
1117
1118	/* set BT to return connection status in ESTATUS on next read CMD: */
1119	buffer[0] = si->ps.tv_encoder.adress + WR;
1120	/* set ESTATUS at b'01' (return conn.stat.) */
1121	buffer[1] = 0xc4;
1122	/* and leave chip outputs on. */
1123	buffer[2] = 0x41;
1124
1125	/* reset status */
1126	i2c_flag_error (-1);
1127
1128	i2c_bstart(si->ps.tv_encoder.bus);
1129	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1130	i2c_bstop(si->ps.tv_encoder.bus);
1131	/* log on errors */
1132	stat = i2c_flag_error(0);
1133	if (stat)
1134	{
1135		LOG(4,("Brooktree: I2C errors occurred while reading connection status (1)\n"));
1136		return stat;
1137	}
1138
1139	/* do actual read connection status: */
1140	buffer[0] = si->ps.tv_encoder.adress + WR;
1141	/* select register with CHECK_STAT CMD */
1142	buffer[1] = 0xba;
1143	/* issue actual command. */
1144	buffer[2] = 0x40;
1145
1146	i2c_bstart(si->ps.tv_encoder.bus);
1147	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1148	i2c_bstop(si->ps.tv_encoder.bus);
1149	/* log on errors */
1150	stat = i2c_flag_error(0);
1151	if (stat)
1152	{
1153		LOG(4,("Brooktree: I2C errors occurred while reading connection status (2)\n"));
1154		return stat;
1155	}
1156
1157	/* CX: Wait 600uS for signals to stabilize (see datasheet) */
1158	/* warning, note:
1159	 * datasheet is in error! 60mS needed!! */
1160	snooze(60000);
1161
1162	/* read back updated connection status: */
1163	buffer[0] = si->ps.tv_encoder.adress + RD;
1164
1165	/* transmit 1 byte */
1166	i2c_bstart(si->ps.tv_encoder.bus);
1167	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 1);
1168
1169	/* receive 1 byte */
1170	/* ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec)
1171	 * While the BT's don't care, CX chips will block the SDA line if an ACK gets sent! */
1172	buffer[0] = 1;
1173	i2c_readbuffer(si->ps.tv_encoder.bus, buffer, 1);
1174	i2c_bstop(si->ps.tv_encoder.bus);
1175	/* log on errors */
1176	stat = i2c_flag_error(0);
1177	if (stat)
1178	{
1179		LOG(4,("Brooktree: I2C errors occurred while reading connection status (3)\n"));
1180		return stat;
1181	}
1182
1183	*monstat = ((buffer[0] & 0xe0) >> 5);
1184	LOG(4,("Brooktree: TV output monitor status = %d\n", *monstat));
1185
1186	/* instruct BT to go back to normal operation: */
1187	buffer[0] = si->ps.tv_encoder.adress + WR;
1188	/* select register with CHECK_STAT CMD */
1189	buffer[1] = 0xba;
1190	/* issue actual command. */
1191	buffer[2] = 0x00;
1192
1193	i2c_bstart(si->ps.tv_encoder.bus);
1194	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1195	i2c_bstop(si->ps.tv_encoder.bus);
1196	/* log on errors */
1197	stat = i2c_flag_error(0);
1198	if (stat)
1199	{
1200		LOG(4,("Brooktree: I2C errors occurred while reading connection status (4)\n"));
1201		return stat;
1202	}
1203
1204	return stat;
1205}//end BT_read_monstat.
1206
1207static uint8 BT_killclk_blackout(void)
1208{
1209	uint8 stat;
1210
1211	uint8 buffer[4];
1212
1213	LOG(4,("Brooktree: Killing clock and/or blacking out (blocking output signals)\n"));
1214
1215	/* reset status */
1216	i2c_flag_error (-1);
1217
1218	if (si->ps.tv_encoder.type <= BT869) //BT...
1219	{
1220		/* Only disable external pixelclock input on BT's.
1221		 * CX chips will lock the bus if you do this.
1222		 * (It looks like the external pixelclock is always OK as long as a valid
1223		 * mode is programmed for the TVout chip. This means that disabling the use
1224		 * of this clock is not needed anyway.
1225		 * If you do disable this input, this pixelclock will rise to about 60Mhz BTW..) */
1226
1227		/* disable use of external pixelclock source... */
1228		/* (should prevent BT for being 'overclocked' by RIVA in VGA-only mode...) */
1229		buffer[0] = si->ps.tv_encoder.adress + WR;
1230		/* select BT register for setting EN_XCLK */
1231		buffer[1] = 0xa0;
1232		/* clear it */
1233		buffer[2] = 0x00;
1234
1235		i2c_bstart(si->ps.tv_encoder.bus);
1236		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
1237		i2c_bstop(si->ps.tv_encoder.bus);
1238		/* log on errors */
1239		stat = i2c_flag_error(0);
1240		if (stat)
1241		{
1242			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-BT)\n"));
1243			return stat;
1244		}
1245	}
1246	else //CX...
1247	{
1248		/* Disable CX video out (or wild output will be seen on TV..) */
1249		buffer[0] = si->ps.tv_encoder.adress + WR;
1250		/* select register in CX */
1251		buffer[1] = 0x6c;
1252		/* disable active video out. */
1253		buffer[2] = 0x02;
1254
1255		i2c_bstart(si->ps.tv_encoder.bus);
1256		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
1257		i2c_bstop(si->ps.tv_encoder.bus);
1258		/* log on errors */
1259		stat = i2c_flag_error(0);
1260		if (stat)
1261		{
1262			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-CX)\n"));
1263			return stat;
1264		}
1265	}
1266
1267	/* black-out TVout while outputs are enabled... */
1268	buffer[0] = si->ps.tv_encoder.adress + WR;
1269	/* select first TV config register to write */
1270	buffer[1] = 0xc4;
1271	/* disable testimage while outputs remain enabled */
1272	buffer[2] = 0x01;
1273	/* input is 24bit mpx'd RGB, BLANK = in, sync = act. hi */
1274	buffer[3] = 0x18;
1275
1276	i2c_bstart(si->ps.tv_encoder.bus);
1277	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1278	i2c_bstop(si->ps.tv_encoder.bus);
1279	/* log on errors */
1280	stat = i2c_flag_error(0);
1281	if (stat)
1282	{
1283		LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (2)\n"));
1284		return stat;
1285	}
1286
1287	return stat;
1288}//end BT_killclk_blackout.
1289
1290uint8 BT_dpms(bool display)
1291{
1292	uint8 stat;
1293
1294	uint8 buffer[3];
1295
1296	LOG(4,("Brooktree: setting DPMS: "));
1297
1298	/* reset status */
1299	i2c_flag_error (-1);
1300
1301	/* shutdown all analog electronics... */
1302	buffer[0] = si->ps.tv_encoder.adress + WR;
1303	/* select first TV config register to write */
1304	buffer[1] = 0xba;
1305	if (display)
1306	{
1307		/* enable all DACs */
1308		buffer[2] = 0x00;
1309		LOG(4,("display on\n"));
1310	}
1311	else
1312	{
1313		/* shutdown all DACs */
1314		buffer[2] = 0x10;
1315		LOG(4,("display off\n"));
1316	}
1317
1318	i2c_bstart(si->ps.tv_encoder.bus);
1319	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
1320	i2c_bstop(si->ps.tv_encoder.bus);
1321	/* log on errors */
1322	stat = i2c_flag_error(0);
1323	if (stat)
1324	{
1325		LOG(4,("Brooktree: I2C errors occurred while setting DPMS\n"));
1326		return stat;
1327	}
1328
1329	return stat;
1330}//end BT_dpms.
1331
1332uint8 BT_check_tvmode(display_mode target)
1333{
1334	uint8 status = NOT_SUPPORTED;
1335	uint32 mode = ((target.timing.h_display) | ((target.timing.v_display) << 16));
1336
1337	switch (mode)
1338	{
1339	case (640 | (480 << 16)):
1340		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1341			status = PAL640;
1342		if ((target.flags & TV_BITS) == TV_NTSC)
1343		{
1344			if (!(target.flags & TV_VIDEO)) status = NTSC640;
1345			else status = NTSC640_OS;
1346		}
1347		break;
1348	case (768 | (576 << 16)):
1349		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1350			status = PAL800_OS;
1351		break;
1352	case (800 | (600 << 16)):
1353		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1354			status = PAL800;
1355		if (((target.flags & TV_BITS) == TV_NTSC) && (!(target.flags & TV_VIDEO)))
1356			status = NTSC800;
1357		break;
1358	case (720 | (480 << 16)):
1359		if (((target.flags & TV_BITS) == TV_NTSC) && (target.flags & TV_VIDEO))
1360			status = NTSC720;
1361		break;
1362	case (720 | (576 << 16)):
1363		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1364			status = PAL720;
1365		break;
1366	}
1367
1368	return status;
1369}//end BT_check_tvmode.
1370
1371
1372/*
1373//BeTVOut's SwitchRIVAtoTV(vtot) timing formula: (note: vtot = (v_total - 2))
1374//-----------------------------------------------------------------------------------
1375//HORIZONTAL:
1376//-----------
1377h_sync_start = h_display;
1378
1379//fixme, note, checkout:
1380//feels like in fact TNT2-M64 nv_crtc.c registerprogramming should be adapted...
1381if (TNT2-M64)
1382{
1383	h_sync_end = h_display + 8;
1384	h_total = h_display + 56;
1385}
1386else //TNT1, TNT2, Geforce2... (so default)
1387{
1388	h_sync_end = h_display + 16;
1389	h_total = h_display + 48;
1390}
1391
1392//fixme, note, checkout:
1393//BeTVOut uses two 'tweaks':
1394// - on TNT2-M64 only:
1395//   register h_blank_e is increased with 1 (so should be done in nv_crtc.c here)
1396// - 'all cards':
1397//   register h_blank_e b6 = 0 (only influences TNT2-M64 in modes NTSC800 and PAL800).
1398//-----------------------------------------------------------------------------------
1399//VERTICAL:
1400//---------
1401v_sync_start = v_display;
1402v_total = vtot + 2;
1403v_sync_end = v_total - 1; //(This takes care of the 'cursor trash' on TNT1's...)
1404//-----------------------------------------------------------------------------------
1405*/
1406static status_t BT_update_mode_for_gpu(display_mode *target, uint8 tvmode)
1407{
1408	//fixme if needed:
1409	//pixelclock is not actually pgm'd because PLL is pgm' earlier during setmode...
1410	switch (tvmode)
1411	{
1412	case NTSC640:
1413	case NTSC640_TST:
1414		target->timing.h_display = 640;
1415		target->timing.h_sync_start = 640;
1416		if (si->ps.card_type == NV05M64)
1417		{
1418			target->timing.h_sync_end = 648;
1419			target->timing.h_total = 696;
1420		}
1421		else
1422		{
1423			//fixme if possible:
1424			//see if tweaking h_sync_end can shift picture 8 pixels right to fix
1425			//ws tv's tuning fault (always going for max. compatibility :)
1426			target->timing.h_sync_end = 656;
1427			target->timing.h_total = 688;
1428		}
1429		target->timing.v_display = 480;
1430		target->timing.v_sync_start = 480;
1431		target->timing.v_sync_end = 555;	//This prevents 'cursor trash' on TNT1's
1432		target->timing.v_total = 556;		//Above 525 because mode scales down
1433		if (si->ps.card_type == NV05M64)
1434			target->timing.pixel_clock = ((696 * 556 * 60) / 1000);
1435		else
1436			target->timing.pixel_clock = ((688 * 556 * 60) / 1000);
1437		break;
1438	case NTSC800:
1439		target->timing.h_display = 800;
1440		target->timing.h_sync_start = 800;
1441		if (si->ps.card_type == NV05M64)
1442		{
1443			target->timing.h_sync_end = 808;
1444			target->timing.h_total = 856;
1445		}
1446		else
1447		{
1448			target->timing.h_sync_end = 816;
1449			target->timing.h_total = 848;
1450		}
1451		target->timing.v_display = 600;
1452		target->timing.v_sync_start = 600;
1453		target->timing.v_sync_end = 685;	//This prevents 'cursor trash' on TNT1's
1454		target->timing.v_total = 686;		//Above 525 because mode scales down
1455		if (si->ps.card_type == NV05M64)
1456			target->timing.pixel_clock = ((856 * 686 * 60) / 1000);
1457		else
1458			target->timing.pixel_clock = ((848 * 686 * 60) / 1000);
1459		break;
1460	case PAL640:
1461		target->timing.h_display = 640;
1462		target->timing.h_sync_start = 640;
1463		if (si->ps.card_type == NV05M64)
1464		{
1465			target->timing.h_sync_end = 648;
1466			target->timing.h_total = 696;
1467		}
1468		else
1469		{
1470			target->timing.h_sync_end = 656;
1471			target->timing.h_total = 688;
1472		}
1473		target->timing.v_display = 480;
1474		target->timing.v_sync_start = 480;
1475		target->timing.v_sync_end = 570;	//This prevents 'cursor trash' on TNT1's
1476		target->timing.v_total = 571;		//Below 625 because mode scales up
1477		if (si->ps.card_type == NV05M64)
1478			target->timing.pixel_clock = ((696 * 571 * 50) / 1000);
1479		else
1480			target->timing.pixel_clock = ((688 * 571 * 50) / 1000);
1481		break;
1482	case PAL800:
1483	case PAL800_TST:
1484		target->timing.h_display = 800;
1485		target->timing.h_sync_start = 800;
1486		if (si->ps.card_type == NV05M64)
1487		{
1488			target->timing.h_sync_end = 808;
1489			target->timing.h_total = 856;
1490		}
1491		else
1492		{
1493			target->timing.h_sync_end = 816;
1494			target->timing.h_total = 848;
1495		}
1496		target->timing.v_display = 600;
1497		target->timing.v_sync_start = 600;
1498		target->timing.v_sync_end = 695;	//This prevents 'cursor trash' on TNT1's
1499		target->timing.v_total = 696;		//Above 625 because mode scales down
1500		if (si->ps.card_type == NV05M64)
1501			target->timing.pixel_clock = ((856 * 696 * 50) / 1000);
1502		else
1503			target->timing.pixel_clock = ((848 * 696 * 50) / 1000);
1504		break;
1505	case NTSC640_OS:
1506		target->timing.h_display = 640;			//BT H_ACTIVE
1507		target->timing.h_sync_start = 744;		//set for CH/BT compatible TV output
1508		target->timing.h_sync_end = 744+20;		//delta is BT H_BLANKI
1509		target->timing.h_total = 784;			//BT H_CLKI
1510		target->timing.v_display = 480;			//BT  V_ACTIVEI
1511		target->timing.v_sync_start = 490;		//set for centered sync pulse
1512		target->timing.v_sync_end = 490+25;		//delta is BT V_BLANKI
1513		target->timing.v_total = 525;			//BT V_LINESI (== 525: 1:1 scaled mode)
1514		target->timing.pixel_clock = ((784 * 525 * 60) / 1000); //refresh
1515		break;
1516	case PAL800_OS:
1517		target->timing.h_display = 768;			//H_ACTIVE
1518		if (si->ps.tv_encoder.type <= BT869)
1519		{
1520			/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
1521			target->timing.h_sync_start = 856;		//set for centered TV output
1522			target->timing.h_sync_end = 856+20;		//delta is BT H_BLANKI
1523		}
1524		else
1525		{
1526			/* confirmed on NV11 using 4:3 TV and 16:9 TV */
1527			target->timing.h_sync_start = 848;		//set for centered TV output
1528			target->timing.h_sync_end = 848+20;		//delta is BT H_BLANKI
1529		}
1530		target->timing.h_total = 944;			//BT H_CLKI
1531		target->timing.v_display = 576;			//V_ACTIVEI
1532		target->timing.v_sync_start = 579;		//set for centered sync pulse
1533		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1534		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
1535		target->timing.pixel_clock = ((944 * 625 * 50) / 1000); //refresh
1536		break;
1537	case NTSC720:
1538		/* (tested on TNT2 with BT869) */
1539		target->timing.h_display = 720;			//H_ACTIVE
1540		if (si->ps.tv_encoder.type <= BT869)
1541		{
1542			/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
1543			target->timing.h_sync_start = 744;		//do not change!
1544			target->timing.h_sync_end = 744+144;	//delta is H_sync_pulse
1545		}
1546		else
1547		{
1548			/* confirmed on NV11 using 4:3 TV and 16:9 TV */
1549			target->timing.h_sync_start = 728;		//do not change!
1550			target->timing.h_sync_end = 728+160;	//delta is H_sync_pulse
1551		}
1552		target->timing.h_total = 888;			//BT H_TOTAL
1553		target->timing.v_display = 480;			//V_ACTIVEI
1554		target->timing.v_sync_start = 490;		//set for centered sync pulse
1555		target->timing.v_sync_end = 490+26;		//delta is V_sync_pulse
1556		target->timing.v_total = 525;			//CH V_TOTAL (== 525: 1:1 scaled mode)
1557		target->timing.pixel_clock = ((888 * 525 * 60) / 1000); //refresh
1558		break;
1559	case PAL720:
1560		target->timing.h_display = 720;			//BT H_ACTIVE
1561		target->timing.h_sync_start = 744;		//set for centered sync pulse
1562		target->timing.h_sync_end = 744+140;	//delta is BT H_BLANKI
1563		target->timing.h_total = 888;			//BT H_CLKI
1564		target->timing.v_display = 576;			//BT  V_ACTIVEI
1565		target->timing.v_sync_start = 579;		//set for centered sync pulse
1566		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1567		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
1568		target->timing.pixel_clock = ((888 * 625 * 50) / 1000); //refresh
1569		break;
1570	default:
1571		return B_ERROR;
1572	}
1573
1574	return B_OK;
1575}//end BT_update_mode_for_gpu.
1576
1577/* note:
1578 * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869),
1579 * Diamond Viper V550 16Mb PCI (TNT1/BT869),
1580 * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */
1581static status_t BT_start_tvout(display_mode tv_target)
1582{
1583	/* TV_PRIMARY tells us that the head to be used with TVout is the head that's
1584	 * actually assigned as being the primary head at powerup:
1585	 * so non dualhead-mode-dependant, and not 'fixed' CRTC1! */
1586	if (tv_target.flags & TV_PRIMARY)
1587	{
1588		if ((tv_target.flags & DUALHEAD_BITS) != DUALHEAD_SWITCH)
1589			head1_start_tvout();
1590		else
1591			head2_start_tvout();
1592	}
1593	else
1594	{
1595		if ((tv_target.flags & DUALHEAD_BITS) != DUALHEAD_SWITCH)
1596			head2_start_tvout();
1597		else
1598			head1_start_tvout();
1599	}
1600
1601	return B_OK;
1602}//end BT_start_tvout.
1603
1604/* note:
1605 * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869),
1606 * Diamond Viper V550 16Mb PCI (TNT1/BT869),
1607 * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */
1608status_t BT_stop_tvout(void)
1609{
1610	/* prevent BT from being overclocked by VGA-only modes & black-out TV-out */
1611	BT_killclk_blackout();
1612
1613	/* TV_PRIMARY tells us that the head to be used with TVout is the head that's
1614	 * actually assigned as being the primary head at powerup:
1615	 * so non dualhead-mode-dependant, and not 'fixed' CRTC1! */
1616	if (si->dm.flags & TV_PRIMARY)
1617	{
1618		if ((si->dm.flags & DUALHEAD_BITS) != DUALHEAD_SWITCH)
1619			head1_stop_tvout();
1620		else
1621			head2_stop_tvout();
1622	}
1623	else
1624	{
1625		if ((si->dm.flags & DUALHEAD_BITS) != DUALHEAD_SWITCH)
1626			head2_stop_tvout();
1627		else
1628			head1_stop_tvout();
1629	}
1630
1631	/* fixme if needed:
1632	 * a full encoder chip reset could be done here (so after decoupling crtc)... */
1633	/* (but: beware of the 'locked SDA' syndrome then!) */
1634
1635	/* fixme if needed: we _could_ setup a TVout mode and apply the testsignal here... */
1636	if (0)
1637	{
1638		//set mode (selecting PAL/NTSC according to board wiring for example) etc, then:
1639		BT_testsignal();
1640	}
1641
1642	return B_OK;
1643}//end BT_stop_tvout.
1644
1645status_t BT_setmode(display_mode target)
1646{
1647	uint8 tvmode, monstat;
1648	/* enable flickerfilter in desktop modes, disable it in video modes. */
1649	uint8 ffilter = 0;
1650
1651	/* use a display_mode copy because we might tune it for TVout compatibility */
1652	display_mode tv_target = target;
1653
1654	/* preset new TVout mode */
1655	tvmode = BT_check_tvmode(tv_target);
1656	if (!tvmode) return B_ERROR;
1657
1658	/* read current output devices connection status */
1659	BT_read_monstat(&monstat);
1660
1661	/* (pre)set TV mode */
1662	/* note:
1663	 * Manual config is non-dependent of the state of the PAL hardware input pin;
1664	 * Also SDA lockups occur when setting EN_XCLK after autoconfig!
1665	 * Make sure PAL_MD=0 for NTSC and PAL_MD = 1 for PAL... */
1666	switch (tvmode)
1667	{
1668	case NTSC640:
1669	case NTSC640_TST:
1670		ffilter = 1;
1671		BT_init_NTSC640();
1672		break;
1673	case NTSC800:
1674		ffilter = 1;
1675		BT_init_NTSC800();
1676		break;
1677	case PAL640:
1678		ffilter = 1;
1679		BT_init_PAL640();
1680		break;
1681	case PAL800:
1682	case PAL800_TST:
1683		ffilter = 1;
1684		BT_init_PAL800();
1685		break;
1686	case NTSC640_OS:
1687		BT_init_NTSC640_OS();
1688		break;
1689	case PAL800_OS:
1690		BT_init_PAL800_OS();
1691		break;
1692	case NTSC720:
1693		BT_init_NTSC720();
1694		break;
1695	case PAL720:
1696		BT_init_PAL720();
1697		break;
1698	}
1699
1700	/* modify BT Hphase signal to center TV image... */
1701	BT_setup_hphase(tvmode);
1702
1703	/* disable Macro mode */
1704	switch (tvmode)
1705	{
1706	case NTSC640:
1707	case NTSC640_TST:
1708	case NTSC800:
1709	case NTSC640_OS:
1710	case NTSC720:
1711		/* NTSC */
1712		BT_set_macro (0, 0);
1713		break;
1714	default:
1715		/* PAL */
1716		BT_set_macro (1, 0);
1717		break;
1718	}
1719
1720	/* setup output signal routing and flickerfilter */
1721	BT_setup_output(monstat, (uint8)(si->settings.tv_output), ffilter);
1722
1723	/* update the GPU CRTC timing for the requested mode */
1724	BT_update_mode_for_gpu(&tv_target, tvmode);
1725
1726	/* setup GPU CRTC timing */
1727	/* TV_PRIMARY tells us that the head to be used with TVout is the head that's
1728	 * actually assigned as being the primary head at powerup:
1729	 * so non dualhead-mode-dependant, and not 'fixed' CRTC1! */
1730	if (tv_target.flags & TV_PRIMARY)
1731	{
1732		if ((tv_target.flags & DUALHEAD_BITS) != DUALHEAD_SWITCH)
1733			head1_set_timing(tv_target);
1734		else
1735			head2_set_timing(tv_target);
1736	}
1737	else
1738	{
1739		if ((tv_target.flags & DUALHEAD_BITS) != DUALHEAD_SWITCH)
1740			head2_set_timing(tv_target);
1741		else
1742			head1_set_timing(tv_target);
1743	}
1744
1745	/* now set GPU CRTC to slave mode */
1746	BT_start_tvout(tv_target);
1747
1748	return B_OK;
1749}
1750