xref: /haiku/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c (revision bfecd0cddb43bfcd2ca6222defddd96b7844e562)
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 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
616 	{
617 		/* confirmed on NV11 using 4:3 TV and 16:9 TV */
618 		buffer[7] = 0x0c;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
619 							//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
620 	}
621 	else //set BT value
622 	{
623 		/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
624 		buffer[7] = 0x28;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
625 							//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
626 	}
627 	buffer[8] = 0x18;	//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
628 
629 	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
630 	buffer[10] = 0x26;		//lsn = msn h_clk_o;
631 							//b4-5 = msbits h_active;
632 							//b7 = b8 v_avtive_o.
633 	buffer[11] = 0x00;		//h_fract is always 0.
634 	buffer[12] = 0x78;		//lsb h_clk_i: h_clk_i is horizontal total = 888.
635 	buffer[13] = 0x90; 	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
636 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
637 						//try-out: b3 = msn h_blank_i;
638 							//b4 = vblankdly is always 0.
639 	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
640 	buffer[16] = 0x1a; 	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
641 						//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
642 	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
643 	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
644 							//b3-2 = msn v_active_i;
645 							//b5-4 = ylpf = 3;
646 							//b7-6 = clpf = 0.
647 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
648 	buffer[20] = 0x50;		//b5-0 = msn v_scale;
649 						//scope: tuned. b7-6 = msn h_blank_o.
650 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
651 	buffer[21] = 0x98;		//lsb PLL fract: PLL fract = 0x6e98
652 	buffer[22] = 0x6e;		//msb PLL fract
653 	buffer[23] = 0x8c;		//b5-0 = PLL int: PLL int = 0x0c;
654 							//b6 = by_pll: by_pll = 0;
655 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
656 	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
657 							//b1 = setup = 1 for NTSC;
658 							//b2 = 625line = 0 for NTSC;
659 							//b3 = vsync_dur = 1 for NTSC;
660 							//b4 = dic_screset is always 0;
661 							//b5 = pal_md = 0 for NTSC;
662 							//b6 = eclip is always 0;
663 							//b7 = reserved (en_scart) is always 0.
664 	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
665 	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
666 	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
667 	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
668 	buffer[29] = 0x85;		//my: y $85 for NTSC
669 	buffer[30] = 0x3c;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
670 	buffer[31] = 0x91;		//msc = $20c2913c
671 	buffer[32] = 0xc2;
672 	buffer[33] = 0x20;		//msb msc.
673 	buffer[34] = 0x00;		//phase_off always $00
674 
675 	/* reset status */
676 	i2c_flag_error (-1);
677 
678 	i2c_bstart(si->ps.tv_encoder.bus);
679 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
680 	i2c_bstop(si->ps.tv_encoder.bus);
681 	/* log on errors */
682 	stat = i2c_flag_error(0);
683 	if (stat)
684 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC720\n"));
685 
686 	return stat;
687 }//end BT_init_NTSC720.
688 
689 static uint8 BT_init_PAL800_OS()
690 {
691 	uint8 stat;
692 
693 	uint8 buffer[35];
694 
695 	LOG(4,("Brooktree: Setting PAL 800x600 overscanning VCD mode\n"));
696 
697 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
698 	buffer[1] = 0x76;		//select first bt register to write to.
699 	buffer[2] = 0x60;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
700 	buffer[3] = 0x20;		//lsb h_active: h_active = 800 pixels wide port
701 	buffer[4] = 0x8b;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 64.0uS = 4.70uS for PAL
702 	buffer[5] = 0xa5;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 64.0uS = 5.6uS for PAL
703 	buffer[6] = 0x6b;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 64.0uS = 7.97uS for PAL
704 
705 	//How to find the correct values for h_blank_o and v_blank_o:
706 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
707 	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
708 	//    horizontal position is about OK;
709 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
710 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
711 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
712 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
713 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
714 
715 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
716 	{
717 		/* confirmed on NV11 using 4:3 TV and 16:9 TV */
718 		buffer[7] = 0xf0;
719 		buffer[8] = 0x17;
720 	}
721 	else //set BT value
722 	{
723 		/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
724 		buffer[7] = 0xd0;//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
725 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 64.0uS = 10.0uS for PAL)
726 		buffer[8] = 0x18;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
727 	}
728 
729 	buffer[9] = 0x2e;		//v_active_o: = (active output lines + 2) / field (on TV)
730 	buffer[10] = 0xb7;		//lsn = msn h_clk_o;
731 							//b4-5 = msbits h_active;
732 							//b7 = b8 v_avtive_o.
733 	buffer[11] = 0x00;		//h_fract is always 0.
734 	buffer[12] = 0xb0;		//lsb h_clk_i: h_clk_i is horizontal total = 944.
735 
736 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
737 		buffer[13] = 0x20;
738 	else //set BT value
739 		buffer[13] = 0x14;//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
740 
741 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
742 					 	//try-out: b3 = msn h_blank_i;
743 							//b4 = vblankdly is always 0.
744 	buffer[15] = 0x71;		//lsb v_lines_i: v_lines_i = 625
745 
746 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
747 		buffer[16] = 0x08;
748 	else				//set BT value
749 		buffer[16] = 0x2a;//try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
750 					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
751 
752 	buffer[17] = 0x58;		//lsb v_active_i: v_active_i = 600
753 	buffer[18] = 0x3a;		//b1-0 = msn v_lines_i;
754 							//b3-2 = msn v_active_i;
755 							//b5-4 = ylpf = 3;
756 							//b7-6 = clpf = 0.
757 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
758 	buffer[20] = 0x10;		//b5-0 = msn v_scale;
759 						//scope: tuned. b7-6 = msn h_blank_o.
760 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 50Hz)
761 	buffer[21] = 0x72;		//lsb PLL fract: PLL fract = 0x1c72
762 	buffer[22] = 0x1c;		//msb PLL fract
763 	buffer[23] = 0x8d;		//b5-0 = PLL int: PLL int = 0x0d;
764 							//b6 = by_pll: by_pll = 0;
765 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
766 	buffer[24] = 0x24;		//b0 = ni_out is always 0;
767 							//b1 = setup = 0 for PAL;
768 							//b2 = 625line = 1 for PAL;
769 							//b3 = vsync_dur = 0 for PAL;
770 							//b4 = dic_screset is always 0;
771 							//b5 = pal_md = 1 for PAL;
772 							//b6 = eclip is always 0;
773 							//b7 = reserved (en_scart) is always 0.
774 	buffer[25] = 0xf0;		//sync_amp $f0 for PAL
775 	buffer[26] = 0x57;		//bst_amp $57-$58 for PAL
776 	buffer[27] = 0x80;		//mcr: r-y $80-$81 for PAL
777 	buffer[28] = 0x48;		//mcb: b-y $48-$49 for PAL
778 	buffer[29] = 0x8c;		//my: y $8c for PAL
779 	buffer[30] = 0x31;		//lsb msc: msc b31-0: PAL formula: ((4433619 / pixelclk) * 2^32) = MSC
780 	buffer[31] = 0x8c;		//msc = $26798c31
781 	buffer[32] = 0x79;
782 	buffer[33] = 0x26;		//msb msc.
783 	buffer[34] = 0x00;		//phase_off always $00
784 
785 	/* reset status */
786 	i2c_flag_error (-1);
787 
788 	i2c_bstart(si->ps.tv_encoder.bus);
789 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
790 	i2c_bstop(si->ps.tv_encoder.bus);
791 	/* log on errors */
792 	stat = i2c_flag_error(0);
793 	if (stat)
794 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800 OS\n"));
795 
796 	return stat;
797 }//end BT_init_PAL800_OS.
798 
799 static uint8 BT_init_NTSC640_OS()
800 {
801 	uint8 stat;
802 
803 	uint8 buffer[35];
804 
805 	LOG(4,("Brooktree: Setting NTSC 640x480 overscanning VCD mode\n"));
806 
807 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
808 	buffer[1] = 0x76;		//select first bt register to write to.
809 	buffer[2] = 0x20;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
810 	buffer[3] = 0x80;		//lsb h_active: h_active = 640 pixels wide port
811 	buffer[4] = 0x74;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
812 	buffer[5] = 0x83;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
813 	buffer[6] = 0x44;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
814 
815 	//How to find the correct values for h_blank_o and v_blank_o:
816 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
817 	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
818 	//    horizontal position is about OK;
819 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
820 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
821 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
822 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
823 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
824 
825 	buffer[7] = 0xf7;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV:
826 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
827 
828 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
829 		buffer[8] = 0x1d;
830 	else //set BT value
831 		buffer[8] = 0x1c;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
832 
833 	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
834 	buffer[10] = 0x26;		//lsn = msn h_clk_o;
835 							//b4-5 = msbits h_active;
836 							//b7 = b8 v_avtive_o.
837 	buffer[11] = 0x00;		//h_fract is always 0.
838 	buffer[12] = 0x10;		//lsb h_clk_i: h_clk_i is horizontal total = 784.
839 	buffer[13] = 0x14;	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
840 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
841 						//try-out: b3 = msn h_blank_i;
842 							//b4 = vblankdly is always 0.
843 	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
844 	buffer[16] = 0x18;	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
845 					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
846 	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
847 	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
848 							//b3-2 = msn v_active_i;
849 							//b5-4 = ylpf = 3;
850 							//b7-6 = clpf = 0.
851 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
852 	buffer[20] = 0x10;		//b5-0 = msn v_scale;
853 						//scope: tuned. b7-6 = msn h_blank_o.
854 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
855 	buffer[21] = 0xdb;		//lsb PLL fract: PLL fract = 0xf9db
856 	buffer[22] = 0xf9;		//msb PLL fract
857 	buffer[23] = 0x8a;		//b5-0 = PLL int: PLL int = 0x0a;
858 							//b6 = by_pll: by_pll = 0;
859 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
860 	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
861 							//b1 = setup = 1 for NTSC;
862 							//b2 = 625line = 0 for NTSC;
863 							//b3 = vsync_dur = 1 for NTSC;
864 							//b4 = dic_screset is always 0;
865 							//b5 = pal_md = 0 for NTSC;
866 							//b6 = eclip is always 0;
867 							//b7 = reserved (en_scart) is always 0.
868 	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
869 	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
870 	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
871 	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
872 	buffer[29] = 0x85;		//my: y $85 for NTSC
873 	buffer[30] = 0x37;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
874 	buffer[31] = 0x12;		//msc = $251b1237
875 	buffer[32] = 0x1b;
876 	buffer[33] = 0x25;		//msb msc.
877 	buffer[34] = 0x00;		//phase_off always $00
878 
879 	/* reset status */
880 	i2c_flag_error (-1);
881 
882 	i2c_bstart(si->ps.tv_encoder.bus);
883 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
884 	i2c_bstop(si->ps.tv_encoder.bus);
885 	/* log on errors */
886 	stat = i2c_flag_error(0);
887 	if (stat)
888 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640 OS\n"));
889 
890 	return stat;
891 }//end BT_init_NTSC640_OS.
892 
893 static uint8 BT_testsignal(void)
894 {
895 	uint8 stat;
896 
897 	uint8 buffer[3];
898 
899 	LOG(4,("Brooktree: Enabling testsignal\n"));
900 
901 	buffer[0] = si->ps.tv_encoder.adress + WR;
902 	/* select bt register for enabling colorbars and outputs */
903 	buffer[1] = 0xc4;
904 	/* issue the actual command */
905 	buffer[2] = 0x05;
906 
907 	/* reset status */
908 	i2c_flag_error (-1);
909 
910 	i2c_bstart(si->ps.tv_encoder.bus);
911 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
912 	i2c_bstop(si->ps.tv_encoder.bus);
913 	/* log on errors */
914 	stat = i2c_flag_error(0);
915 	if (stat)
916 		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
917 
918 	return stat;
919 }//end BT_testsignal.
920 
921 static uint8 BT_setup_output(uint8 monstat, uint8 output, uint8 ffilter)
922 {
923 	uint8 stat;
924 
925 	uint8 buffer[7];
926 
927 	buffer[0] = si->ps.tv_encoder.adress + WR;
928 	/* select first TV config register to write */
929 	buffer[1] = 0xc6;
930 	/* input is 24bit mpx'd RGB, BLANK = out, sync = act. hi */
931 	buffer[2] = 0x98;
932 	/* disable all filters, exept flicker filter */
933 	buffer[3] = 0x98;
934 	if (!ffilter)
935 	{
936 		/* disable flicker filter */
937 		buffer[3] = 0xc0;
938 		LOG(4,("Brooktree: Disabling flickerfilter\n"));
939 	}
940 	else
941 		LOG(4,("Brooktree: Enabling flickerfilter\n"));
942 
943 	/* (disable filters) */
944 	buffer[4] = 0xc0;
945 	/* (disable filters) */
946 	buffer[5] = 0xc0;
947 	switch (output)
948 	/* Description of ELSA Erazor III hardware layout:
949 	 * (This is the default (recommended) layout by NVIDIA)
950 	 * DAC A = CVBS
951 	 * DAC B = C (chrominance)
952 	 * DAC C = Y (luminance) */
953 
954 	/* Description of Diamond VIPER550:
955 	 * DAC A = Not connected
956 	 * DAC B = C (chrominance)
957 	 * DAC C = Y (luminance)
958 	 * To be able to connect to CVBS TV's a special cable is supplied:
959 	 * This cable connects the Y (DAC C) output to the TV CVBS input. */
960 	{
961 	case 1:
962 		LOG(4,("Brooktree: Forcing both Y/C and CVBS signals where supported by hardware\n"));
963 		buffer[6] = 0x18;	// Y/C and CVBS out if all ports implemented
964 							// in hardware, else only Y/C or CVBS out.
965 		break;
966 	case 2:
967 		LOG(4,("Brooktree: Forcing CVBS signals on all outputs\n"));
968 		buffer[6] = 0x00;	// put CVBS on all outputs. Used for cards
969 		break;				// with only Y/C out and 'translation cable'.
970 	default:
971 		LOG(4,("Brooktree: Outputting signals according to autodetect status:\n"));
972 		switch (monstat)	// only 'autodetect' remains...
973 		{
974 		case 1:
975 			LOG(4,("Brooktree: Only Y connected, outputting CVBS on all outputs\n"));
976 			buffer[6] = 0x00;	//only Y connected: must be CVBS!
977 			break;
978 		case 2:
979 			LOG(4,("Brooktree: Only C connected, outputting CVBS on all outputs\n"));
980 			buffer[6] = 0x00;	//only C connected: must be CVBS!
981 			break;				//(though cable is wired wrong...)
982 		case 5:
983 			LOG(4,("Brooktree: CVBS and only Y connected, outputting CVBS on all outputs\n"));
984 			buffer[6] = 0x00;	//CVBS and only Y connected: 2x CVBS!
985 			break;			   	//(officially not supported...)
986 		case 6:
987 			LOG(4,("Brooktree: CVBS and only C connected, outputting CVBS on all outputs\n"));
988 			buffer[6] = 0x00;	//CVBS and only C connected: 2x CVBS!
989 			break;			   	//(officially not supported...)
990 		default:
991 			LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n"));
992 			buffer[6] = 0x18;	//nothing, or
993 							 	//Y/C only, or
994 							 	//CVBS only (but on CVBS output), or
995 							 	//Y/C and CVBS connected:
996 							 	//So activate recommended signals.
997 		}
998 	}
999 
1000 	/* reset status */
1001 	i2c_flag_error (-1);
1002 
1003 	i2c_bstart(si->ps.tv_encoder.bus);
1004 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1005 	i2c_bstop(si->ps.tv_encoder.bus);
1006 	/* log on errors */
1007 	stat = i2c_flag_error(0);
1008 	if (stat)
1009 		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
1010 
1011 	return stat;
1012 }//end BT_setup_output.
1013 
1014 static uint8 BT_setup_hphase(uint8 mode)
1015 {
1016 	uint8 stat, hoffset;
1017 
1018 	uint8 buffer[7];
1019 
1020 	LOG(4,("Brooktree: Tuning horizontal phase\n"));
1021 
1022 	/* CX needs timing reset (advised on BT also), first 1mS delay needed! */
1023 	snooze(1000);
1024 
1025 	/* values below are all tested on TNT1, TNT2 and GeForce2MX */
1026 	buffer[0] = si->ps.tv_encoder.adress + WR;
1027 	/* select first TV output timing register to write */
1028 	buffer[1] = 0x6c;
1029 	/* turn on active video & generate timing reset on CX chips! */
1030 	buffer[2] = 0x86;
1031 	/* (set fail save values...) */
1032 	buffer[3] = 0x00;		//set default horizontal sync offset
1033 	buffer[4] = 0x02;		//set default horizontal sync width
1034 	buffer[5] = 0x00;		//set default vertical sync offset
1035 
1036 	/* do specific timing setup for all chips and modes: */
1037 	switch (si->ps.card_type)
1038 	{
1039 	case NV05:
1040 	case NV05M64:
1041 	case NV15:
1042 		/* confirmed TNT2, TNT2M64, GeForce2Ti.
1043 		 * (8 pixels delayed hpos, so picture more to the right) */
1044 		hoffset = 8;
1045 		break;
1046 	default:
1047 		/* confirmed TNT1, GeForce256, GeForce2MX.
1048 		 * (std hpos)
1049 		 * NOTE: It might be that GeForce needs TNT2 offset:
1050 		 * for now CX chips get seperate extra offset, until sure.
1051 		 * (CX is only found AFAIK on GeForce cards, no BT tested
1052 		 * on GeForce yet. CH was tested on GeForce and seemed to
1053 		 * indicate TNT1 offset was needed.) */
1054 		hoffset = 0;
1055 		break;
1056 	}
1057 
1058 	switch (mode)
1059 	{
1060 	case NTSC640_TST:
1061 	case NTSC640:
1062 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1063 		/* confirmed on TNT1 with BT869 using 4:3 TV and 16:9 TV */
1064 		buffer[3] = (0x1e + hoffset);	//set horizontal sync offset
1065 		break;
1066 	case NTSC800:
1067 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1068 		buffer[3] = (0xe1 + hoffset);	//set horizontal sync offset
1069 		buffer[4] = 0xc2;
1070 		//Vsync offset reg. does not exist on CX: mode is checked and OK.
1071 		buffer[5] = 0x40;				//set VSync offset (on BT's only)
1072 		break;
1073 	case PAL640:
1074 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1075 		buffer[3] = (0xa8 + hoffset);
1076 		break;
1077 	case PAL800_TST:
1078 	case PAL800:
1079 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
1080 		buffer[3] = (0x2c + hoffset);
1081 		break;
1082 	case NTSC720:
1083 		if (si->ps.tv_encoder.type >= CX25870)
1084 			buffer[3] = (0xb2 + hoffset); //set horizontal sync offset CX
1085 		else
1086 			buffer[3] = (0xd0 + hoffset); //set horizontal sync offset BT
1087 		buffer[4] = 0xff;				//hsync width = max:
1088 		break;							//to prevent vertical image 'shivering'.
1089 	case PAL720:
1090 		buffer[3] = (0xd4 + hoffset);
1091 		buffer[4] = 0xff;
1092 		break;
1093 	case NTSC640_OS:
1094 		buffer[3] = (0xc8 + hoffset);
1095 		buffer[4] = 0xff;
1096 		break;
1097 	case PAL800_OS:
1098 		if (si->ps.tv_encoder.type >= CX25870)
1099 			buffer[3] = (0x78 + hoffset); //set horizontal sync offset CX
1100 		else
1101 			buffer[3] = (0xc4 + hoffset); //set horizontal sync offset BT
1102 		buffer[4] = 0xff;
1103 		break;
1104 	default: //nothing to be done here...
1105 		break;
1106 	}
1107 
1108 	buffer[6] = 0x01;		//set default vertical sync width
1109 
1110 	/* reset status */
1111 	i2c_flag_error (-1);
1112 
1113 	i2c_bstart(si->ps.tv_encoder.bus);
1114 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1115 	i2c_bstop(si->ps.tv_encoder.bus);
1116 	/* log on errors */
1117 	stat = i2c_flag_error(0);
1118 	if (stat)
1119 		LOG(4,("Brooktree: I2C errors occurred while setting up h_phase\n"));
1120 
1121 	return stat;
1122 }//end BT_setup_hphase.
1123 
1124 static uint8 BT_read_monstat(uint8* monstat)
1125 {
1126 	uint8 stat;
1127 	uint8 buffer[3];
1128 
1129 	/* make sure we have the recommended failsafe selected */
1130 	*monstat = 0;
1131 
1132 	LOG(4,("Brooktree: Autodetecting connected output devices\n"));
1133 
1134 	/* set BT to return connection status in ESTATUS on next read CMD: */
1135 	buffer[0] = si->ps.tv_encoder.adress + WR;
1136 	/* set ESTATUS at b'01' (return conn.stat.) */
1137 	buffer[1] = 0xc4;
1138 	/* and leave chip outputs on. */
1139 	buffer[2] = 0x41;
1140 
1141 	/* reset status */
1142 	i2c_flag_error (-1);
1143 
1144 	i2c_bstart(si->ps.tv_encoder.bus);
1145 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1146 	i2c_bstop(si->ps.tv_encoder.bus);
1147 	/* log on errors */
1148 	stat = i2c_flag_error(0);
1149 	if (stat)
1150 	{
1151 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (1)\n"));
1152 		return stat;
1153 	}
1154 
1155 	/* do actual read connection status: */
1156 	buffer[0] = si->ps.tv_encoder.adress + WR;
1157 	/* select register with CHECK_STAT CMD */
1158 	buffer[1] = 0xba;
1159 	/* issue actual command. */
1160 	buffer[2] = 0x40;
1161 
1162 	i2c_bstart(si->ps.tv_encoder.bus);
1163 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1164 	i2c_bstop(si->ps.tv_encoder.bus);
1165 	/* log on errors */
1166 	stat = i2c_flag_error(0);
1167 	if (stat)
1168 	{
1169 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (2)\n"));
1170 		return stat;
1171 	}
1172 
1173 	/* CX: Wait 600uS for signals to stabilize (see datasheet) */
1174 	/* warning, note:
1175 	 * datasheet is in error! 60mS needed!! */
1176 	snooze(60000);
1177 
1178 	/* read back updated connection status: */
1179 	buffer[0] = si->ps.tv_encoder.adress + RD;
1180 
1181 	/* transmit 1 byte */
1182 	i2c_bstart(si->ps.tv_encoder.bus);
1183 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 1);
1184 
1185 	/* receive 1 byte */
1186 	/* ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec)
1187 	 * While the BT's don't care, CX chips will block the SDA line if an ACK gets sent! */
1188 	buffer[0] = 1;
1189 	i2c_readbuffer(si->ps.tv_encoder.bus, buffer, 1);
1190 	i2c_bstop(si->ps.tv_encoder.bus);
1191 	/* log on errors */
1192 	stat = i2c_flag_error(0);
1193 	if (stat)
1194 	{
1195 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (3)\n"));
1196 		return stat;
1197 	}
1198 
1199 	*monstat = ((buffer[0] & 0xe0) >> 5);
1200 	LOG(4,("Brooktree: TV output monitor status = %d\n", *monstat));
1201 
1202 	/* instruct BT to go back to normal operation: */
1203 	buffer[0] = si->ps.tv_encoder.adress + WR;
1204 	/* select register with CHECK_STAT CMD */
1205 	buffer[1] = 0xba;
1206 	/* issue actual command. */
1207 	buffer[2] = 0x00;
1208 
1209 	i2c_bstart(si->ps.tv_encoder.bus);
1210 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1211 	i2c_bstop(si->ps.tv_encoder.bus);
1212 	/* log on errors */
1213 	stat = i2c_flag_error(0);
1214 	if (stat)
1215 	{
1216 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (4)\n"));
1217 		return stat;
1218 	}
1219 
1220 	return stat;
1221 }//end BT_read_monstat.
1222 
1223 static uint8 BT_killclk_blackout(void)
1224 {
1225 	uint8 stat;
1226 
1227 	uint8 buffer[4];
1228 
1229 	LOG(4,("Brooktree: Killing clock and/or blacking out (blocking output signals)\n"));
1230 
1231 	/* reset status */
1232 	i2c_flag_error (-1);
1233 
1234 	if (si->ps.tv_encoder.type <= BT869) //BT...
1235 	{
1236 		/* Only disable external pixelclock input on BT's.
1237 		 * CX chips will lock the bus if you do this.
1238 		 * (It looks like the external pixelclock is always OK as long as a valid
1239 		 * mode is programmed for the TVout chip. This means that disabling the use
1240 		 * of this clock is not needed anyway.
1241 		 * If you do disable this input, this pixelclock will rise to about 60Mhz BTW..) */
1242 
1243 		/* disable use of external pixelclock source... */
1244 		/* (should prevent BT for being 'overclocked' by RIVA in VGA-only mode...) */
1245 		buffer[0] = si->ps.tv_encoder.adress + WR;
1246 		/* select BT register for setting EN_XCLK */
1247 		buffer[1] = 0xa0;
1248 		/* clear it */
1249 		buffer[2] = 0x00;
1250 
1251 		i2c_bstart(si->ps.tv_encoder.bus);
1252 		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
1253 		i2c_bstop(si->ps.tv_encoder.bus);
1254 		/* log on errors */
1255 		stat = i2c_flag_error(0);
1256 		if (stat)
1257 		{
1258 			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-BT)\n"));
1259 			return stat;
1260 		}
1261 	}
1262 	else //CX...
1263 	{
1264 		/* Disable CX video out (or wild output will be seen on TV..) */
1265 		buffer[0] = si->ps.tv_encoder.adress + WR;
1266 		/* select register in CX */
1267 		buffer[1] = 0x6c;
1268 		/* disable active video out. */
1269 		buffer[2] = 0x02;
1270 
1271 		i2c_bstart(si->ps.tv_encoder.bus);
1272 		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
1273 		i2c_bstop(si->ps.tv_encoder.bus);
1274 		/* log on errors */
1275 		stat = i2c_flag_error(0);
1276 		if (stat)
1277 		{
1278 			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-CX)\n"));
1279 			return stat;
1280 		}
1281 	}
1282 
1283 	/* black-out TVout while outputs are enabled... */
1284 	buffer[0] = si->ps.tv_encoder.adress + WR;
1285 	/* select first TV config register to write */
1286 	buffer[1] = 0xc4;
1287 	/* disable testimage while outputs remain enabled */
1288 	buffer[2] = 0x01;
1289 	/* input is 24bit mpx'd RGB, BLANK = in, sync = act. hi */
1290 	buffer[3] = 0x18;
1291 
1292 	i2c_bstart(si->ps.tv_encoder.bus);
1293 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1294 	i2c_bstop(si->ps.tv_encoder.bus);
1295 	/* log on errors */
1296 	stat = i2c_flag_error(0);
1297 	if (stat)
1298 	{
1299 		LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (2)\n"));
1300 		return stat;
1301 	}
1302 
1303 	return stat;
1304 }//end BT_killclk_blackout.
1305 
1306 uint8 BT_dpms(bool display)
1307 {
1308 	uint8 stat;
1309 
1310 	uint8 buffer[3];
1311 
1312 	LOG(4,("Brooktree: setting DPMS: "));
1313 
1314 	/* reset status */
1315 	i2c_flag_error (-1);
1316 
1317 	/* shutdown all analog electronics... */
1318 	buffer[0] = si->ps.tv_encoder.adress + WR;
1319 	/* select first TV config register to write */
1320 	buffer[1] = 0xba;
1321 	if (display)
1322 	{
1323 		/* enable all DACs */
1324 		buffer[2] = 0x00;
1325 		LOG(4,("display on\n"));
1326 	}
1327 	else
1328 	{
1329 		/* shutdown all DACs */
1330 		buffer[2] = 0x10;
1331 		LOG(4,("display off\n"));
1332 	}
1333 
1334 	i2c_bstart(si->ps.tv_encoder.bus);
1335 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
1336 	i2c_bstop(si->ps.tv_encoder.bus);
1337 	/* log on errors */
1338 	stat = i2c_flag_error(0);
1339 	if (stat)
1340 	{
1341 		LOG(4,("Brooktree: I2C errors occurred while setting DPMS\n"));
1342 		return stat;
1343 	}
1344 
1345 	return stat;
1346 }//end BT_dpms.
1347 
1348 uint8 BT_check_tvmode(display_mode target)
1349 {
1350 	uint8 status = NOT_SUPPORTED;
1351 	uint32 mode = ((target.timing.h_display) | ((target.timing.v_display) << 16));
1352 
1353 	switch (mode)
1354 	{
1355 	case (640 | (480 << 16)):
1356 		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1357 			status = PAL640;
1358 		if ((target.flags & TV_BITS) == TV_NTSC)
1359 		{
1360 			if (!(target.flags & TV_VIDEO)) status = NTSC640;
1361 			else status = NTSC640_OS;
1362 		}
1363 		break;
1364 	case (768 | (576 << 16)):
1365 		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1366 			status = PAL800_OS;
1367 		break;
1368 	case (800 | (600 << 16)):
1369 		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1370 			status = PAL800;
1371 		if (((target.flags & TV_BITS) == TV_NTSC) && (!(target.flags & TV_VIDEO)))
1372 			status = NTSC800;
1373 		break;
1374 	case (720 | (480 << 16)):
1375 		if (((target.flags & TV_BITS) == TV_NTSC) && (target.flags & TV_VIDEO))
1376 			status = NTSC720;
1377 		break;
1378 	case (720 | (576 << 16)):
1379 		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1380 			status = PAL720;
1381 		break;
1382 	}
1383 
1384 	return status;
1385 }//end BT_check_tvmode.
1386 
1387 
1388 /*
1389 //BeTVOut's SwitchRIVAtoTV(vtot) timing formula: (note: vtot = (v_total - 2))
1390 //-----------------------------------------------------------------------------------
1391 //HORIZONTAL:
1392 //-----------
1393 h_sync_start = h_display;
1394 
1395 //fixme, note, checkout:
1396 //feels like in fact TNT2-M64 nv_crtc.c registerprogramming should be adapted...
1397 if (TNT2-M64)
1398 {
1399 	h_sync_end = h_display + 8;
1400 	h_total = h_display + 56;
1401 }
1402 else //TNT1, TNT2, Geforce2... (so default)
1403 {
1404 	h_sync_end = h_display + 16;
1405 	h_total = h_display + 48;
1406 }
1407 
1408 //fixme, note, checkout:
1409 //BeTVOut uses two 'tweaks':
1410 // - on TNT2-M64 only:
1411 //   register h_blank_e is increased with 1 (so should be done in nv_crtc.c here)
1412 // - 'all cards':
1413 //   register h_blank_e b6 = 0 (only influences TNT2-M64 in modes NTSC800 and PAL800).
1414 //-----------------------------------------------------------------------------------
1415 //VERTICAL:
1416 //---------
1417 v_sync_start = v_display;
1418 v_total = vtot + 2;
1419 v_sync_end = v_total - 1; //(This takes care of the 'cursor trash' on TNT1's...)
1420 //-----------------------------------------------------------------------------------
1421 */
1422 static status_t BT_update_mode_for_gpu(display_mode *target, uint8 tvmode)
1423 {
1424 	//fixme if needed:
1425 	//pixelclock is not actually pgm'd because PLL is pgm' earlier during setmode...
1426 	switch (tvmode)
1427 	{
1428 	case NTSC640:
1429 	case NTSC640_TST:
1430 		target->timing.h_display = 640;
1431 		target->timing.h_sync_start = 640;
1432 		if (si->ps.card_type == NV05M64)
1433 		{
1434 			target->timing.h_sync_end = 648;
1435 			target->timing.h_total = 696;
1436 		}
1437 		else
1438 		{
1439 			//fixme if possible:
1440 			//see if tweaking h_sync_end can shift picture 8 pixels right to fix
1441 			//ws tv's tuning fault (always going for max. compatibility :)
1442 			target->timing.h_sync_end = 656;
1443 			target->timing.h_total = 688;
1444 		}
1445 		target->timing.v_display = 480;
1446 		target->timing.v_sync_start = 480;
1447 		target->timing.v_sync_end = 555;	//This prevents 'cursor trash' on TNT1's
1448 		target->timing.v_total = 556;		//Above 525 because mode scales down
1449 		if (si->ps.card_type == NV05M64)
1450 			target->timing.pixel_clock = ((696 * 556 * 60) / 1000);
1451 		else
1452 			target->timing.pixel_clock = ((688 * 556 * 60) / 1000);
1453 		break;
1454 	case NTSC800:
1455 		target->timing.h_display = 800;
1456 		target->timing.h_sync_start = 800;
1457 		if (si->ps.card_type == NV05M64)
1458 		{
1459 			target->timing.h_sync_end = 808;
1460 			target->timing.h_total = 856;
1461 		}
1462 		else
1463 		{
1464 			target->timing.h_sync_end = 816;
1465 			target->timing.h_total = 848;
1466 		}
1467 		target->timing.v_display = 600;
1468 		target->timing.v_sync_start = 600;
1469 		target->timing.v_sync_end = 685;	//This prevents 'cursor trash' on TNT1's
1470 		target->timing.v_total = 686;		//Above 525 because mode scales down
1471 		if (si->ps.card_type == NV05M64)
1472 			target->timing.pixel_clock = ((856 * 686 * 60) / 1000);
1473 		else
1474 			target->timing.pixel_clock = ((848 * 686 * 60) / 1000);
1475 		break;
1476 	case PAL640:
1477 		target->timing.h_display = 640;
1478 		target->timing.h_sync_start = 640;
1479 		if (si->ps.card_type == NV05M64)
1480 		{
1481 			target->timing.h_sync_end = 648;
1482 			target->timing.h_total = 696;
1483 		}
1484 		else
1485 		{
1486 			target->timing.h_sync_end = 656;
1487 			target->timing.h_total = 688;
1488 		}
1489 		target->timing.v_display = 480;
1490 		target->timing.v_sync_start = 480;
1491 		target->timing.v_sync_end = 570;	//This prevents 'cursor trash' on TNT1's
1492 		target->timing.v_total = 571;		//Below 625 because mode scales up
1493 		if (si->ps.card_type == NV05M64)
1494 			target->timing.pixel_clock = ((696 * 571 * 50) / 1000);
1495 		else
1496 			target->timing.pixel_clock = ((688 * 571 * 50) / 1000);
1497 		break;
1498 	case PAL800:
1499 	case PAL800_TST:
1500 		target->timing.h_display = 800;
1501 		target->timing.h_sync_start = 800;
1502 		if (si->ps.card_type == NV05M64)
1503 		{
1504 			target->timing.h_sync_end = 808;
1505 			target->timing.h_total = 856;
1506 		}
1507 		else
1508 		{
1509 			target->timing.h_sync_end = 816;
1510 			target->timing.h_total = 848;
1511 		}
1512 		target->timing.v_display = 600;
1513 		target->timing.v_sync_start = 600;
1514 		target->timing.v_sync_end = 695;	//This prevents 'cursor trash' on TNT1's
1515 		target->timing.v_total = 696;		//Above 625 because mode scales down
1516 		if (si->ps.card_type == NV05M64)
1517 			target->timing.pixel_clock = ((856 * 696 * 50) / 1000);
1518 		else
1519 			target->timing.pixel_clock = ((848 * 696 * 50) / 1000);
1520 		break;
1521 	case NTSC640_OS:
1522 		target->timing.h_display = 640;			//BT H_ACTIVE
1523 		target->timing.h_sync_start = 744;		//set for CH/BT compatible TV output
1524 		target->timing.h_sync_end = 744+20;		//delta is BT H_BLANKI
1525 		target->timing.h_total = 784;			//BT H_CLKI
1526 		target->timing.v_display = 480;			//BT  V_ACTIVEI
1527 		target->timing.v_sync_start = 490;		//set for centered sync pulse
1528 		target->timing.v_sync_end = 490+25;		//delta is BT V_BLANKI
1529 		target->timing.v_total = 525;			//BT V_LINESI (== 525: 1:1 scaled mode)
1530 		target->timing.pixel_clock = ((784 * 525 * 60) / 1000); //refresh
1531 		break;
1532 	case PAL800_OS:
1533 		target->timing.h_display = 768;			//H_ACTIVE
1534 		if (si->ps.tv_encoder.type <= BT869)
1535 		{
1536 			/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
1537 			target->timing.h_sync_start = 856;		//set for centered TV output
1538 			target->timing.h_sync_end = 856+20;		//delta is BT H_BLANKI
1539 		}
1540 		else
1541 		{
1542 			/* confirmed on NV11 using 4:3 TV and 16:9 TV */
1543 			target->timing.h_sync_start = 848;		//set for centered TV output
1544 			target->timing.h_sync_end = 848+20;		//delta is BT H_BLANKI
1545 		}
1546 		target->timing.h_total = 944;			//BT H_CLKI
1547 		target->timing.v_display = 576;			//V_ACTIVEI
1548 		target->timing.v_sync_start = 579;		//set for centered sync pulse
1549 		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1550 		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
1551 		target->timing.pixel_clock = ((944 * 625 * 50) / 1000); //refresh
1552 		break;
1553 	case NTSC720:
1554 		/* (tested on TNT2 with BT869) */
1555 		target->timing.h_display = 720;			//H_ACTIVE
1556 		if (si->ps.tv_encoder.type <= BT869)
1557 		{
1558 			/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
1559 			target->timing.h_sync_start = 744;		//do not change!
1560 			target->timing.h_sync_end = 744+144;	//delta is H_sync_pulse
1561 		}
1562 		else
1563 		{
1564 			/* confirmed on NV11 using 4:3 TV and 16:9 TV */
1565 			target->timing.h_sync_start = 728;		//do not change!
1566 			target->timing.h_sync_end = 728+160;	//delta is H_sync_pulse
1567 		}
1568 		target->timing.h_total = 888;			//BT H_TOTAL
1569 		target->timing.v_display = 480;			//V_ACTIVEI
1570 		target->timing.v_sync_start = 490;		//set for centered sync pulse
1571 		target->timing.v_sync_end = 490+26;		//delta is V_sync_pulse
1572 		target->timing.v_total = 525;			//CH V_TOTAL (== 525: 1:1 scaled mode)
1573 		target->timing.pixel_clock = ((888 * 525 * 60) / 1000); //refresh
1574 		break;
1575 	case PAL720:
1576 		target->timing.h_display = 720;			//BT H_ACTIVE
1577 		target->timing.h_sync_start = 744;		//set for centered sync pulse
1578 		target->timing.h_sync_end = 744+140;	//delta is BT H_BLANKI
1579 		target->timing.h_total = 888;			//BT H_CLKI
1580 		target->timing.v_display = 576;			//BT  V_ACTIVEI
1581 		target->timing.v_sync_start = 579;		//set for centered sync pulse
1582 		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1583 		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
1584 		target->timing.pixel_clock = ((888 * 625 * 50) / 1000); //refresh
1585 		break;
1586 	default:
1587 		return B_ERROR;
1588 	}
1589 
1590 	return B_OK;
1591 }//end BT_update_mode_for_gpu.
1592 
1593 /* note:
1594  * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869),
1595  * Diamond Viper V550 16Mb PCI (TNT1/BT869),
1596  * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */
1597 static status_t BT_start_tvout(void)
1598 {
1599 	/* enable access to primary head */
1600 	set_crtc_owner(0);
1601 
1602 	/* CAUTION:
1603 	 * On old cards, PLLSEL (and TV_SETUP?) cannot be read (sometimes?), but
1604 	 * write actions do succeed ...
1605 	 * This is confirmed for both ISA and PCI access, on NV04 and NV11. */
1606 
1607 	/* setup TVencoder connection */
1608 	/* b1-0 = %01: encoder type is MASTER;
1609 	 * b24 = 1: VIP datapos is b0-7 */
1610 	//fixme if needed: setup completely instead of relying on pre-init by BIOS..
1611 	//(it seems to work OK on NV04 and NV11 although read reg. doesn't seem to work)
1612 	DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000002) | 0x01000001));
1613 
1614 	/* tell GPU to use pixelclock from TVencoder instead of using internal source */
1615 	/* (nessecary or display will 'shiver' on both TV and VGA.) */
1616 	if (si->ps.secondary_head)
1617 		//fixme: assuming TVout is on primary head!!
1618 		DACW(PLLSEL, 0x20030f00);
1619 	else
1620 		DACW(PLLSEL, 0x00030700);
1621 
1622 	/* Set overscan color to 'black' */
1623 	/* note:
1624 	 * Change this instruction for a visible overscan color if you're trying to
1625 	 * center the output on TV. Use it as a guide-'line' then ;-) */
1626 	ATBW(OSCANCOLOR, 0x00);
1627 
1628 	/* set CRTC to slaved mode (b7 = 1) and clear TVadjust (b3-5 = %000) */
1629 	CRTCW(PIXEL, ((CRTCR(PIXEL) & 0xc7) | 0x80));
1630 	/* select TV encoder, not panel encoder (b0 = 0).
1631 	 * Note:
1632 	 * Both are devices (often) using the CRTC in slaved mode. */
1633 	CRTCW(LCD, (CRTCR(LCD) & 0xfe));
1634 
1635 	/* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of
1636 	 * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */
1637 	CRTCW(TREG, 0x80);
1638 
1639 	return B_OK;
1640 }//end BT_start_tvout.
1641 
1642 /* note:
1643  * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869),
1644  * Diamond Viper V550 16Mb PCI (TNT1/BT869),
1645  * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */
1646 status_t BT_stop_tvout(void)
1647 {
1648 	/* prevent BT from being overclocked by VGA-only modes & black-out TV-out */
1649 	BT_killclk_blackout();
1650 
1651 	/* enable access to primary head */
1652 	set_crtc_owner(0);
1653 
1654 	/* switch on VGA monitor HSYNC and VSYNC */
1655 	//fixme: is this needed?
1656 	CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0x3f));
1657 
1658 
1659 	/* wait for one image to be generated to make sure VGA has kicked in and is
1660 	 * running OK before continuing...
1661 	 * (Kicking in will fail often if we do not wait here) */
1662 
1663 	/* make sure we are 'in' active VGA picture */
1664 	while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1);
1665 	/* wait for next vertical retrace start on VGA */
1666 	while (!(NV_REG8(NV8_INSTAT1) & 0x08)) snooze(1);
1667 	/* now wait until we are 'in' active VGA picture again */
1668 	while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1);
1669 
1670 
1671 	/* set CRTC to master mode (b7 = 0) if it wasn't slaved for a panel before */
1672 	if (!(si->ps.slaved_tmds1))	CRTCW(PIXEL, (CRTCR(PIXEL) & 0x03));
1673 
1674 	/* CAUTION:
1675 	 * On old cards, PLLSEL (and TV_SETUP?) cannot be read (sometimes?), but
1676 	 * write actions do succeed ...
1677 	 * This is confirmed for both ISA and PCI access, on NV04 and NV11. */
1678 
1679 	/* setup TVencoder connection */
1680 	/* b1-0 = %00: encoder type is SLAVE;
1681 	 * b24 = 1: VIP datapos is b0-7 */
1682 	//fixme if needed: setup completely instead of relying on pre-init by BIOS..
1683 	//(it seems to work OK on NV04 and NV11 although read reg. doesn't seem to work)
1684 	DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000003) | 0x01000000));
1685 
1686 	/* tell GPU to use pixelclock from internal source instead of using TVencoder */
1687 	if (si->ps.secondary_head)
1688 		DACW(PLLSEL, 0x30000f00);
1689 	else
1690 		DACW(PLLSEL, 0x10000700);
1691 
1692 	/* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of
1693 	 * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */
1694 	CRTCW(TREG, 0x00);
1695 
1696 	/* select panel encoder, not TV encoder if needed (b0 = 1).
1697 	 * Note:
1698 	 * Both are devices (often) using the CRTC in slaved mode. */
1699 	if (si->ps.slaved_tmds1) CRTCW(LCD, (CRTCR(LCD) | 0x01));
1700 
1701 	/* fixme if needed:
1702 	 * a full encoder chip reset could be done here (so after decoupling crtc)... */
1703 	/* (but: beware of the 'locked SDA' syndrome then!) */
1704 
1705 	return B_OK;
1706 }//end BT_stop_tvout.
1707 
1708 status_t BT_setmode(display_mode target)
1709 {
1710 	uint8 tvmode, monstat;
1711 	/* enable flickerfilter in desktop modes, disable it in video modes. */
1712 	uint8 ffilter = 0;
1713 
1714 	/* use a display_mode copy because we might tune it for TVout compatibility */
1715 	display_mode tv_target = target;
1716 
1717 	/* preset new TVout mode */
1718 	tvmode = BT_check_tvmode(tv_target);
1719 	if (!tvmode) return B_ERROR;
1720 
1721 	/* read current output devices connection status */
1722 	BT_read_monstat(&monstat);
1723 
1724 	/* (pre)set TV mode */
1725 	/* note:
1726 	 * Manual config is non-dependent of the state of the PAL hardware input pin;
1727 	 * Also SDA lockups occur when setting EN_XCLK after autoconfig!
1728 	 * Make sure PAL_MD=0 for NTSC and PAL_MD = 1 for PAL... */
1729 	switch (tvmode)
1730 	{
1731 	case NTSC640:
1732 	case NTSC640_TST:
1733 		ffilter = 1;
1734 		BT_init_NTSC640();
1735 		break;
1736 	case NTSC800:
1737 		ffilter = 1;
1738 		BT_init_NTSC800();
1739 		break;
1740 	case PAL640:
1741 		ffilter = 1;
1742 		BT_init_PAL640();
1743 		break;
1744 	case PAL800:
1745 	case PAL800_TST:
1746 		ffilter = 1;
1747 		BT_init_PAL800();
1748 		break;
1749 	case NTSC640_OS:
1750 		BT_init_NTSC640_OS();
1751 		break;
1752 	case PAL800_OS:
1753 		BT_init_PAL800_OS();
1754 		break;
1755 	case NTSC720:
1756 		BT_init_NTSC720();
1757 		break;
1758 	case PAL720:
1759 		BT_init_PAL720();
1760 		break;
1761 	}
1762 
1763 	/* modify BT Hphase signal to center TV image... */
1764 	BT_setup_hphase(tvmode);
1765 
1766 	/* disable Macro mode */
1767 	switch (tvmode)
1768 	{
1769 	case NTSC640:
1770 	case NTSC640_TST:
1771 	case NTSC800:
1772 	case NTSC640_OS:
1773 	case NTSC720:
1774 		/* NTSC */
1775 		BT_set_macro (0, 0);
1776 		break;
1777 	default:
1778 		/* PAL */
1779 		BT_set_macro (1, 0);
1780 		break;
1781 	}
1782 
1783 	/* setup output signal routing and flickerfilter */
1784 	BT_setup_output(monstat, (uint8)(si->settings.tv_output), ffilter);
1785 
1786 	/* update the GPU CRTC timing for the requested mode */
1787 	BT_update_mode_for_gpu(&tv_target, tvmode);
1788 
1789 	/* setup GPU CRTC timing */
1790 	head1_set_timing(tv_target);
1791 
1792 //fixme: only testing older cards for now...
1793 if (si->ps.secondary_head && (si->ps.card_type > NV15))
1794 {
1795 	BT_testsignal();
1796 	return B_OK;
1797 }
1798 
1799 	/* now set GPU CRTC to slave mode */
1800 	BT_start_tvout();
1801 
1802 //fixme: add code to disable VGA screen when TVout enabled
1803 //(use via nv.setting preset)
1804 
1805 	return B_OK;
1806 }
1807