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