xref: /haiku/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c (revision 4594e58a1bef7c90159326e104b85399361d8c9d)
112566cbdSRudolf Cornelissen /*
212566cbdSRudolf Cornelissen 	Author:
3b2459715SRudolf Cornelissen 	Rudolf Cornelissen 4/2002-10/2005
4fb6cadf1Sshatty */
5fb6cadf1Sshatty 
6fb6cadf1Sshatty #define MODULE_BIT 0x00100000
7fb6cadf1Sshatty 
8fb6cadf1Sshatty #include "nv_std.h"
9fb6cadf1Sshatty 
1012566cbdSRudolf Cornelissen #define PRADR	0x88
1112566cbdSRudolf Cornelissen #define SCADR	0x8a
1212566cbdSRudolf Cornelissen #define WR		0x00
1312566cbdSRudolf Cornelissen #define RD		0x01
1412566cbdSRudolf Cornelissen 
1521f6ecabSRudolf Cornelissen enum
1621f6ecabSRudolf Cornelissen {	// TVoutput mode to set
17b2459715SRudolf Cornelissen 	NOT_SUPPORTED = 0,
1821f6ecabSRudolf Cornelissen 	NTSC640_TST,
1921f6ecabSRudolf Cornelissen 	NTSC640,
2021f6ecabSRudolf Cornelissen 	NTSC800,
2121f6ecabSRudolf Cornelissen 	PAL800_TST,
2221f6ecabSRudolf Cornelissen 	PAL640,
2321f6ecabSRudolf Cornelissen 	PAL800,
2421f6ecabSRudolf Cornelissen 	NTSC720,
2521f6ecabSRudolf Cornelissen 	PAL720,
2621f6ecabSRudolf Cornelissen 	NTSC640_OS,
2721f6ecabSRudolf Cornelissen 	PAL800_OS
2821f6ecabSRudolf Cornelissen };
2921f6ecabSRudolf Cornelissen 
30b0fce481SRudolf Cornelissen /* Dirk Thierbach's Macro setup for registers 0xda-0xfe.
31b0fce481SRudolf Cornelissen  * (also see http://sourceforge.net/projects/nv-tv-out/) */
329a7218c5SRudolf Cornelissen static uint8 BtNtscMacro0 [] = {
339a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
349a7218c5SRudolf Cornelissen   0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x00,0x00};
359a7218c5SRudolf Cornelissen static uint8 BtNtscMacro1 [] = {
369a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
379a7218c5SRudolf Cornelissen   0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x63,0x00};
389a7218c5SRudolf Cornelissen static uint8 BtNtscMacro2 [] = {
399a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
409a7218c5SRudolf Cornelissen   0xbd,0x6c,0x31,0x92,0x32,0xdd,0xe3,0x00};
419a7218c5SRudolf Cornelissen static uint8 BtNtscMacro3 [] = {
429a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
439a7218c5SRudolf Cornelissen   0xbd,0x66,0xb5,0x90,0xb2,0x7d,0xe3,0x00};
449a7218c5SRudolf Cornelissen 
459a7218c5SRudolf Cornelissen static uint8 BtPalMacro0 [] = {
469a7218c5SRudolf Cornelissen   0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05,
479a7218c5SRudolf Cornelissen   0xd3,0x78,0xa2,0x25,0x54,0xa5,0x00,0x00};
489a7218c5SRudolf Cornelissen static uint8 BtPalMacro1 [] = {
499a7218c5SRudolf Cornelissen   0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05,
509a7218c5SRudolf Cornelissen   0xd3,0x78,0xa2,0x25,0x54,0xa5,0x63,0x00};
519a7218c5SRudolf Cornelissen 
529a7218c5SRudolf Cornelissen static uint8 BT_set_macro (int std, int mode)
539a7218c5SRudolf Cornelissen {
549a7218c5SRudolf Cornelissen 	uint8 stat;
559a7218c5SRudolf Cornelissen 	uint8 buffer[21];
569a7218c5SRudolf Cornelissen 
57b0fce481SRudolf Cornelissen 	LOG(4,("Brooktree: Setting Macro:\n"));
589a7218c5SRudolf Cornelissen 
599a7218c5SRudolf Cornelissen 	if ((std < 0) | (std > 1) | (mode < 0) | (mode > 3))
609a7218c5SRudolf Cornelissen 	{
619a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Non existing mode or standard selected, aborting.\n"));
629a7218c5SRudolf Cornelissen 		return 0x80;
639a7218c5SRudolf Cornelissen 	}
649a7218c5SRudolf Cornelissen 
659a7218c5SRudolf Cornelissen 	switch (std)
669a7218c5SRudolf Cornelissen 	{
679a7218c5SRudolf Cornelissen 	case 0:
689a7218c5SRudolf Cornelissen 		/* NTSC */
699a7218c5SRudolf Cornelissen 		switch (mode)
709a7218c5SRudolf Cornelissen 		{
719a7218c5SRudolf Cornelissen 		case 0:
729a7218c5SRudolf Cornelissen 			/* disabled */
73b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: NTSC, disabled\n"));
749a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro0, 19);
759a7218c5SRudolf Cornelissen 			break;
769a7218c5SRudolf Cornelissen 		case 1:
779a7218c5SRudolf Cornelissen 			/* enabled mode 1 */
78b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: NTSC, mode 1\n"));
799a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro1, 19);
809a7218c5SRudolf Cornelissen 			break;
819a7218c5SRudolf Cornelissen 		case 2:
829a7218c5SRudolf Cornelissen 			/* enabled mode 2 */
83b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: NTSC, mode 2\n"));
849a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro2, 19);
859a7218c5SRudolf Cornelissen 			break;
869a7218c5SRudolf Cornelissen 		case 3:
879a7218c5SRudolf Cornelissen 			/* enabled mode 3 */
88b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: NTSC, mode 3\n"));
899a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro3, 19);
909a7218c5SRudolf Cornelissen 			break;
919a7218c5SRudolf Cornelissen 		}
929a7218c5SRudolf Cornelissen 		break;
939a7218c5SRudolf Cornelissen 	case 1:
949a7218c5SRudolf Cornelissen 		/* PAL */
959a7218c5SRudolf Cornelissen 		switch (mode)
969a7218c5SRudolf Cornelissen 		{
979a7218c5SRudolf Cornelissen 		case 0:
989a7218c5SRudolf Cornelissen 			/* disabled */
99b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: PAL, disabled\n"));
1009a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtPalMacro0, 19);
1019a7218c5SRudolf Cornelissen 			break;
1029a7218c5SRudolf Cornelissen 		case 1:
1039a7218c5SRudolf Cornelissen 		case 2:
1049a7218c5SRudolf Cornelissen 		case 3:
1059a7218c5SRudolf Cornelissen 			/* enabled */
106b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: PAL, enabled\n"));
1079a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtPalMacro1, 19);
1089a7218c5SRudolf Cornelissen 			break;
1099a7218c5SRudolf Cornelissen 		}
1109a7218c5SRudolf Cornelissen 		break;
1119a7218c5SRudolf Cornelissen 	}
1129a7218c5SRudolf Cornelissen 
1139a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
1149a7218c5SRudolf Cornelissen 	/* select first register to write to */
1159a7218c5SRudolf Cornelissen 	buffer[1] = 0xda;
1169a7218c5SRudolf Cornelissen 
1179a7218c5SRudolf Cornelissen 	/* reset status */
1189a7218c5SRudolf Cornelissen 	i2c_flag_error (-1);
1199a7218c5SRudolf Cornelissen 
1209a7218c5SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
1219a7218c5SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1229a7218c5SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
1239a7218c5SRudolf Cornelissen 	/* log on errors */
1249a7218c5SRudolf Cornelissen 	stat = i2c_flag_error(0);
1259a7218c5SRudolf Cornelissen 	if (stat)
1269a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting Macro\n"));
1279a7218c5SRudolf Cornelissen 
1289a7218c5SRudolf Cornelissen 	return stat;
1299a7218c5SRudolf Cornelissen }//end BT_set_macro.
1309a7218c5SRudolf Cornelissen 
13112566cbdSRudolf Cornelissen /*
13212566cbdSRudolf Cornelissen  see if a (possible) BT/CX chip resides at the given adress.
13312566cbdSRudolf Cornelissen  Return zero if no errors occurred.
13412566cbdSRudolf Cornelissen */
13512566cbdSRudolf Cornelissen static uint8 BT_check (uint8 bus, uint8 adress)
13612566cbdSRudolf Cornelissen {
1370ece4905SRudolf Cornelissen 	uint8 buffer[3];
13812566cbdSRudolf Cornelissen 
1390ece4905SRudolf Cornelissen 	buffer[0] = adress + WR;
14012566cbdSRudolf Cornelissen 	/* set ESTATUS at b'00'; and enable bt chip-outputs
14112566cbdSRudolf Cornelissen 	 * WARNING:
14212566cbdSRudolf Cornelissen 	 * If bit0 = 0 is issued below (EN_OUT = disabled), the BT will lock SDA
14312566cbdSRudolf Cornelissen 	 * after writing adress $A0 (setting EN_XCLK)!!!
1449a7218c5SRudolf Cornelissen 	 * Until a reboot the corresponding I2C bus will be inacessable then!!! */
1450ece4905SRudolf Cornelissen 	buffer[1] = 0xc4;
14612566cbdSRudolf Cornelissen 	/* fixme: if testimage 'was' active txbuffer[3] should become 0x05...
14712566cbdSRudolf Cornelissen 	 * (currently this cannot be detected in a 'foolproof' way so don't touch...) */
14812566cbdSRudolf Cornelissen 	/* (ESTATUS b'0x' means: RX ID and VERSION info later..) */
1490ece4905SRudolf Cornelissen 	buffer[2] = 0x01;
1500ece4905SRudolf Cornelissen 
1510ece4905SRudolf Cornelissen 	/* reset status */
1520ece4905SRudolf Cornelissen 	i2c_flag_error (-1);
1530ece4905SRudolf Cornelissen 
1540ece4905SRudolf Cornelissen 	/* do check */
1550ece4905SRudolf Cornelissen 	i2c_bstart(bus);
1560ece4905SRudolf Cornelissen 	i2c_writebuffer(bus, buffer, sizeof(buffer));
15712566cbdSRudolf Cornelissen 	i2c_bstop(bus);
15812566cbdSRudolf Cornelissen 	return i2c_flag_error(0);
15912566cbdSRudolf Cornelissen }
16012566cbdSRudolf Cornelissen 
16112566cbdSRudolf Cornelissen /* identify chiptype */
16212566cbdSRudolf Cornelissen static uint8 BT_read_type (void)
16312566cbdSRudolf Cornelissen {
1640ece4905SRudolf Cornelissen 	uint8 id, type, stat;
1650ece4905SRudolf Cornelissen 	uint8 buffer[3];
1660ece4905SRudolf Cornelissen 
1670ece4905SRudolf Cornelissen 	/* Make sure a CX (Conexant) chip (if this turns out to be there) is set to
1680ece4905SRudolf Cornelissen 	 * BT-compatibility mode! (This command will do nothing on a BT chip...) */
1690ece4905SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
1700ece4905SRudolf Cornelissen 	/* select CX reg. for BT-compatible readback, video still off */
1710ece4905SRudolf Cornelissen 	buffer[1] = 0x6c;
1720ece4905SRudolf Cornelissen 	/* set it up */
1730ece4905SRudolf Cornelissen 	buffer[2] = 0x02;
17412566cbdSRudolf Cornelissen 
17512566cbdSRudolf Cornelissen 	/* reset status */
17612566cbdSRudolf Cornelissen 	i2c_flag_error (-1);
17712566cbdSRudolf Cornelissen 
17812566cbdSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
1790ece4905SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
18012566cbdSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
18112566cbdSRudolf Cornelissen 	/* abort on errors */
18212566cbdSRudolf Cornelissen 	stat = i2c_flag_error(0);
18312566cbdSRudolf Cornelissen 	if (stat) return stat;
18412566cbdSRudolf Cornelissen 
18512566cbdSRudolf Cornelissen 	/* Do actual readtype command */
18612566cbdSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
1879a7218c5SRudolf Cornelissen 	/* issue I2C read command */
18812566cbdSRudolf Cornelissen 	i2c_writebyte(si->ps.tv_encoder.bus, si->ps.tv_encoder.adress + RD);
18912566cbdSRudolf Cornelissen 	/* receive 1 byte;
1909a7218c5SRudolf Cornelissen 	 * ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec). */
19112566cbdSRudolf Cornelissen 	/* note:
19212566cbdSRudolf Cornelissen 	 * While the BT's don't care, CX chips will block the SDA line if
19312566cbdSRudolf Cornelissen 	 * an ACK gets sent! */
19412566cbdSRudolf Cornelissen 	id = i2c_readbyte(si->ps.tv_encoder.bus, true);
19512566cbdSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
19612566cbdSRudolf Cornelissen 	/* abort on errors */
19712566cbdSRudolf Cornelissen 	stat = i2c_flag_error(0);
19812566cbdSRudolf Cornelissen 	if (stat) return stat;
19912566cbdSRudolf Cornelissen 
2000ece4905SRudolf Cornelissen 	/* check type to be supported one */
2010ece4905SRudolf Cornelissen 	type = (id & 0xe0) >> 5;
2020ece4905SRudolf Cornelissen 	if (type > 3)
2030ece4905SRudolf Cornelissen 	{
2040ece4905SRudolf Cornelissen 		LOG(4,("Brooktree: Found unsupported encoder type %d, aborting.\n", type));
2050ece4905SRudolf Cornelissen 		return 0x80;
2060ece4905SRudolf Cornelissen 	}
2070ece4905SRudolf Cornelissen 
20812566cbdSRudolf Cornelissen 	/* inform driver about TV encoder found */
20912566cbdSRudolf Cornelissen 	si->ps.tvout = true;
2100ece4905SRudolf Cornelissen 	si->ps.tv_encoder.type = BT868 + type;
21112566cbdSRudolf Cornelissen 	si->ps.tv_encoder.version = id & 0x1f;
21212566cbdSRudolf Cornelissen 
21312566cbdSRudolf Cornelissen 	return stat;
21412566cbdSRudolf Cornelissen }
21512566cbdSRudolf Cornelissen 
21612566cbdSRudolf Cornelissen bool BT_probe()
21712566cbdSRudolf Cornelissen {
21812566cbdSRudolf Cornelissen 	bool btfound = false;
21912566cbdSRudolf Cornelissen 
2209a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Checking I2C bus(ses) for first possible TV encoder...\n"));
22112566cbdSRudolf Cornelissen 	if (si->ps.i2c_bus0)
22212566cbdSRudolf Cornelissen 	{
22312566cbdSRudolf Cornelissen 		/* try primary adress on bus 0 */
22412566cbdSRudolf Cornelissen 		if (!BT_check(0, PRADR))
22512566cbdSRudolf Cornelissen 		{
22612566cbdSRudolf Cornelissen 			btfound = true;
22712566cbdSRudolf Cornelissen 			si->ps.tv_encoder.adress = PRADR;
22812566cbdSRudolf Cornelissen 			si->ps.tv_encoder.bus = 0;
22912566cbdSRudolf Cornelissen 		}
23012566cbdSRudolf Cornelissen 		else
23112566cbdSRudolf Cornelissen 		{
23212566cbdSRudolf Cornelissen 			/* try secondary adress on bus 0 */
23312566cbdSRudolf Cornelissen 			if (!BT_check(0, SCADR))
23412566cbdSRudolf Cornelissen 			{
23512566cbdSRudolf Cornelissen 				btfound = true;
23612566cbdSRudolf Cornelissen 				si->ps.tv_encoder.adress = SCADR;
23712566cbdSRudolf Cornelissen 				si->ps.tv_encoder.bus = 0;
23812566cbdSRudolf Cornelissen 			}
23912566cbdSRudolf Cornelissen 		}
24012566cbdSRudolf Cornelissen 	}
24112566cbdSRudolf Cornelissen 
24212566cbdSRudolf Cornelissen 	if (si->ps.i2c_bus1 && !btfound)
24312566cbdSRudolf Cornelissen 	{
24412566cbdSRudolf Cornelissen 		/* try primary adress on bus 1 */
24512566cbdSRudolf Cornelissen 		if (!BT_check(1, PRADR))
24612566cbdSRudolf Cornelissen 		{
24712566cbdSRudolf Cornelissen 			btfound = true;
24812566cbdSRudolf Cornelissen 			si->ps.tv_encoder.adress = PRADR;
24912566cbdSRudolf Cornelissen 			si->ps.tv_encoder.bus = 1;
25012566cbdSRudolf Cornelissen 		}
25112566cbdSRudolf Cornelissen 		else
25212566cbdSRudolf Cornelissen 		{
25312566cbdSRudolf Cornelissen 			/* try secondary adress on bus 1 */
25412566cbdSRudolf Cornelissen 			if (!BT_check(1, SCADR))
25512566cbdSRudolf Cornelissen 			{
25612566cbdSRudolf Cornelissen 				btfound = true;
25712566cbdSRudolf Cornelissen 				si->ps.tv_encoder.adress = SCADR;
25812566cbdSRudolf Cornelissen 				si->ps.tv_encoder.bus = 1;
25912566cbdSRudolf Cornelissen 			}
26012566cbdSRudolf Cornelissen 		}
26112566cbdSRudolf Cornelissen 	}
26212566cbdSRudolf Cornelissen 
26312566cbdSRudolf Cornelissen 	/* identify exact TV encoder type */
26412566cbdSRudolf Cornelissen 	if (btfound)
26512566cbdSRudolf Cornelissen 	{
26612566cbdSRudolf Cornelissen 		/* if errors are found, retry */
26712566cbdSRudolf Cornelissen 		/* note:
26812566cbdSRudolf Cornelissen 		 * NACK: occurs on some ASUS V7700 GeForce cards!
26912566cbdSRudolf Cornelissen 		 * (apparantly the video-in chip or another chip resides at 'BT' adresses
27012566cbdSRudolf Cornelissen 		 * there..) */
27112566cbdSRudolf Cornelissen 		uint8 stat;
27212566cbdSRudolf Cornelissen 		uint8 cnt = 0;
27312566cbdSRudolf Cornelissen 		while ((stat = BT_read_type()) && (cnt < 3))
27412566cbdSRudolf Cornelissen 		{
2750ece4905SRudolf Cornelissen 			/* don't retry on unsupported chiptype */
2760ece4905SRudolf Cornelissen 			if (stat == 0x80)
2770ece4905SRudolf Cornelissen 			{
2780ece4905SRudolf Cornelissen 				btfound = 0;
2790ece4905SRudolf Cornelissen 				break;
2800ece4905SRudolf Cornelissen 			}
28112566cbdSRudolf Cornelissen 			cnt++;
28212566cbdSRudolf Cornelissen 		}
2830ece4905SRudolf Cornelissen 		if (stat & 0x7f)
28412566cbdSRudolf Cornelissen 		{
2859a7218c5SRudolf Cornelissen 			LOG(4,("Brooktree: Too much errors occurred, aborting.\n"));
28612566cbdSRudolf Cornelissen 			btfound = 0;
28712566cbdSRudolf Cornelissen 		}
28812566cbdSRudolf Cornelissen 	}
28912566cbdSRudolf Cornelissen 
29012566cbdSRudolf Cornelissen 	if (btfound)
29112566cbdSRudolf Cornelissen 		LOG(4,("Brooktree: Found TV encoder on bus %d, adress $%02x\n",
29212566cbdSRudolf Cornelissen 			si->ps.tv_encoder.bus, si->ps.tv_encoder.adress));
29312566cbdSRudolf Cornelissen 	else
29412566cbdSRudolf Cornelissen 		LOG(4,("Brooktree: No TV encoder Found\n"));
29512566cbdSRudolf Cornelissen 
29612566cbdSRudolf Cornelissen 	return btfound;
29712566cbdSRudolf Cornelissen }
29812566cbdSRudolf Cornelissen 
29977497c49SRudolf Cornelissen static uint8 BT_init_PAL640()
300fb6cadf1Sshatty {
30177497c49SRudolf Cornelissen 	uint8 stat;
302fb6cadf1Sshatty 
30377497c49SRudolf Cornelissen 	uint8 buffer[35];
304fb6cadf1Sshatty 
3059a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 640x480 desktop mode\n"));
3069a7218c5SRudolf Cornelissen 
3079a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
30877497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
30977497c49SRudolf Cornelissen 	buffer[2] = 0x60;
31077497c49SRudolf Cornelissen 	buffer[3] = 0x80;
31177497c49SRudolf Cornelissen 	buffer[4] = 0x8a;
31277497c49SRudolf Cornelissen 	buffer[5] = 0xa6;
31377497c49SRudolf Cornelissen 	buffer[6] = 0x68;
31477497c49SRudolf Cornelissen 	buffer[7] = 0xc1;
31577497c49SRudolf Cornelissen 	buffer[8] = 0x2e;
31677497c49SRudolf Cornelissen 	buffer[9] = 0xf2;
31777497c49SRudolf Cornelissen 	buffer[10] = 0x27;
31877497c49SRudolf Cornelissen 	buffer[11] = 0x00;
31977497c49SRudolf Cornelissen 	buffer[12] = 0xb0;
32077497c49SRudolf Cornelissen 	buffer[13] = 0x0a;
32177497c49SRudolf Cornelissen 	buffer[14] = 0x0b;
32277497c49SRudolf Cornelissen 	buffer[15] = 0x71;
32377497c49SRudolf Cornelissen 	buffer[16] = 0x5a;
32477497c49SRudolf Cornelissen 	buffer[17] = 0xe0;
32577497c49SRudolf Cornelissen 	buffer[18] = 0x36;
32677497c49SRudolf Cornelissen 	buffer[19] = 0x00;
32777497c49SRudolf Cornelissen 	buffer[20] = 0x50;
32877497c49SRudolf Cornelissen 	buffer[21] = 0x72;
32977497c49SRudolf Cornelissen 	buffer[22] = 0x1c;
33077497c49SRudolf Cornelissen 	buffer[23] = 0x8d;		//chip-pin CLKI is pixel clock (only non-default here!)
33177497c49SRudolf Cornelissen 	buffer[24] = 0x24;
33277497c49SRudolf Cornelissen 	buffer[25] = 0xf0;
33377497c49SRudolf Cornelissen 	buffer[26] = 0x58;
33477497c49SRudolf Cornelissen 	buffer[27] = 0x81;
33577497c49SRudolf Cornelissen 	buffer[28] = 0x49;
33677497c49SRudolf Cornelissen 	buffer[29] = 0x8c;
33777497c49SRudolf Cornelissen 	buffer[30] = 0x0c;
33877497c49SRudolf Cornelissen 	buffer[31] = 0x8c;
33977497c49SRudolf Cornelissen 	buffer[32] = 0x79;
34077497c49SRudolf Cornelissen 	buffer[33] = 0x26;
34177497c49SRudolf Cornelissen 	buffer[34] = 0x00;
34277497c49SRudolf Cornelissen 
34377497c49SRudolf Cornelissen 	/* reset status */
34477497c49SRudolf Cornelissen 	i2c_flag_error (-1);
34577497c49SRudolf Cornelissen 
34677497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
34777497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
34877497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
34977497c49SRudolf Cornelissen 	/* log on errors */
35077497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
35177497c49SRudolf Cornelissen 	if (stat)
35277497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL640\n"));
35377497c49SRudolf Cornelissen 
35477497c49SRudolf Cornelissen 	return stat;
35577497c49SRudolf Cornelissen }//end BT_init_PAL640.
35677497c49SRudolf Cornelissen 
35777497c49SRudolf Cornelissen static uint8 BT_init_PAL800()
358fb6cadf1Sshatty {
35977497c49SRudolf Cornelissen 	uint8 stat;
360fb6cadf1Sshatty 
36177497c49SRudolf Cornelissen 	uint8 buffer[35];
362fb6cadf1Sshatty 
3639a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 800x600 desktop mode\n"));
3649a7218c5SRudolf Cornelissen 
3659a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
36677497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
36777497c49SRudolf Cornelissen 	buffer[2] = 0x00;
36877497c49SRudolf Cornelissen 	buffer[3] = 0x20;
36977497c49SRudolf Cornelissen 	buffer[4] = 0xaa;
37077497c49SRudolf Cornelissen 	buffer[5] = 0xca;
37177497c49SRudolf Cornelissen 	buffer[6] = 0x9a;
37277497c49SRudolf Cornelissen 	buffer[7] = 0x0d;
37377497c49SRudolf Cornelissen 	buffer[8] = 0x29;
37477497c49SRudolf Cornelissen 	buffer[9] = 0xfc;
37577497c49SRudolf Cornelissen 	buffer[10] = 0x39;
37677497c49SRudolf Cornelissen 	buffer[11] = 0x00;
37777497c49SRudolf Cornelissen 	buffer[12] = 0xc0;
37877497c49SRudolf Cornelissen 	buffer[13] = 0x8c;
37977497c49SRudolf Cornelissen 	buffer[14] = 0x03;
38077497c49SRudolf Cornelissen 	buffer[15] = 0xee;
38177497c49SRudolf Cornelissen 	buffer[16] = 0x5f;
38277497c49SRudolf Cornelissen 	buffer[17] = 0x58;
38377497c49SRudolf Cornelissen 	buffer[18] = 0x3a;
38477497c49SRudolf Cornelissen 	buffer[19] = 0x66;
38577497c49SRudolf Cornelissen 	buffer[20] = 0x96;
38677497c49SRudolf Cornelissen 	buffer[21] = 0x00;
38777497c49SRudolf Cornelissen 	buffer[22] = 0x00;
38877497c49SRudolf Cornelissen 	buffer[23] = 0x90;		//chip-pin CLKI is pixel clock (only non-default here!)
38977497c49SRudolf Cornelissen 	buffer[24] = 0x24;
39077497c49SRudolf Cornelissen 	buffer[25] = 0xf0;
39177497c49SRudolf Cornelissen 	buffer[26] = 0x57;
39277497c49SRudolf Cornelissen 	buffer[27] = 0x80;
39377497c49SRudolf Cornelissen 	buffer[28] = 0x48;
39477497c49SRudolf Cornelissen 	buffer[29] = 0x8c;
39577497c49SRudolf Cornelissen 	buffer[30] = 0x18;
39677497c49SRudolf Cornelissen 	buffer[31] = 0x28;
39777497c49SRudolf Cornelissen 	buffer[32] = 0x87;
39877497c49SRudolf Cornelissen 	buffer[33] = 0x1f;
39977497c49SRudolf Cornelissen 	buffer[34] = 0x00;
40077497c49SRudolf Cornelissen 
40177497c49SRudolf Cornelissen 	/* reset status */
40277497c49SRudolf Cornelissen 	i2c_flag_error (-1);
40377497c49SRudolf Cornelissen 
40477497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
40577497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
40677497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
40777497c49SRudolf Cornelissen 	/* log on errors */
40877497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
40977497c49SRudolf Cornelissen 	if (stat)
41077497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n"));
41177497c49SRudolf Cornelissen 
41277497c49SRudolf Cornelissen 	return stat;
41377497c49SRudolf Cornelissen }//end BT_init_PAL800.
41477497c49SRudolf Cornelissen 
41577497c49SRudolf Cornelissen static uint8 BT_init_NTSC640()
416fb6cadf1Sshatty {
41777497c49SRudolf Cornelissen 	uint8 stat;
418fb6cadf1Sshatty 
41977497c49SRudolf Cornelissen 	uint8 buffer[35];
42077497c49SRudolf Cornelissen 
4219a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 640x480 desktop mode\n"));
4229a7218c5SRudolf Cornelissen 
4239a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
42477497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
42577497c49SRudolf Cornelissen 	buffer[2] = 0x00;
42677497c49SRudolf Cornelissen 	buffer[3] = 0x80;
42777497c49SRudolf Cornelissen 	buffer[4] = 0x84;
42877497c49SRudolf Cornelissen 	buffer[5] = 0x96;
42977497c49SRudolf Cornelissen 	buffer[6] = 0x60;
43077497c49SRudolf Cornelissen 	buffer[7] = 0x7d;
43177497c49SRudolf Cornelissen 	buffer[8] = 0x22;
43277497c49SRudolf Cornelissen 	buffer[9] = 0xd4;
43377497c49SRudolf Cornelissen 	buffer[10] = 0x27;
43477497c49SRudolf Cornelissen 	buffer[11] = 0x00;
43577497c49SRudolf Cornelissen 	buffer[12] = 0x10;
43677497c49SRudolf Cornelissen 	buffer[13] = 0x7e;
43777497c49SRudolf Cornelissen 	buffer[14] = 0x03;
43877497c49SRudolf Cornelissen 	buffer[15] = 0x58;
43977497c49SRudolf Cornelissen 	buffer[16] = 0x4b;
44077497c49SRudolf Cornelissen 	buffer[17] = 0xe0;
44177497c49SRudolf Cornelissen 	buffer[18] = 0x36;
44277497c49SRudolf Cornelissen 	buffer[19] = 0x92;
44377497c49SRudolf Cornelissen 	buffer[20] = 0x54;
44477497c49SRudolf Cornelissen 	buffer[21] = 0x0e;
44577497c49SRudolf Cornelissen 	buffer[22] = 0x88;
44677497c49SRudolf Cornelissen 	buffer[23] = 0x8c;		//chip-pin CLKI is pixel clock (only non-default here!)
44777497c49SRudolf Cornelissen 	buffer[24] = 0x0a;
44877497c49SRudolf Cornelissen 	buffer[25] = 0xe5;
44977497c49SRudolf Cornelissen 	buffer[26] = 0x76;
45077497c49SRudolf Cornelissen 	buffer[27] = 0x79;
45177497c49SRudolf Cornelissen 	buffer[28] = 0x44;
45277497c49SRudolf Cornelissen 	buffer[29] = 0x85;
45377497c49SRudolf Cornelissen 	buffer[30] = 0x00;
45477497c49SRudolf Cornelissen 	buffer[31] = 0x00;
45577497c49SRudolf Cornelissen 	buffer[32] = 0x80;
45677497c49SRudolf Cornelissen 	buffer[33] = 0x20;
45777497c49SRudolf Cornelissen 	buffer[34] = 0x00;
45877497c49SRudolf Cornelissen 
45977497c49SRudolf Cornelissen 	/* reset status */
46077497c49SRudolf Cornelissen 	i2c_flag_error (-1);
46177497c49SRudolf Cornelissen 
46277497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
46377497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
46477497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
46577497c49SRudolf Cornelissen 	/* log on errors */
46677497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
46777497c49SRudolf Cornelissen 	if (stat)
46877497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640\n"));
46977497c49SRudolf Cornelissen 
47077497c49SRudolf Cornelissen 	return stat;
47177497c49SRudolf Cornelissen }//end BT_init_NTSC640.
47277497c49SRudolf Cornelissen 
47377497c49SRudolf Cornelissen static uint8 BT_init_NTSC800()
474fb6cadf1Sshatty {
47577497c49SRudolf Cornelissen 	uint8 stat;
476fb6cadf1Sshatty 
47777497c49SRudolf Cornelissen 	uint8 buffer[35];
478fb6cadf1Sshatty 
4799a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 800x600 desktop mode\n"));
4809a7218c5SRudolf Cornelissen 
4819a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
48277497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
48377497c49SRudolf Cornelissen 	buffer[2] = 0xa0;
48477497c49SRudolf Cornelissen 	buffer[3] = 0x20;
48577497c49SRudolf Cornelissen 	buffer[4] = 0xb6;
48677497c49SRudolf Cornelissen 	buffer[5] = 0xce;
48777497c49SRudolf Cornelissen 	buffer[6] = 0x84;
48877497c49SRudolf Cornelissen 	buffer[7] = 0x55;
48977497c49SRudolf Cornelissen 	buffer[8] = 0x20;
49077497c49SRudolf Cornelissen 	buffer[9] = 0xd8;
49177497c49SRudolf Cornelissen 	buffer[10] = 0x39;
49277497c49SRudolf Cornelissen 	buffer[11] = 0x00;
49377497c49SRudolf Cornelissen 	buffer[12] = 0x70;
49477497c49SRudolf Cornelissen 	buffer[13] = 0x42;
49577497c49SRudolf Cornelissen 	buffer[14] = 0x03;
49677497c49SRudolf Cornelissen 	buffer[15] = 0xdf;
49777497c49SRudolf Cornelissen 	buffer[16] = 0x56;
49877497c49SRudolf Cornelissen 	buffer[17] = 0x58;
49977497c49SRudolf Cornelissen 	buffer[18] = 0x3a;
50077497c49SRudolf Cornelissen 	buffer[19] = 0xcd;
50177497c49SRudolf Cornelissen 	buffer[20] = 0x9c;
50277497c49SRudolf Cornelissen 	buffer[21] = 0x14;
50377497c49SRudolf Cornelissen 	buffer[22] = 0x3b;
50477497c49SRudolf Cornelissen 	buffer[23] = 0x91;		//chip-pin CLKI is pixel clock (only non-default here!)
50577497c49SRudolf Cornelissen 	buffer[24] = 0x0a;
50677497c49SRudolf Cornelissen 	buffer[25] = 0xe5;
50777497c49SRudolf Cornelissen 	buffer[26] = 0x74;
50877497c49SRudolf Cornelissen 	buffer[27] = 0x77;
50977497c49SRudolf Cornelissen 	buffer[28] = 0x43;
51077497c49SRudolf Cornelissen 	buffer[29] = 0x85;
51177497c49SRudolf Cornelissen 	buffer[30] = 0xba;
51277497c49SRudolf Cornelissen 	buffer[31] = 0xe8;
51377497c49SRudolf Cornelissen 	buffer[32] = 0xa2;
51477497c49SRudolf Cornelissen 	buffer[33] = 0x17;
51577497c49SRudolf Cornelissen 	buffer[34] = 0x00;
51677497c49SRudolf Cornelissen 
51777497c49SRudolf Cornelissen 	/* reset status */
51877497c49SRudolf Cornelissen 	i2c_flag_error (-1);
51977497c49SRudolf Cornelissen 
52077497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
52177497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
52277497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
52377497c49SRudolf Cornelissen 	/* log on errors */
52477497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
52577497c49SRudolf Cornelissen 	if (stat)
52677497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n"));
52777497c49SRudolf Cornelissen 
52877497c49SRudolf Cornelissen 	return stat;
52977497c49SRudolf Cornelissen }//end BT_init_NTSC800.
53077497c49SRudolf Cornelissen 
53177497c49SRudolf Cornelissen static uint8 BT_init_PAL720()
532fb6cadf1Sshatty {
53377497c49SRudolf Cornelissen 	uint8 stat;
53477497c49SRudolf Cornelissen 
53577497c49SRudolf Cornelissen 	uint8 buffer[35];
53677497c49SRudolf Cornelissen 
5379a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 720x576 overscanning DVD mode\n"));
5389a7218c5SRudolf Cornelissen 
5399a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
54077497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
54177497c49SRudolf Cornelissen 	buffer[2] = 0xf0;
54277497c49SRudolf Cornelissen 	buffer[3] = 0xd0;
54377497c49SRudolf Cornelissen 	buffer[4] = 0x82;
54477497c49SRudolf Cornelissen 	buffer[5] = 0x9c;
54577497c49SRudolf Cornelissen 	buffer[6] = 0x5a;
54677497c49SRudolf Cornelissen 	buffer[7] = 0x31;
54777497c49SRudolf Cornelissen 	buffer[8] = 0x16;
54877497c49SRudolf Cornelissen 	buffer[9] = 0x22;
54977497c49SRudolf Cornelissen 	buffer[10] = 0xa6;
55077497c49SRudolf Cornelissen 	buffer[11] = 0x00;
55177497c49SRudolf Cornelissen 	buffer[12] = 0x78;
55277497c49SRudolf Cornelissen 	buffer[13] = 0x93;
55377497c49SRudolf Cornelissen 	buffer[14] = 0x03;
55477497c49SRudolf Cornelissen 	buffer[15] = 0x71;
55577497c49SRudolf Cornelissen 	buffer[16] = 0x2a;
55677497c49SRudolf Cornelissen 	buffer[17] = 0x40;
55777497c49SRudolf Cornelissen 	buffer[18] = 0x0a;
55877497c49SRudolf Cornelissen 	buffer[19] = 0x00;
55977497c49SRudolf Cornelissen 	buffer[20] = 0x50;
56077497c49SRudolf Cornelissen 	buffer[21] = 0x55;
56177497c49SRudolf Cornelissen 	buffer[22] = 0x55;
56277497c49SRudolf Cornelissen 	buffer[23] = 0x8c;		//chip-pin CLKI is pixel clock (only non-default here!)
56377497c49SRudolf Cornelissen 	buffer[24] = 0x24;
56477497c49SRudolf Cornelissen 	buffer[25] = 0xf0;
56577497c49SRudolf Cornelissen 	buffer[26] = 0x59;
56677497c49SRudolf Cornelissen 	buffer[27] = 0x82;
56777497c49SRudolf Cornelissen 	buffer[28] = 0x49;
56877497c49SRudolf Cornelissen 	buffer[29] = 0x8c;
56977497c49SRudolf Cornelissen 	buffer[30] = 0x8e;
57077497c49SRudolf Cornelissen 	buffer[31] = 0xb0;
57177497c49SRudolf Cornelissen 	buffer[32] = 0xe6;
57277497c49SRudolf Cornelissen 	buffer[33] = 0x28;
57377497c49SRudolf Cornelissen 	buffer[34] = 0x00;
57477497c49SRudolf Cornelissen 
57577497c49SRudolf Cornelissen 	/* reset status */
57677497c49SRudolf Cornelissen 	i2c_flag_error (-1);
57777497c49SRudolf Cornelissen 
57877497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
57977497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
58077497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
58177497c49SRudolf Cornelissen 	/* log on errors */
58277497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
58377497c49SRudolf Cornelissen 	if (stat)
58477497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL720\n"));
58577497c49SRudolf Cornelissen 
58677497c49SRudolf Cornelissen 	return stat;
58777497c49SRudolf Cornelissen }//end BT_init_PAL720.
58877497c49SRudolf Cornelissen 
58977497c49SRudolf Cornelissen static uint8 BT_init_NTSC720()
590fb6cadf1Sshatty {
59177497c49SRudolf Cornelissen 	uint8 stat;
592fb6cadf1Sshatty 
59377497c49SRudolf Cornelissen 	uint8 buffer[35];
59477497c49SRudolf Cornelissen 
5959a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 720x480 overscanning DVD mode\n"));
5969a7218c5SRudolf Cornelissen 
5979a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
59877497c49SRudolf Cornelissen 	buffer[1] = 0x76;		//select first bt register to write to.
59977497c49SRudolf Cornelissen 	buffer[2] = 0xf0;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
60077497c49SRudolf Cornelissen 	buffer[3] = 0xd0;		//lsb h_active: h_active = 720 pixels wide port
60177497c49SRudolf Cornelissen 	buffer[4] = 0x83;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
60277497c49SRudolf Cornelissen 	buffer[5] = 0x98;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
60377497c49SRudolf Cornelissen 	buffer[6] = 0x5e;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
60477497c49SRudolf Cornelissen 
60577497c49SRudolf Cornelissen 	//How to find the correct values for h_blank_o and v_blank_o:
60677497c49SRudolf Cornelissen 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
60777497c49SRudolf Cornelissen 	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
60877497c49SRudolf Cornelissen 	//    horizontal position is about OK;
60977497c49SRudolf Cornelissen 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
61077497c49SRudolf Cornelissen 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
61177497c49SRudolf Cornelissen 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
61277497c49SRudolf Cornelissen 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
61377497c49SRudolf Cornelissen 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
61477497c49SRudolf Cornelissen 
61577497c49SRudolf Cornelissen 	buffer[7] = 0x28;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
61677497c49SRudolf Cornelissen 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
61777497c49SRudolf Cornelissen 	buffer[8] = 0x18;	//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
61877497c49SRudolf Cornelissen 
61977497c49SRudolf Cornelissen 	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
62077497c49SRudolf Cornelissen 	buffer[10] = 0x26;		//lsn = msn h_clk_o;
62177497c49SRudolf Cornelissen 							//b4-5 = msbits h_active;
62277497c49SRudolf Cornelissen 							//b7 = b8 v_avtive_o.
62377497c49SRudolf Cornelissen 	buffer[11] = 0x00;		//h_fract is always 0.
62477497c49SRudolf Cornelissen 	buffer[12] = 0x78;		//lsb h_clk_i: h_clk_i is horizontal total = 888.
62577497c49SRudolf Cornelissen 	buffer[13] = 0x90; 	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
62677497c49SRudolf Cornelissen 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
62777497c49SRudolf Cornelissen 						//try-out: b3 = msn h_blank_i;
62877497c49SRudolf Cornelissen 							//b4 = vblankdly is always 0.
62977497c49SRudolf Cornelissen 	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
63077497c49SRudolf Cornelissen 	buffer[16] = 0x1a; 	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
63177497c49SRudolf Cornelissen 						//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
63277497c49SRudolf Cornelissen 	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
63377497c49SRudolf Cornelissen 	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
63477497c49SRudolf Cornelissen 							//b3-2 = msn v_active_i;
63577497c49SRudolf Cornelissen 							//b5-4 = ylpf = 3;
63677497c49SRudolf Cornelissen 							//b7-6 = clpf = 0.
63777497c49SRudolf Cornelissen 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
63877497c49SRudolf Cornelissen 	buffer[20] = 0x50;		//b5-0 = msn v_scale;
63977497c49SRudolf Cornelissen 						//scope: tuned. b7-6 = msn h_blank_o.
64077497c49SRudolf Cornelissen 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
64177497c49SRudolf Cornelissen 	buffer[21] = 0x98;		//lsb PLL fract: PLL fract = 0x6e98
64277497c49SRudolf Cornelissen 	buffer[22] = 0x6e;		//msb PLL fract
64377497c49SRudolf Cornelissen 	buffer[23] = 0x8c;		//b5-0 = PLL int: PLL int = 0x0c;
64477497c49SRudolf Cornelissen 							//b6 = by_pll: by_pll = 0;
64577497c49SRudolf Cornelissen 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
64677497c49SRudolf Cornelissen 	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
64777497c49SRudolf Cornelissen 							//b1 = setup = 1 for NTSC;
64877497c49SRudolf Cornelissen 							//b2 = 625line = 0 for NTSC;
64977497c49SRudolf Cornelissen 							//b3 = vsync_dur = 1 for NTSC;
65077497c49SRudolf Cornelissen 							//b4 = dic_screset is always 0;
65177497c49SRudolf Cornelissen 							//b5 = pal_md = 0 for NTSC;
65277497c49SRudolf Cornelissen 							//b6 = eclip is always 0;
65377497c49SRudolf Cornelissen 							//b7 = reserved (en_scart) is always 0.
65477497c49SRudolf Cornelissen 	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
65577497c49SRudolf Cornelissen 	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
65677497c49SRudolf Cornelissen 	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
65777497c49SRudolf Cornelissen 	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
65877497c49SRudolf Cornelissen 	buffer[29] = 0x85;		//my: y $85 for NTSC
65977497c49SRudolf Cornelissen 	buffer[30] = 0x3c;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
66077497c49SRudolf Cornelissen 	buffer[31] = 0x91;		//msc = $20c2913c
66177497c49SRudolf Cornelissen 	buffer[32] = 0xc2;
66277497c49SRudolf Cornelissen 	buffer[33] = 0x20;		//msb msc.
66377497c49SRudolf Cornelissen 	buffer[34] = 0x00;		//phase_off always $00
66477497c49SRudolf Cornelissen 
66577497c49SRudolf Cornelissen 	/* reset status */
66677497c49SRudolf Cornelissen 	i2c_flag_error (-1);
66777497c49SRudolf Cornelissen 
66877497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
66977497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
67077497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
67177497c49SRudolf Cornelissen 	/* log on errors */
67277497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
67377497c49SRudolf Cornelissen 	if (stat)
67477497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC720\n"));
67577497c49SRudolf Cornelissen 
67677497c49SRudolf Cornelissen 	return stat;
67777497c49SRudolf Cornelissen }//end BT_init_NTSC720.
67877497c49SRudolf Cornelissen 
67977497c49SRudolf Cornelissen static uint8 BT_init_PAL800_OS()
680fb6cadf1Sshatty {
68177497c49SRudolf Cornelissen 	uint8 stat;
682fb6cadf1Sshatty 
68377497c49SRudolf Cornelissen 	uint8 buffer[35];
68477497c49SRudolf Cornelissen 
6859a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 800x600 overscanning VCD mode\n"));
6869a7218c5SRudolf Cornelissen 
6879a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
68877497c49SRudolf Cornelissen 	buffer[1] = 0x76;		//select first bt register to write to.
68977497c49SRudolf Cornelissen 	buffer[2] = 0x60;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
69077497c49SRudolf Cornelissen 	buffer[3] = 0x20;		//lsb h_active: h_active = 800 pixels wide port
69177497c49SRudolf Cornelissen 	buffer[4] = 0x8b;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 64.0uS = 4.70uS for PAL
69277497c49SRudolf Cornelissen 	buffer[5] = 0xa5;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 64.0uS = 5.6uS for PAL
69377497c49SRudolf Cornelissen 	buffer[6] = 0x6b;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 64.0uS = 7.97uS for PAL
69477497c49SRudolf Cornelissen 
69577497c49SRudolf Cornelissen 	//How to find the correct values for h_blank_o and v_blank_o:
69677497c49SRudolf Cornelissen 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
69777497c49SRudolf Cornelissen 	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
69877497c49SRudolf Cornelissen 	//    horizontal position is about OK;
69977497c49SRudolf Cornelissen 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
70077497c49SRudolf Cornelissen 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
70177497c49SRudolf Cornelissen 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
70277497c49SRudolf Cornelissen 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
70377497c49SRudolf Cornelissen 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
70477497c49SRudolf Cornelissen 
70577497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
706fb6cadf1Sshatty 	{
7074e918a7cSRudolf Cornelissen 		//fixme if needed: (added 0x10 for BT)..
70877497c49SRudolf Cornelissen 		buffer[7] = 0xf4;
70977497c49SRudolf Cornelissen 		buffer[8] = 0x17;
710fb6cadf1Sshatty 	}
711fb6cadf1Sshatty 	else
71277497c49SRudolf Cornelissen 	{	//set BT value
7134e918a7cSRudolf Cornelissen 		/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
7146245f19cSRudolf Cornelissen 		buffer[7] = 0xd0;//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
71577497c49SRudolf Cornelissen 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 64.0uS = 10.0uS for PAL)
71677497c49SRudolf Cornelissen 		buffer[8] = 0x18;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
71777497c49SRudolf Cornelissen 	}
71877497c49SRudolf Cornelissen 
71977497c49SRudolf Cornelissen 	buffer[9] = 0x2e;		//v_active_o: = (active output lines + 2) / field (on TV)
72077497c49SRudolf Cornelissen 	buffer[10] = 0xb7;		//lsn = msn h_clk_o;
72177497c49SRudolf Cornelissen 							//b4-5 = msbits h_active;
72277497c49SRudolf Cornelissen 							//b7 = b8 v_avtive_o.
72377497c49SRudolf Cornelissen 	buffer[11] = 0x00;		//h_fract is always 0.
72477497c49SRudolf Cornelissen 	buffer[12] = 0xb0;		//lsb h_clk_i: h_clk_i is horizontal total = 944.
72577497c49SRudolf Cornelissen 
72677497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
72777497c49SRudolf Cornelissen 		buffer[13] = 0x20;
72877497c49SRudolf Cornelissen 	else				//set BT value
72977497c49SRudolf Cornelissen 		buffer[13] = 0x14;//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
73077497c49SRudolf Cornelissen 
73177497c49SRudolf Cornelissen 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
73277497c49SRudolf Cornelissen 					 	//try-out: b3 = msn h_blank_i;
73377497c49SRudolf Cornelissen 							//b4 = vblankdly is always 0.
73477497c49SRudolf Cornelissen 	buffer[15] = 0x71;		//lsb v_lines_i: v_lines_i = 625
73577497c49SRudolf Cornelissen 
73677497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
73777497c49SRudolf Cornelissen 		buffer[16] = 0x08;
73877497c49SRudolf Cornelissen 	else				//set BT value
73977497c49SRudolf Cornelissen 		buffer[16] = 0x2a;//try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
74077497c49SRudolf Cornelissen 					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
74177497c49SRudolf Cornelissen 
74277497c49SRudolf Cornelissen 	buffer[17] = 0x58;		//lsb v_active_i: v_active_i = 600
74377497c49SRudolf Cornelissen 	buffer[18] = 0x3a;		//b1-0 = msn v_lines_i;
74477497c49SRudolf Cornelissen 							//b3-2 = msn v_active_i;
74577497c49SRudolf Cornelissen 							//b5-4 = ylpf = 3;
74677497c49SRudolf Cornelissen 							//b7-6 = clpf = 0.
74777497c49SRudolf Cornelissen 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
74877497c49SRudolf Cornelissen 	buffer[20] = 0x10;		//b5-0 = msn v_scale;
74977497c49SRudolf Cornelissen 						//scope: tuned. b7-6 = msn h_blank_o.
75077497c49SRudolf Cornelissen 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 50Hz)
75177497c49SRudolf Cornelissen 	buffer[21] = 0x72;		//lsb PLL fract: PLL fract = 0x1c72
75277497c49SRudolf Cornelissen 	buffer[22] = 0x1c;		//msb PLL fract
75377497c49SRudolf Cornelissen 	buffer[23] = 0x8d;		//b5-0 = PLL int: PLL int = 0x0d;
75477497c49SRudolf Cornelissen 							//b6 = by_pll: by_pll = 0;
75577497c49SRudolf Cornelissen 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
75677497c49SRudolf Cornelissen 	buffer[24] = 0x24;		//b0 = ni_out is always 0;
75777497c49SRudolf Cornelissen 							//b1 = setup = 0 for PAL;
75877497c49SRudolf Cornelissen 							//b2 = 625line = 1 for PAL;
75977497c49SRudolf Cornelissen 							//b3 = vsync_dur = 0 for PAL;
76077497c49SRudolf Cornelissen 							//b4 = dic_screset is always 0;
76177497c49SRudolf Cornelissen 							//b5 = pal_md = 1 for PAL;
76277497c49SRudolf Cornelissen 							//b6 = eclip is always 0;
76377497c49SRudolf Cornelissen 							//b7 = reserved (en_scart) is always 0.
76477497c49SRudolf Cornelissen 	buffer[25] = 0xf0;		//sync_amp $f0 for PAL
76577497c49SRudolf Cornelissen 	buffer[26] = 0x57;		//bst_amp $57-$58 for PAL
76677497c49SRudolf Cornelissen 	buffer[27] = 0x80;		//mcr: r-y $80-$81 for PAL
76777497c49SRudolf Cornelissen 	buffer[28] = 0x48;		//mcb: b-y $48-$49 for PAL
76877497c49SRudolf Cornelissen 	buffer[29] = 0x8c;		//my: y $8c for PAL
76977497c49SRudolf Cornelissen 	buffer[30] = 0x31;		//lsb msc: msc b31-0: PAL formula: ((4433619 / pixelclk) * 2^32) = MSC
77077497c49SRudolf Cornelissen 	buffer[31] = 0x8c;		//msc = $26798c31
77177497c49SRudolf Cornelissen 	buffer[32] = 0x79;
77277497c49SRudolf Cornelissen 	buffer[33] = 0x26;		//msb msc.
77377497c49SRudolf Cornelissen 	buffer[34] = 0x00;		//phase_off always $00
77477497c49SRudolf Cornelissen 
77577497c49SRudolf Cornelissen 	/* reset status */
77677497c49SRudolf Cornelissen 	i2c_flag_error (-1);
77777497c49SRudolf Cornelissen 
77877497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
77977497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
78077497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
78177497c49SRudolf Cornelissen 	/* log on errors */
78277497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
78377497c49SRudolf Cornelissen 	if (stat)
78477497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800 OS\n"));
78577497c49SRudolf Cornelissen 
78677497c49SRudolf Cornelissen 	return stat;
78777497c49SRudolf Cornelissen }//end BT_init_PAL800_OS.
78877497c49SRudolf Cornelissen 
78977497c49SRudolf Cornelissen static uint8 BT_init_NTSC640_OS()
790fb6cadf1Sshatty {
79177497c49SRudolf Cornelissen 	uint8 stat;
792fb6cadf1Sshatty 
79377497c49SRudolf Cornelissen 	uint8 buffer[35];
794fb6cadf1Sshatty 
7959a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 640x480 overscanning VCD mode\n"));
7969a7218c5SRudolf Cornelissen 
7979a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
79877497c49SRudolf Cornelissen 	buffer[1] = 0x76;		//select first bt register to write to.
79977497c49SRudolf Cornelissen 	buffer[2] = 0x20;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
80077497c49SRudolf Cornelissen 	buffer[3] = 0x80;		//lsb h_active: h_active = 640 pixels wide port
80177497c49SRudolf Cornelissen 	buffer[4] = 0x74;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
80277497c49SRudolf Cornelissen 	buffer[5] = 0x83;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
80377497c49SRudolf Cornelissen 	buffer[6] = 0x44;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
804fb6cadf1Sshatty 
80577497c49SRudolf Cornelissen 	//How to find the correct values for h_blank_o and v_blank_o:
80677497c49SRudolf Cornelissen 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
80777497c49SRudolf Cornelissen 	// 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while
80877497c49SRudolf Cornelissen 	//    horizontal position is about OK;
80977497c49SRudolf Cornelissen 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
81077497c49SRudolf Cornelissen 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
81177497c49SRudolf Cornelissen 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
81277497c49SRudolf Cornelissen 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
81377497c49SRudolf Cornelissen 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
814fb6cadf1Sshatty 
81577497c49SRudolf Cornelissen 	buffer[7] = 0xf7;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV:
81677497c49SRudolf Cornelissen 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
817fb6cadf1Sshatty 
81877497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
81977497c49SRudolf Cornelissen 		buffer[8] = 0x1d;
82077497c49SRudolf Cornelissen 	else				//set BT value
82177497c49SRudolf Cornelissen 		buffer[8] = 0x1c;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
822fb6cadf1Sshatty 
82377497c49SRudolf Cornelissen 	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
82477497c49SRudolf Cornelissen 	buffer[10] = 0x26;		//lsn = msn h_clk_o;
82577497c49SRudolf Cornelissen 							//b4-5 = msbits h_active;
82677497c49SRudolf Cornelissen 							//b7 = b8 v_avtive_o.
82777497c49SRudolf Cornelissen 	buffer[11] = 0x00;		//h_fract is always 0.
82877497c49SRudolf Cornelissen 	buffer[12] = 0x10;		//lsb h_clk_i: h_clk_i is horizontal total = 784.
82977497c49SRudolf Cornelissen 	buffer[13] = 0x14;	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
83077497c49SRudolf Cornelissen 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
83177497c49SRudolf Cornelissen 						//try-out: b3 = msn h_blank_i;
83277497c49SRudolf Cornelissen 							//b4 = vblankdly is always 0.
83377497c49SRudolf Cornelissen 	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
83477497c49SRudolf Cornelissen 	buffer[16] = 0x18;	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
83577497c49SRudolf Cornelissen 					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
83677497c49SRudolf Cornelissen 	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
83777497c49SRudolf Cornelissen 	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
83877497c49SRudolf Cornelissen 							//b3-2 = msn v_active_i;
83977497c49SRudolf Cornelissen 							//b5-4 = ylpf = 3;
84077497c49SRudolf Cornelissen 							//b7-6 = clpf = 0.
84177497c49SRudolf Cornelissen 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
84277497c49SRudolf Cornelissen 	buffer[20] = 0x10;		//b5-0 = msn v_scale;
84377497c49SRudolf Cornelissen 						//scope: tuned. b7-6 = msn h_blank_o.
84477497c49SRudolf Cornelissen 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
84577497c49SRudolf Cornelissen 	buffer[21] = 0xdb;		//lsb PLL fract: PLL fract = 0xf9db
84677497c49SRudolf Cornelissen 	buffer[22] = 0xf9;		//msb PLL fract
84777497c49SRudolf Cornelissen 	buffer[23] = 0x8a;		//b5-0 = PLL int: PLL int = 0x0a;
84877497c49SRudolf Cornelissen 							//b6 = by_pll: by_pll = 0;
84977497c49SRudolf Cornelissen 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
85077497c49SRudolf Cornelissen 	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
85177497c49SRudolf Cornelissen 							//b1 = setup = 1 for NTSC;
85277497c49SRudolf Cornelissen 							//b2 = 625line = 0 for NTSC;
85377497c49SRudolf Cornelissen 							//b3 = vsync_dur = 1 for NTSC;
85477497c49SRudolf Cornelissen 							//b4 = dic_screset is always 0;
85577497c49SRudolf Cornelissen 							//b5 = pal_md = 0 for NTSC;
85677497c49SRudolf Cornelissen 							//b6 = eclip is always 0;
85777497c49SRudolf Cornelissen 							//b7 = reserved (en_scart) is always 0.
85877497c49SRudolf Cornelissen 	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
85977497c49SRudolf Cornelissen 	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
86077497c49SRudolf Cornelissen 	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
86177497c49SRudolf Cornelissen 	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
86277497c49SRudolf Cornelissen 	buffer[29] = 0x85;		//my: y $85 for NTSC
86377497c49SRudolf Cornelissen 	buffer[30] = 0x37;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
86477497c49SRudolf Cornelissen 	buffer[31] = 0x12;		//msc = $251b1237
86577497c49SRudolf Cornelissen 	buffer[32] = 0x1b;
86677497c49SRudolf Cornelissen 	buffer[33] = 0x25;		//msb msc.
86777497c49SRudolf Cornelissen 	buffer[34] = 0x00;		//phase_off always $00
868fb6cadf1Sshatty 
86977497c49SRudolf Cornelissen 	/* reset status */
87077497c49SRudolf Cornelissen 	i2c_flag_error (-1);
871fb6cadf1Sshatty 
87277497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
87377497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
87477497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
87577497c49SRudolf Cornelissen 	/* log on errors */
87677497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
87777497c49SRudolf Cornelissen 	if (stat)
87877497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640 OS\n"));
879fb6cadf1Sshatty 
88077497c49SRudolf Cornelissen 	return stat;
88177497c49SRudolf Cornelissen }//end BT_init_NTSC640_OS.
882fb6cadf1Sshatty 
88321f6ecabSRudolf Cornelissen static uint8 BT_testsignal(void)
88421f6ecabSRudolf Cornelissen {
88521f6ecabSRudolf Cornelissen 	uint8 stat;
88621f6ecabSRudolf Cornelissen 
88721f6ecabSRudolf Cornelissen 	uint8 buffer[3];
88821f6ecabSRudolf Cornelissen 
8899a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Enabling testsignal\n"));
8909a7218c5SRudolf Cornelissen 
89121f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
89221f6ecabSRudolf Cornelissen 	/* select bt register for enabling colorbars and outputs */
89321f6ecabSRudolf Cornelissen 	buffer[1] = 0xc4;
89421f6ecabSRudolf Cornelissen 	/* issue the actual command */
89521f6ecabSRudolf Cornelissen 	buffer[2] = 0x05;
89621f6ecabSRudolf Cornelissen 
89721f6ecabSRudolf Cornelissen 	/* reset status */
89821f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
89921f6ecabSRudolf Cornelissen 
90021f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
90121f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
90221f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
90321f6ecabSRudolf Cornelissen 	/* log on errors */
90421f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
90521f6ecabSRudolf Cornelissen 	if (stat)
90621f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
90721f6ecabSRudolf Cornelissen 
90821f6ecabSRudolf Cornelissen 	return stat;
90921f6ecabSRudolf Cornelissen }//end BT_testsignal.
91021f6ecabSRudolf Cornelissen 
91121f6ecabSRudolf Cornelissen static uint8 BT_setup_output(uint8 monstat, uint8 output, uint8 ffilter)
91221f6ecabSRudolf Cornelissen {
91321f6ecabSRudolf Cornelissen 	uint8 stat;
91421f6ecabSRudolf Cornelissen 
91521f6ecabSRudolf Cornelissen 	uint8 buffer[7];
91621f6ecabSRudolf Cornelissen 
91721f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
91821f6ecabSRudolf Cornelissen 	/* select first TV config register to write */
91921f6ecabSRudolf Cornelissen 	buffer[1] = 0xc6;
92021f6ecabSRudolf Cornelissen 	/* input is 24bit mpx'd RGB, BLANK = out, sync = act. hi */
92121f6ecabSRudolf Cornelissen 	buffer[2] = 0x98;
92221f6ecabSRudolf Cornelissen 	/* disable all filters, exept flicker filter */
92321f6ecabSRudolf Cornelissen 	buffer[3] = 0x98;
92421f6ecabSRudolf Cornelissen 	if (!ffilter)
92521f6ecabSRudolf Cornelissen 	{
92621f6ecabSRudolf Cornelissen 		/* disable flicker filter */
92721f6ecabSRudolf Cornelissen 		buffer[3] = 0xc0;
9289a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Disabling flickerfilter\n"));
92921f6ecabSRudolf Cornelissen 	}
9309a7218c5SRudolf Cornelissen 	else
9319a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Enabling flickerfilter\n"));
9329a7218c5SRudolf Cornelissen 
93321f6ecabSRudolf Cornelissen 	/* (disable filters) */
93421f6ecabSRudolf Cornelissen 	buffer[4] = 0xc0;
93521f6ecabSRudolf Cornelissen 	/* (disable filters) */
93621f6ecabSRudolf Cornelissen 	buffer[5] = 0xc0;
93721f6ecabSRudolf Cornelissen 	switch (output)
93821f6ecabSRudolf Cornelissen 	/* Description of ELSA Erazor III hardware layout:
93921f6ecabSRudolf Cornelissen 	 * (This is the default (recommended) layout by NVIDIA)
94021f6ecabSRudolf Cornelissen 	 * DAC A = CVBS
94121f6ecabSRudolf Cornelissen 	 * DAC B = C (chrominance)
94221f6ecabSRudolf Cornelissen 	 * DAC C = Y (luminance) */
94321f6ecabSRudolf Cornelissen 
94421f6ecabSRudolf Cornelissen 	/* Description of Diamond VIPER550:
94521f6ecabSRudolf Cornelissen 	 * DAC A = Not connected
94621f6ecabSRudolf Cornelissen 	 * DAC B = C (chrominance)
94721f6ecabSRudolf Cornelissen 	 * DAC C = Y (luminance)
94821f6ecabSRudolf Cornelissen 	 * To be able to connect to CVBS TV's a special cable is supplied:
94921f6ecabSRudolf Cornelissen 	 * This cable connects the Y (DAC C) output to the TV CVBS input. */
95021f6ecabSRudolf Cornelissen 	{
9519a7218c5SRudolf Cornelissen 	case 1:
9529a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n"));
9539a7218c5SRudolf Cornelissen 		buffer[6] = 0x18;	// Y/C and CVBS out if all ports implemented
95421f6ecabSRudolf Cornelissen 							// in hardware, else only Y/C or CVBS out.
95521f6ecabSRudolf Cornelissen 		break;
9569a7218c5SRudolf Cornelissen 	case 2:
9579a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Outputting CVBS on all outputs\n"));
9589a7218c5SRudolf Cornelissen 		buffer[6] = 0x00;	// put CVBS on all outputs. Used for cards
95921f6ecabSRudolf Cornelissen 		break;				// with only Y/C out and 'translation cable'.
9609a7218c5SRudolf Cornelissen 	default:
961b0fce481SRudolf Cornelissen 		LOG(4,("Brooktree: Outputting signals according to autodetect status:\n"));
9629a7218c5SRudolf Cornelissen 		switch (monstat)	// only 'autodetect' remains...
96321f6ecabSRudolf Cornelissen 		{
9649a7218c5SRudolf Cornelissen 		case 1:
965b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: Only Y connected, outputting CVBS on all outputs\n"));
9669a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//only Y connected: must be CVBS!
96721f6ecabSRudolf Cornelissen 			break;
9689a7218c5SRudolf Cornelissen 		case 2:
969b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: Only C connected, outputting CVBS on all outputs\n"));
9709a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//only C connected: must be CVBS!
97121f6ecabSRudolf Cornelissen 			break;				//(though cable is wired wrong...)
9729a7218c5SRudolf Cornelissen 		case 5:
973b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: CVBS and only Y connected, outputting CVBS on all outputs\n"));
9749a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//CVBS and only Y connected: 2x CVBS!
97521f6ecabSRudolf Cornelissen 			break;			   	//(officially not supported...)
9769a7218c5SRudolf Cornelissen 		case 6:
977b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: CVBS and only C connected, outputting CVBS on all outputs\n"));
9789a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//CVBS and only C connected: 2x CVBS!
97921f6ecabSRudolf Cornelissen 			break;			   	//(officially not supported...)
9809a7218c5SRudolf Cornelissen 		default:
981b0fce481SRudolf Cornelissen 			LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n"));
9829a7218c5SRudolf Cornelissen 			buffer[6] = 0x18;	//nothing, or
98321f6ecabSRudolf Cornelissen 							 	//Y/C only, or
98421f6ecabSRudolf Cornelissen 							 	//CVBS only (but on CVBS output), or
98521f6ecabSRudolf Cornelissen 							 	//Y/C and CVBS connected:
98621f6ecabSRudolf Cornelissen 							 	//So activate recommended signals.
98721f6ecabSRudolf Cornelissen 		}
98821f6ecabSRudolf Cornelissen 	}
98921f6ecabSRudolf Cornelissen 
99021f6ecabSRudolf Cornelissen 	/* reset status */
99121f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
99221f6ecabSRudolf Cornelissen 
99321f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
99421f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
99521f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
99621f6ecabSRudolf Cornelissen 	/* log on errors */
99721f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
99821f6ecabSRudolf Cornelissen 	if (stat)
99921f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
100021f6ecabSRudolf Cornelissen 
100121f6ecabSRudolf Cornelissen 	return stat;
100221f6ecabSRudolf Cornelissen }//end BT_setup_output.
100321f6ecabSRudolf Cornelissen 
100421f6ecabSRudolf Cornelissen static uint8 BT_setup_hphase(uint8 mode)
100521f6ecabSRudolf Cornelissen {
100621f6ecabSRudolf Cornelissen 	uint8 stat, hoffset;
100721f6ecabSRudolf Cornelissen 
100821f6ecabSRudolf Cornelissen 	uint8 buffer[7];
100921f6ecabSRudolf Cornelissen 
10109a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Tuning horizontal phase\n"));
10119a7218c5SRudolf Cornelissen 
101221f6ecabSRudolf Cornelissen 	/* CX needs timing reset (advised on BT also), first 1mS delay needed! */
101321f6ecabSRudolf Cornelissen 	snooze(1000);
101421f6ecabSRudolf Cornelissen 
101521f6ecabSRudolf Cornelissen 	/* values below are all tested on TNT1, TNT2 and GeForce2MX */
101621f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
101721f6ecabSRudolf Cornelissen 	/* select first TV output timing register to write */
101821f6ecabSRudolf Cornelissen 	buffer[1] = 0x6c;
101921f6ecabSRudolf Cornelissen 	/* turn on active video & generate timing reset on CX chips! */
102021f6ecabSRudolf Cornelissen 	buffer[2] = 0x86;
102121f6ecabSRudolf Cornelissen 	/* (set fail save values...) */
102221f6ecabSRudolf Cornelissen 	buffer[3] = 0x00;		//set default horizontal sync offset
102321f6ecabSRudolf Cornelissen 	buffer[4] = 0x02;		//set default horizontal sync width
102421f6ecabSRudolf Cornelissen 	buffer[5] = 0x00;		//set default vertical sync offset
102521f6ecabSRudolf Cornelissen 
102621f6ecabSRudolf Cornelissen 	/* do specific timing setup for all chips and modes: */
1027*4594e58aSRudolf Cornelissen 	switch (si->ps.card_type)
1028b0fce481SRudolf Cornelissen 	{
1029*4594e58aSRudolf Cornelissen 	case NV05:
1030*4594e58aSRudolf Cornelissen 	case NV05M64:
1031*4594e58aSRudolf Cornelissen 	case NV15:
1032*4594e58aSRudolf Cornelissen 		/* confirmed TNT2, TNT2M64, GeForce2Ti.
1033b0fce481SRudolf Cornelissen 		 * (8 pixels delayed hpos, so picture more to the right) */
1034b0fce481SRudolf Cornelissen 		hoffset = 8;
1035*4594e58aSRudolf Cornelissen 		break;
1036*4594e58aSRudolf Cornelissen 	default:
1037*4594e58aSRudolf Cornelissen 		/* confirmed TNT1, GeForce256, GeForce2MX.
1038b0fce481SRudolf Cornelissen 		 * (std hpos)
1039b0fce481SRudolf Cornelissen 		 * NOTE: It might be that GeForce needs TNT2 offset:
1040b0fce481SRudolf Cornelissen 		 * for now CX chips get seperate extra offset, until sure.
1041b0fce481SRudolf Cornelissen 		 * (CX is only found AFAIK on GeForce cards, no BT tested
1042b0fce481SRudolf Cornelissen 		 * on GeForce yet. CH was tested on GeForce and seemed to
1043b0fce481SRudolf Cornelissen 		 * indicate TNT1 offset was needed.) */
1044b0fce481SRudolf Cornelissen 		hoffset = 0;
1045*4594e58aSRudolf Cornelissen 		break;
1046b0fce481SRudolf Cornelissen 	}
104721f6ecabSRudolf Cornelissen 
104821f6ecabSRudolf Cornelissen 	switch (mode)
104921f6ecabSRudolf Cornelissen 	{
105021f6ecabSRudolf Cornelissen 	case NTSC640_TST:
105121f6ecabSRudolf Cornelissen 	case NTSC640:
10524e918a7cSRudolf Cornelissen 		//fixme if needed (subtracted 0x07 for BT)..
105321f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
10544e918a7cSRudolf Cornelissen 		/* confirmed on TNT1 with BT869 using 4:3 TV and 16:9 TV */
1055f2069d6cSRudolf Cornelissen 		buffer[3] = (0x1e + hoffset);	//set horizontal sync offset
105621f6ecabSRudolf Cornelissen 		break;
105721f6ecabSRudolf Cornelissen 	case NTSC800:
105821f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
105921f6ecabSRudolf Cornelissen 		buffer[3] = (0xe1 + hoffset);	//set horizontal sync offset
106021f6ecabSRudolf Cornelissen 		buffer[4] = 0xc2;
106121f6ecabSRudolf Cornelissen 		//Vsync offset reg. does not exist on CX: mode is checked and OK.
106221f6ecabSRudolf Cornelissen 		buffer[5] = 0x40;				//set VSync offset (on BT's only)
106321f6ecabSRudolf Cornelissen 		break;
106421f6ecabSRudolf Cornelissen 	case PAL640:
106521f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
106621f6ecabSRudolf Cornelissen 		buffer[3] = (0xa8 + hoffset);
106721f6ecabSRudolf Cornelissen 		break;
106821f6ecabSRudolf Cornelissen 	case PAL800_TST:
106921f6ecabSRudolf Cornelissen 	case PAL800:
107021f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
107121f6ecabSRudolf Cornelissen 		buffer[3] = (0x2c + hoffset);
107221f6ecabSRudolf Cornelissen 		break;
107321f6ecabSRudolf Cornelissen 	case NTSC720:
107421f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870)
107521f6ecabSRudolf Cornelissen 			buffer[3] = (0xb2 + hoffset); //set horizontal sync offset CX
107621f6ecabSRudolf Cornelissen 		else
107721f6ecabSRudolf Cornelissen 			buffer[3] = (0xd0 + hoffset); //set horizontal sync offset BT
107821f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;				//hsync width = max:
107921f6ecabSRudolf Cornelissen 		break;							//to prevent vertical image 'shivering'.
108021f6ecabSRudolf Cornelissen 	case PAL720:
108121f6ecabSRudolf Cornelissen 		buffer[3] = (0xd4 + hoffset);
108221f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;
108321f6ecabSRudolf Cornelissen 		break;
108421f6ecabSRudolf Cornelissen 	case NTSC640_OS:
108521f6ecabSRudolf Cornelissen 		buffer[3] = (0xc8 + hoffset);
108621f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;
108721f6ecabSRudolf Cornelissen 		break;
108821f6ecabSRudolf Cornelissen 	case PAL800_OS:
108921f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870)
109021f6ecabSRudolf Cornelissen 			buffer[3] = (0x78 + hoffset); //set horizontal sync offset CX
109121f6ecabSRudolf Cornelissen 		else
109221f6ecabSRudolf Cornelissen 			buffer[3] = (0xc4 + hoffset); //set horizontal sync offset BT
109321f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;
109421f6ecabSRudolf Cornelissen 		break;
109521f6ecabSRudolf Cornelissen 	default: //nothing to be done here...
109621f6ecabSRudolf Cornelissen 		break;
109721f6ecabSRudolf Cornelissen 	}
109821f6ecabSRudolf Cornelissen 
109921f6ecabSRudolf Cornelissen 	buffer[6] = 0x01;		//set default vertical sync width
110021f6ecabSRudolf Cornelissen 
110121f6ecabSRudolf Cornelissen 	/* reset status */
110221f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
110321f6ecabSRudolf Cornelissen 
110421f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
110521f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
110621f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
110721f6ecabSRudolf Cornelissen 	/* log on errors */
110821f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
110921f6ecabSRudolf Cornelissen 	if (stat)
111021f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting up h_phase\n"));
111121f6ecabSRudolf Cornelissen 
111221f6ecabSRudolf Cornelissen 	return stat;
111321f6ecabSRudolf Cornelissen }//end BT_setup_hphase.
111421f6ecabSRudolf Cornelissen 
111521f6ecabSRudolf Cornelissen static uint8 BT_read_monstat(uint8* monstat)
111621f6ecabSRudolf Cornelissen {
111721f6ecabSRudolf Cornelissen 	uint8 stat;
111821f6ecabSRudolf Cornelissen 	uint8 buffer[3];
111921f6ecabSRudolf Cornelissen 
1120efe9c7a6SRudolf Cornelissen 	/* make sure we have the recommended failsafe selected */
1121efe9c7a6SRudolf Cornelissen 	*monstat = 0;
1122efe9c7a6SRudolf Cornelissen 
11239a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Autodetecting connected output devices\n"));
11249a7218c5SRudolf Cornelissen 
112521f6ecabSRudolf Cornelissen 	/* set BT to return connection status in ESTATUS on next read CMD: */
112621f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
112721f6ecabSRudolf Cornelissen 	/* set ESTATUS at b'01' (return conn.stat.) */
112821f6ecabSRudolf Cornelissen 	buffer[1] = 0xc4;
112921f6ecabSRudolf Cornelissen 	/* and leave chip outputs on. */
113021f6ecabSRudolf Cornelissen 	buffer[2] = 0x41;
113121f6ecabSRudolf Cornelissen 
113221f6ecabSRudolf Cornelissen 	/* reset status */
113321f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
113421f6ecabSRudolf Cornelissen 
113521f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
113621f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
113721f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
113821f6ecabSRudolf Cornelissen 	/* log on errors */
113921f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
114021f6ecabSRudolf Cornelissen 	if (stat)
114121f6ecabSRudolf Cornelissen 	{
114221f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (1)\n"));
114321f6ecabSRudolf Cornelissen 		return stat;
114421f6ecabSRudolf Cornelissen 	}
114521f6ecabSRudolf Cornelissen 
114621f6ecabSRudolf Cornelissen 	/* do actual read connection status: */
114721f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
114821f6ecabSRudolf Cornelissen 	/* select register with CHECK_STAT CMD */
114921f6ecabSRudolf Cornelissen 	buffer[1] = 0xba;
115021f6ecabSRudolf Cornelissen 	/* issue actual command. */
115121f6ecabSRudolf Cornelissen 	buffer[2] = 0x40;
115221f6ecabSRudolf Cornelissen 
115321f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
115421f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
115521f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
115621f6ecabSRudolf Cornelissen 	/* log on errors */
115721f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
115821f6ecabSRudolf Cornelissen 	if (stat)
115921f6ecabSRudolf Cornelissen 	{
116021f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (2)\n"));
116121f6ecabSRudolf Cornelissen 		return stat;
116221f6ecabSRudolf Cornelissen 	}
116321f6ecabSRudolf Cornelissen 
116421f6ecabSRudolf Cornelissen 	/* CX: Wait 600uS for signals to stabilize (see datasheet) */
116521f6ecabSRudolf Cornelissen 	/* warning, note:
116621f6ecabSRudolf Cornelissen 	 * datasheet is in error! 60mS needed!! */
116721f6ecabSRudolf Cornelissen 	snooze(60000);
116821f6ecabSRudolf Cornelissen 
116921f6ecabSRudolf Cornelissen 	/* read back updated connection status: */
117021f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + RD;
117121f6ecabSRudolf Cornelissen 
117221f6ecabSRudolf Cornelissen 	/* transmit 1 byte */
117321f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
117421f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 1);
117521f6ecabSRudolf Cornelissen 
117621f6ecabSRudolf Cornelissen 	/* receive 1 byte */
11779a7218c5SRudolf Cornelissen 	/* ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec)
117821f6ecabSRudolf Cornelissen 	 * While the BT's don't care, CX chips will block the SDA line if an ACK gets sent! */
117921f6ecabSRudolf Cornelissen 	buffer[0] = 1;
118021f6ecabSRudolf Cornelissen 	i2c_readbuffer(si->ps.tv_encoder.bus, buffer, 1);
118121f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
118221f6ecabSRudolf Cornelissen 	/* log on errors */
118321f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
118421f6ecabSRudolf Cornelissen 	if (stat)
118521f6ecabSRudolf Cornelissen 	{
118621f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (3)\n"));
118721f6ecabSRudolf Cornelissen 		return stat;
118821f6ecabSRudolf Cornelissen 	}
118921f6ecabSRudolf Cornelissen 
119021f6ecabSRudolf Cornelissen 	*monstat = ((buffer[0] & 0xe0) >> 5);
119121f6ecabSRudolf Cornelissen 	LOG(4,("Brooktree: TV output monitor status = %d\n", *monstat));
119221f6ecabSRudolf Cornelissen 
119321f6ecabSRudolf Cornelissen 	/* instruct BT to go back to normal operation: */
119421f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
119521f6ecabSRudolf Cornelissen 	/* select register with CHECK_STAT CMD */
119621f6ecabSRudolf Cornelissen 	buffer[1] = 0xba;
119721f6ecabSRudolf Cornelissen 	/* issue actual command. */
119821f6ecabSRudolf Cornelissen 	buffer[2] = 0x00;
119921f6ecabSRudolf Cornelissen 
120021f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
120121f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
120221f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
120321f6ecabSRudolf Cornelissen 	/* log on errors */
120421f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
120521f6ecabSRudolf Cornelissen 	if (stat)
120621f6ecabSRudolf Cornelissen 	{
120721f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (4)\n"));
120821f6ecabSRudolf Cornelissen 		return stat;
120921f6ecabSRudolf Cornelissen 	}
121021f6ecabSRudolf Cornelissen 
121121f6ecabSRudolf Cornelissen 	return stat;
121221f6ecabSRudolf Cornelissen }//end BT_read_monstat.
121321f6ecabSRudolf Cornelissen 
121421f6ecabSRudolf Cornelissen static uint8 BT_killclk_blackout(void)
121521f6ecabSRudolf Cornelissen {
121621f6ecabSRudolf Cornelissen 	uint8 stat;
121721f6ecabSRudolf Cornelissen 
121821f6ecabSRudolf Cornelissen 	uint8 buffer[4];
121921f6ecabSRudolf Cornelissen 
12209a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Killing clock and/or blacking out (blocking output signals)\n"));
12219a7218c5SRudolf Cornelissen 
122221f6ecabSRudolf Cornelissen 	/* reset status */
122321f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
122421f6ecabSRudolf Cornelissen 
122521f6ecabSRudolf Cornelissen 	if (si->ps.tv_encoder.type <= BT869) //BT...
122621f6ecabSRudolf Cornelissen 	{
122721f6ecabSRudolf Cornelissen 		/* Only disable external pixelclock input on BT's.
122821f6ecabSRudolf Cornelissen 		 * CX chips will lock the bus if you do this.
122921f6ecabSRudolf Cornelissen 		 * (It looks like the external pixelclock is always OK as long as a valid
123021f6ecabSRudolf Cornelissen 		 * mode is programmed for the TVout chip. This means that disabling the use
123121f6ecabSRudolf Cornelissen 		 * of this clock is not needed anyway.
123221f6ecabSRudolf Cornelissen 		 * If you do disable this input, this pixelclock will rise to about 60Mhz BTW..) */
123321f6ecabSRudolf Cornelissen 
123421f6ecabSRudolf Cornelissen 		/* disable use of external pixelclock source... */
123521f6ecabSRudolf Cornelissen 		/* (should prevent BT for being 'overclocked' by RIVA in VGA-only mode...) */
123621f6ecabSRudolf Cornelissen 		buffer[0] = si->ps.tv_encoder.adress + WR;
123721f6ecabSRudolf Cornelissen 		/* select BT register for setting EN_XCLK */
123821f6ecabSRudolf Cornelissen 		buffer[1] = 0xa0;
123921f6ecabSRudolf Cornelissen 		/* clear it */
124021f6ecabSRudolf Cornelissen 		buffer[2] = 0x00;
124121f6ecabSRudolf Cornelissen 
124221f6ecabSRudolf Cornelissen 		i2c_bstart(si->ps.tv_encoder.bus);
124321f6ecabSRudolf Cornelissen 		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
124421f6ecabSRudolf Cornelissen 		i2c_bstop(si->ps.tv_encoder.bus);
124521f6ecabSRudolf Cornelissen 		/* log on errors */
124621f6ecabSRudolf Cornelissen 		stat = i2c_flag_error(0);
124721f6ecabSRudolf Cornelissen 		if (stat)
124821f6ecabSRudolf Cornelissen 		{
124921f6ecabSRudolf Cornelissen 			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-BT)\n"));
125021f6ecabSRudolf Cornelissen 			return stat;
125121f6ecabSRudolf Cornelissen 		}
125221f6ecabSRudolf Cornelissen 	}
125321f6ecabSRudolf Cornelissen 	else //CX...
125421f6ecabSRudolf Cornelissen 	{
125521f6ecabSRudolf Cornelissen 		/* Disable CX video out (or wild output will be seen on TV..) */
125621f6ecabSRudolf Cornelissen 		buffer[0] = si->ps.tv_encoder.adress + WR;
125721f6ecabSRudolf Cornelissen 		/* select register in CX */
125821f6ecabSRudolf Cornelissen 		buffer[1] = 0x6c;
125921f6ecabSRudolf Cornelissen 		/* disable active video out. */
126021f6ecabSRudolf Cornelissen 		buffer[2] = 0x02;
126121f6ecabSRudolf Cornelissen 
126221f6ecabSRudolf Cornelissen 		i2c_bstart(si->ps.tv_encoder.bus);
126321f6ecabSRudolf Cornelissen 		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
126421f6ecabSRudolf Cornelissen 		i2c_bstop(si->ps.tv_encoder.bus);
126521f6ecabSRudolf Cornelissen 		/* log on errors */
126621f6ecabSRudolf Cornelissen 		stat = i2c_flag_error(0);
126721f6ecabSRudolf Cornelissen 		if (stat)
126821f6ecabSRudolf Cornelissen 		{
126921f6ecabSRudolf Cornelissen 			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-CX)\n"));
127021f6ecabSRudolf Cornelissen 			return stat;
127121f6ecabSRudolf Cornelissen 		}
127221f6ecabSRudolf Cornelissen 	}
127321f6ecabSRudolf Cornelissen 
127421f6ecabSRudolf Cornelissen 	/* black-out TVout while outputs are enabled... */
127521f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
127621f6ecabSRudolf Cornelissen 	/* select first TV config register to write */
127721f6ecabSRudolf Cornelissen 	buffer[1] = 0xc4;
127821f6ecabSRudolf Cornelissen 	/* disable testimage while outputs remain enabled */
127921f6ecabSRudolf Cornelissen 	buffer[2] = 0x01;
128021f6ecabSRudolf Cornelissen 	/* input is 24bit mpx'd RGB, BLANK = in, sync = act. hi */
128121f6ecabSRudolf Cornelissen 	buffer[3] = 0x18;
128221f6ecabSRudolf Cornelissen 
128321f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
128421f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
128521f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
128621f6ecabSRudolf Cornelissen 	/* log on errors */
128721f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
128821f6ecabSRudolf Cornelissen 	if (stat)
128921f6ecabSRudolf Cornelissen 	{
129021f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (2)\n"));
129121f6ecabSRudolf Cornelissen 		return stat;
129221f6ecabSRudolf Cornelissen 	}
129321f6ecabSRudolf Cornelissen 
129421f6ecabSRudolf Cornelissen 	return stat;
129521f6ecabSRudolf Cornelissen }//end BT_killclk_blackout.
129621f6ecabSRudolf Cornelissen 
1297b2459715SRudolf Cornelissen uint8 BT_check_tvmode(display_mode target)
1298fb6cadf1Sshatty {
1299b2459715SRudolf Cornelissen 	uint8 status = NOT_SUPPORTED;
1300b2459715SRudolf Cornelissen 	uint32 mode = ((target.timing.h_display) | ((target.timing.v_display) << 16));
1301b2459715SRudolf Cornelissen 
1302b2459715SRudolf Cornelissen 	switch (mode)
1303b2459715SRudolf Cornelissen 	{
1304b2459715SRudolf Cornelissen 	case (640 | (480 << 16)):
1305c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1306c5fe5f2dSRudolf Cornelissen 			status = PAL640;
1307b2459715SRudolf Cornelissen 		if ((target.flags & TV_BITS) == TV_NTSC)
1308b2459715SRudolf Cornelissen 		{
1309b2459715SRudolf Cornelissen 			if (!(target.flags & TV_VIDEO)) status = NTSC640;
1310b2459715SRudolf Cornelissen 			else status = NTSC640_OS;
1311b2459715SRudolf Cornelissen 		}
1312b2459715SRudolf Cornelissen 		break;
1313c5fe5f2dSRudolf Cornelissen 	case (768 | (576 << 16)):
1314c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1315c5fe5f2dSRudolf Cornelissen 			status = PAL800_OS;
1316c5fe5f2dSRudolf Cornelissen 		break;
1317b2459715SRudolf Cornelissen 	case (800 | (600 << 16)):
1318c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1319c5fe5f2dSRudolf Cornelissen 			status = PAL800;
1320c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_NTSC) && (!(target.flags & TV_VIDEO)))
1321c5fe5f2dSRudolf Cornelissen 			status = NTSC800;
1322b2459715SRudolf Cornelissen 		break;
1323b2459715SRudolf Cornelissen 	case (720 | (480 << 16)):
1324b2459715SRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_NTSC) && (target.flags & TV_VIDEO))
1325b2459715SRudolf Cornelissen 			status = NTSC720;
1326b2459715SRudolf Cornelissen 		break;
1327b2459715SRudolf Cornelissen 	case (720 | (576 << 16)):
1328b2459715SRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1329b2459715SRudolf Cornelissen 			status = PAL720;
1330b2459715SRudolf Cornelissen 		break;
1331b2459715SRudolf Cornelissen 	}
1332b2459715SRudolf Cornelissen 
1333b2459715SRudolf Cornelissen 	return status;
1334b2459715SRudolf Cornelissen }//end BT_check_tvmode.
1335b2459715SRudolf Cornelissen 
1336bd7693f2SRudolf Cornelissen 
1337bd7693f2SRudolf Cornelissen /*
1338da3804eeSRudolf Cornelissen //BeTVOut's SwitchRIVAtoTV(vtot) timing formula: (note: vtot = (v_total - 2))
1339bd7693f2SRudolf Cornelissen //-----------------------------------------------------------------------------------
1340bd7693f2SRudolf Cornelissen //HORIZONTAL:
1341bd7693f2SRudolf Cornelissen //-----------
1342bd7693f2SRudolf Cornelissen h_sync_start = h_display;
1343bd7693f2SRudolf Cornelissen 
1344bd7693f2SRudolf Cornelissen //fixme, note, checkout:
1345bd7693f2SRudolf Cornelissen //feels like in fact TNT2-M64 nv_crtc.c registerprogramming should be adapted...
1346bd7693f2SRudolf Cornelissen if (TNT2-M64)
1347bd7693f2SRudolf Cornelissen {
1348bd7693f2SRudolf Cornelissen 	h_sync_end = h_display + 8;
1349bd7693f2SRudolf Cornelissen 	h_total = h_display + 56;
1350bd7693f2SRudolf Cornelissen }
1351bd7693f2SRudolf Cornelissen else //TNT1, TNT2, Geforce2... (so default)
1352bd7693f2SRudolf Cornelissen {
1353bd7693f2SRudolf Cornelissen 	h_sync_end = h_display + 16;
1354bd7693f2SRudolf Cornelissen 	h_total = h_display + 48;
1355bd7693f2SRudolf Cornelissen }
1356bd7693f2SRudolf Cornelissen 
1357bd7693f2SRudolf Cornelissen //fixme, note, checkout:
1358bd7693f2SRudolf Cornelissen //BeTVOut uses two 'tweaks':
1359bd7693f2SRudolf Cornelissen // - on TNT2-M64 only:
1360bd7693f2SRudolf Cornelissen //   register h_blank_e is increased with 1 (so should be done in nv_crtc.c here)
1361463f0fabSRudolf Cornelissen // - 'all cards':
1362463f0fabSRudolf Cornelissen //   register h_blank_e b6 = 0 (only influences TNT2-M64 in modes NTSC800 and PAL800).
1363bd7693f2SRudolf Cornelissen //-----------------------------------------------------------------------------------
1364bd7693f2SRudolf Cornelissen //VERTICAL:
1365bd7693f2SRudolf Cornelissen //---------
1366da3804eeSRudolf Cornelissen v_sync_start = v_display;
1367da3804eeSRudolf Cornelissen v_total = vtot + 2;
1368da3804eeSRudolf Cornelissen v_sync_end = v_total - 1; //(This takes care of the 'cursor trash' on TNT1's...)
1369bd7693f2SRudolf Cornelissen //-----------------------------------------------------------------------------------
1370bd7693f2SRudolf Cornelissen */
137185406c4dSRudolf Cornelissen static status_t BT_update_mode_for_gpu(display_mode *target, uint8 tvmode)
137285406c4dSRudolf Cornelissen {
1373b0fce481SRudolf Cornelissen 	//fixme if needed:
1374b0fce481SRudolf Cornelissen 	//pixelclock is not actually pgm'd because PLL is pgm' earlier during setmode...
137585406c4dSRudolf Cornelissen 	switch (tvmode)
137685406c4dSRudolf Cornelissen 	{
137785406c4dSRudolf Cornelissen 	case NTSC640:
137885406c4dSRudolf Cornelissen 	case NTSC640_TST:
1379bd7693f2SRudolf Cornelissen 		target->timing.h_display = 640;
1380bd7693f2SRudolf Cornelissen 		target->timing.h_sync_start = 640;
1381bd7693f2SRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1382bd7693f2SRudolf Cornelissen 		{
1383bd7693f2SRudolf Cornelissen 			target->timing.h_sync_end = 648;
1384bd7693f2SRudolf Cornelissen 			target->timing.h_total = 696;
1385bd7693f2SRudolf Cornelissen 		}
1386bd7693f2SRudolf Cornelissen 		else
1387bd7693f2SRudolf Cornelissen 		{
13884e918a7cSRudolf Cornelissen 			//fixme if possible:
13894e918a7cSRudolf Cornelissen 			//see if tweaking h_sync_end can shift picture 8 pixels right to fix
13904e918a7cSRudolf Cornelissen 			//ws tv's tuning fault (always going for max. compatibility :)
1391bd7693f2SRudolf Cornelissen 			target->timing.h_sync_end = 656;
1392bd7693f2SRudolf Cornelissen 			target->timing.h_total = 688;
1393bd7693f2SRudolf Cornelissen 		}
1394bd7693f2SRudolf Cornelissen 		target->timing.v_display = 480;
1395da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 480;
1396da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 555;	//This prevents 'cursor trash' on TNT1's
1397da3804eeSRudolf Cornelissen 		target->timing.v_total = 556;		//Above 525 because mode scales down
1398da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1399da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((696 * 556 * 60) / 1000);
1400da3804eeSRudolf Cornelissen 		else
1401da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((688 * 556 * 60) / 1000);
140285406c4dSRudolf Cornelissen 		break;
140385406c4dSRudolf Cornelissen 	case NTSC800:
1404da3804eeSRudolf Cornelissen 		target->timing.h_display = 800;
1405da3804eeSRudolf Cornelissen 		target->timing.h_sync_start = 800;
1406da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1407da3804eeSRudolf Cornelissen 		{
1408da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 808;
1409da3804eeSRudolf Cornelissen 			target->timing.h_total = 856;
1410da3804eeSRudolf Cornelissen 		}
1411da3804eeSRudolf Cornelissen 		else
1412da3804eeSRudolf Cornelissen 		{
1413da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 816;
1414da3804eeSRudolf Cornelissen 			target->timing.h_total = 848;
1415da3804eeSRudolf Cornelissen 		}
1416da3804eeSRudolf Cornelissen 		target->timing.v_display = 600;
1417da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 600;
1418da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 685;	//This prevents 'cursor trash' on TNT1's
1419da3804eeSRudolf Cornelissen 		target->timing.v_total = 686;		//Above 525 because mode scales down
1420da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1421da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((856 * 686 * 60) / 1000);
1422da3804eeSRudolf Cornelissen 		else
1423da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((848 * 686 * 60) / 1000);
142485406c4dSRudolf Cornelissen 		break;
142585406c4dSRudolf Cornelissen 	case PAL640:
1426bd7693f2SRudolf Cornelissen 		target->timing.h_display = 640;
1427da3804eeSRudolf Cornelissen 		target->timing.h_sync_start = 640;
1428da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1429da3804eeSRudolf Cornelissen 		{
1430da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 648;
1431da3804eeSRudolf Cornelissen 			target->timing.h_total = 696;
1432da3804eeSRudolf Cornelissen 		}
1433da3804eeSRudolf Cornelissen 		else
1434da3804eeSRudolf Cornelissen 		{
1435da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 656;
1436da3804eeSRudolf Cornelissen 			target->timing.h_total = 688;
1437da3804eeSRudolf Cornelissen 		}
1438bd7693f2SRudolf Cornelissen 		target->timing.v_display = 480;
1439da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 480;
1440da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 570;	//This prevents 'cursor trash' on TNT1's
1441da3804eeSRudolf Cornelissen 		target->timing.v_total = 571;		//Below 625 because mode scales up
1442da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1443da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((696 * 571 * 50) / 1000);
1444da3804eeSRudolf Cornelissen 		else
1445da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((688 * 571 * 50) / 1000);
144685406c4dSRudolf Cornelissen 		break;
144785406c4dSRudolf Cornelissen 	case PAL800:
144885406c4dSRudolf Cornelissen 	case PAL800_TST:
1449da3804eeSRudolf Cornelissen 		target->timing.h_display = 800;
1450da3804eeSRudolf Cornelissen 		target->timing.h_sync_start = 800;
1451da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1452da3804eeSRudolf Cornelissen 		{
1453da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 808;
1454da3804eeSRudolf Cornelissen 			target->timing.h_total = 856;
1455da3804eeSRudolf Cornelissen 		}
1456da3804eeSRudolf Cornelissen 		else
1457da3804eeSRudolf Cornelissen 		{
1458da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 816;
1459da3804eeSRudolf Cornelissen 			target->timing.h_total = 848;
1460da3804eeSRudolf Cornelissen 		}
1461da3804eeSRudolf Cornelissen 		target->timing.v_display = 600;
1462da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 600;
1463da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 695;	//This prevents 'cursor trash' on TNT1's
1464da3804eeSRudolf Cornelissen 		target->timing.v_total = 696;		//Above 625 because mode scales down
1465da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1466da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((856 * 696 * 50) / 1000);
1467da3804eeSRudolf Cornelissen 		else
1468da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((848 * 696 * 50) / 1000);
146985406c4dSRudolf Cornelissen 		break;
147085406c4dSRudolf Cornelissen 	case NTSC640_OS:
147185406c4dSRudolf Cornelissen 		target->timing.h_display = 640;			//BT H_ACTIVE
147285406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 744;		//set for CH/BT compatible TV output
147385406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 744+20;		//delta is BT H_BLANKI
147485406c4dSRudolf Cornelissen 		target->timing.h_total = 784;			//BT H_CLKI
147585406c4dSRudolf Cornelissen 		target->timing.v_display = 480;			//BT  V_ACTIVEI
147685406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 490;		//set for centered sync pulse
147785406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 490+25;		//delta is BT V_BLANKI
1478da3804eeSRudolf Cornelissen 		target->timing.v_total = 525;			//BT V_LINESI (== 525: 1:1 scaled mode)
147985406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((784 * 525 * 60) / 1000); //refresh
148085406c4dSRudolf Cornelissen 		break;
148185406c4dSRudolf Cornelissen 	case PAL800_OS:
148285406c4dSRudolf Cornelissen 		target->timing.h_display = 768;			//H_ACTIVE
14836245f19cSRudolf Cornelissen 		if (si->ps.tv_encoder.type <= BT869)
14846245f19cSRudolf Cornelissen 		{
14854e918a7cSRudolf Cornelissen 			/* confirmed on TNT1 using 4:3 TV and 16:9 TV */
14866245f19cSRudolf Cornelissen 			target->timing.h_sync_start = 856;		//set for centered TV output
14876245f19cSRudolf Cornelissen 			target->timing.h_sync_end = 856+20;		//delta is BT H_BLANKI
14886245f19cSRudolf Cornelissen 		}
14896245f19cSRudolf Cornelissen 		else
14906245f19cSRudolf Cornelissen 		{
14914e918a7cSRudolf Cornelissen 			//fixme if needed (added 8 for BT)..
149285406c4dSRudolf Cornelissen 			target->timing.h_sync_start = 848;		//set for centered TV output
149385406c4dSRudolf Cornelissen 			target->timing.h_sync_end = 848+20;		//delta is BT H_BLANKI
14946245f19cSRudolf Cornelissen 		}
149585406c4dSRudolf Cornelissen 		target->timing.h_total = 944;			//BT H_CLKI
149685406c4dSRudolf Cornelissen 		target->timing.v_display = 576;			//V_ACTIVEI
149785406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 579;		//set for centered sync pulse
149885406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1499da3804eeSRudolf Cornelissen 		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
150085406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((944 * 625 * 50) / 1000); //refresh
150185406c4dSRudolf Cornelissen 		break;
150285406c4dSRudolf Cornelissen 	case NTSC720:
150385406c4dSRudolf Cornelissen 		/* (tested on TNT2 with BT869) */
150485406c4dSRudolf Cornelissen 		target->timing.h_display = 720;			//H_ACTIVE
150585406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 744;		//do not change!
150685406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 744+144;	//delta is H_sync_pulse
150785406c4dSRudolf Cornelissen 		target->timing.h_total = 888;			//BT H_TOTAL
150885406c4dSRudolf Cornelissen 		target->timing.v_display = 480;			//V_ACTIVEI
150985406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 490;		//set for centered sync pulse
151085406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 490+26;		//delta is V_sync_pulse
1511da3804eeSRudolf Cornelissen 		target->timing.v_total = 525;			//CH V_TOTAL (== 525: 1:1 scaled mode)
151285406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((888 * 525 * 60) / 1000); //refresh
151385406c4dSRudolf Cornelissen 		break;
151485406c4dSRudolf Cornelissen 	case PAL720:
151585406c4dSRudolf Cornelissen 		target->timing.h_display = 720;			//BT H_ACTIVE
151685406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 744;		//set for centered sync pulse
151785406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 744+140;	//delta is BT H_BLANKI
151885406c4dSRudolf Cornelissen 		target->timing.h_total = 888;			//BT H_CLKI
151985406c4dSRudolf Cornelissen 		target->timing.v_display = 576;			//BT  V_ACTIVEI
152085406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 579;		//set for centered sync pulse
152185406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1522da3804eeSRudolf Cornelissen 		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
152385406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((888 * 625 * 50) / 1000); //refresh
152485406c4dSRudolf Cornelissen 		break;
152585406c4dSRudolf Cornelissen 	default:
152685406c4dSRudolf Cornelissen 		return B_ERROR;
152785406c4dSRudolf Cornelissen 	}
152885406c4dSRudolf Cornelissen 
152985406c4dSRudolf Cornelissen 	return B_OK;
153085406c4dSRudolf Cornelissen }//end BT_update_mode_for_gpu.
153185406c4dSRudolf Cornelissen 
153222a0d15bSRudolf Cornelissen /* note:
153322a0d15bSRudolf Cornelissen  * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869),
153422a0d15bSRudolf Cornelissen  * Diamond Viper V550 16Mb PCI (TNT1/BT869),
153522a0d15bSRudolf Cornelissen  * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */
153622a0d15bSRudolf Cornelissen static status_t BT_start_tvout(void)
153722a0d15bSRudolf Cornelissen {
153822a0d15bSRudolf Cornelissen 	/* enable access to primary head */
153922a0d15bSRudolf Cornelissen 	set_crtc_owner(0);
154022a0d15bSRudolf Cornelissen 
15419b394aa2SRudolf Cornelissen 	/* CAUTION:
15429b394aa2SRudolf Cornelissen 	 * On the TNT1, TV_SETUP and PLLSEL cannot be read (sometimes), but
15439b394aa2SRudolf Cornelissen 	 * write actions do succeed ... (tested on both ISA and PCI bus!) */
154422a0d15bSRudolf Cornelissen 
154522a0d15bSRudolf Cornelissen 	/* setup TVencoder connection */
154622a0d15bSRudolf Cornelissen 	/* b1-0 = %01: encoder type is MASTER;
154722a0d15bSRudolf Cornelissen 	 * b24 = 1: VIP datapos is b0-7 */
1548b0fce481SRudolf Cornelissen 	//fixme if needed: setup completely instead of relying on pre-init by BIOS..
15499b394aa2SRudolf Cornelissen 	//(it seems to work OK on TNT1 although read reg. doesn't seem to work)
1550b0fce481SRudolf Cornelissen 	DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000002) | 0x01000001));
155122a0d15bSRudolf Cornelissen 
155222a0d15bSRudolf Cornelissen 	/* tell GPU to use pixelclock from TVencoder instead of using internal source */
155322a0d15bSRudolf Cornelissen 	/* (nessecary or display will 'shiver' on both TV and VGA.) */
15549b394aa2SRudolf Cornelissen 	if (si->ps.secondary_head)
15559b394aa2SRudolf Cornelissen 	{
155622a0d15bSRudolf Cornelissen 		DACW(PLLSEL, (DACR(PLLSEL) | 0x00030000));
15579b394aa2SRudolf Cornelissen 	}
15589b394aa2SRudolf Cornelissen 	else
15599b394aa2SRudolf Cornelissen 	{
15609b394aa2SRudolf Cornelissen 		/* confirmed PLLSEL to be a write-only register on TNT1! */
15619b394aa2SRudolf Cornelissen 		DACW(PLLSEL, 0x00030700);
15629b394aa2SRudolf Cornelissen 	}
156322a0d15bSRudolf Cornelissen 
156422a0d15bSRudolf Cornelissen 	/* Set overscan color to 'black' */
156522a0d15bSRudolf Cornelissen 	/* note:
156622a0d15bSRudolf Cornelissen 	 * Change this instruction for a visible overscan color if you're trying to
156722a0d15bSRudolf Cornelissen 	 * center the output on TV. Use it as a guide-'line' then ;-) */
156822a0d15bSRudolf Cornelissen 	ATBW(OSCANCOLOR, 0x00);
156922a0d15bSRudolf Cornelissen 
157022a0d15bSRudolf Cornelissen 	/* set CRTC to slaved mode (b7 = 1) and clear TVadjust (b3-5 = %000) */
157122a0d15bSRudolf Cornelissen 	CRTCW(PIXEL, ((CRTCR(PIXEL) & 0xc7) | 0x80));
1572bd419083SRudolf Cornelissen 	/* select TV encoder, not panel encoder (b0 = 0).
1573bd419083SRudolf Cornelissen 	 * Note:
1574b0fce481SRudolf Cornelissen 	 * Both are devices (often) using the CRTC in slaved mode. */
1575bd419083SRudolf Cornelissen 	CRTCW(LCD, (CRTCR(LCD) & 0xfe));
157622a0d15bSRudolf Cornelissen 
1577bd419083SRudolf Cornelissen 	/* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of
1578bd419083SRudolf Cornelissen 	 * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */
1579bd419083SRudolf Cornelissen 	CRTCW(TREG, 0x80);
158022a0d15bSRudolf Cornelissen 
158122a0d15bSRudolf Cornelissen 	return B_OK;
158222a0d15bSRudolf Cornelissen }//end BT_start_tvout.
158322a0d15bSRudolf Cornelissen 
1584bd419083SRudolf Cornelissen /* note:
1585bd419083SRudolf Cornelissen  * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869),
1586bd419083SRudolf Cornelissen  * Diamond Viper V550 16Mb PCI (TNT1/BT869),
1587bd419083SRudolf Cornelissen  * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */
158822a0d15bSRudolf Cornelissen status_t BT_stop_tvout(void)
158922a0d15bSRudolf Cornelissen {
159022a0d15bSRudolf Cornelissen 	/* prevent BT from being overclocked by VGA-only modes & black-out TV-out */
159122a0d15bSRudolf Cornelissen 	BT_killclk_blackout();
159222a0d15bSRudolf Cornelissen 
1593bd419083SRudolf Cornelissen 	/* enable access to primary head */
1594bd419083SRudolf Cornelissen 	set_crtc_owner(0);
1595bd419083SRudolf Cornelissen 
1596bd419083SRudolf Cornelissen 	/* switch on VGA monitor HSYNC and VSYNC */
1597bd419083SRudolf Cornelissen //fixme: see if better DPMS state fetching can be setup for crtc.c (!)
1598bd419083SRudolf Cornelissen 	CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0x3f));
1599bd419083SRudolf Cornelissen 
1600bd419083SRudolf Cornelissen 
16010b36eea4SRudolf Cornelissen 	/* wait for one image to be generated to make sure VGA has kicked in and is
16020b36eea4SRudolf Cornelissen 	 * running OK before continuing...
16030b36eea4SRudolf Cornelissen 	 * (Kicking in will fail often if we do not wait here) */
1604bd419083SRudolf Cornelissen 
16050b36eea4SRudolf Cornelissen 	/* make sure we are 'in' active VGA picture */
16060b36eea4SRudolf Cornelissen 	while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1);
16070b36eea4SRudolf Cornelissen 	/* wait for next vertical retrace start on VGA */
16080b36eea4SRudolf Cornelissen 	while (!(NV_REG8(NV8_INSTAT1) & 0x08)) snooze(1);
16090b36eea4SRudolf Cornelissen 	/* now wait until we are 'in' active VGA picture again */
16100b36eea4SRudolf Cornelissen 	while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1);
1611bd419083SRudolf Cornelissen 
16120b36eea4SRudolf Cornelissen 
1613b0fce481SRudolf Cornelissen 	/* set CRTC to master mode (b7 = 0) if it wasn't slaved for a panel before */
1614b0fce481SRudolf Cornelissen 	if (!(si->ps.slaved_tmds1))	CRTCW(PIXEL, (CRTCR(PIXEL) & 0x03));
16150b36eea4SRudolf Cornelissen 
16160b36eea4SRudolf Cornelissen 	//fixme: checkout...
1617bd419083SRudolf Cornelissen 	//CAUTION:
1618bd419083SRudolf Cornelissen 	//On the TNT1, these memadresses apparantly cannot be read (sometimes)!;
16190b36eea4SRudolf Cornelissen 	//write actions do succeed though... (tested only on ISA bus yet..)
1620bd419083SRudolf Cornelissen 
16210b36eea4SRudolf Cornelissen 	/* setup TVencoder connection */
16220b36eea4SRudolf Cornelissen 	/* b1-0 = %00: encoder type is SLAVE;
16230b36eea4SRudolf Cornelissen 	 * b24 = 1: VIP datapos is b0-7 */
1624b0fce481SRudolf Cornelissen 	//fixme if needed: setup completely instead of relying on pre-init by BIOS..
1625b0fce481SRudolf Cornelissen 	DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000003) | 0x01000000));
1626bd419083SRudolf Cornelissen 
16270b36eea4SRudolf Cornelissen 	/* tell GPU to use pixelclock from internal source instead of using TVencoder */
16280b36eea4SRudolf Cornelissen 	DACW(PLLSEL, 0x10000700);
16290b36eea4SRudolf Cornelissen 	if (si->ps.secondary_head) DACW(PLLSEL, (DACR(PLLSEL) | 0x20000800));
1630bd419083SRudolf Cornelissen 
16310b36eea4SRudolf Cornelissen 	/* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of
16320b36eea4SRudolf Cornelissen 	 * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */
16330b36eea4SRudolf Cornelissen 	CRTCW(TREG, 0x00);
1634bd419083SRudolf Cornelissen 
1635b0fce481SRudolf Cornelissen 	/* select panel encoder, not TV encoder if needed (b0 = 1).
16360b36eea4SRudolf Cornelissen 	 * Note:
1637b0fce481SRudolf Cornelissen 	 * Both are devices (often) using the CRTC in slaved mode. */
1638b0fce481SRudolf Cornelissen 	if (si->ps.slaved_tmds1) CRTCW(LCD, (CRTCR(LCD) | 0x01));
163922a0d15bSRudolf Cornelissen 
164022a0d15bSRudolf Cornelissen 	/* fixme if needed:
164122a0d15bSRudolf Cornelissen 	 * a full encoder chip reset could be done here (so after decoupling crtc)... */
1642b0fce481SRudolf Cornelissen 	/* (but: beware of the 'locked SDA' syndrome then!) */
164322a0d15bSRudolf Cornelissen 
164422a0d15bSRudolf Cornelissen 	return B_OK;
1645bd419083SRudolf Cornelissen }//end BT_stop_tvout.
164622a0d15bSRudolf Cornelissen 
1647b2459715SRudolf Cornelissen status_t BT_setmode(display_mode target)
1648b2459715SRudolf Cornelissen {
1649efe9c7a6SRudolf Cornelissen 	uint8 tvmode, monstat;
1650efe9c7a6SRudolf Cornelissen 	/* enable flickerfilter in desktop modes, disable it in video modes. */
1651efe9c7a6SRudolf Cornelissen 	uint8 ffilter = 0;
1652b2459715SRudolf Cornelissen 
1653fb6cadf1Sshatty 	/* use a display_mode copy because we might tune it for TVout compatibility */
1654fb6cadf1Sshatty 	display_mode tv_target = target;
1655fb6cadf1Sshatty 
1656fb6cadf1Sshatty 	/* preset new TVout mode */
1657b2459715SRudolf Cornelissen 	tvmode = BT_check_tvmode(tv_target);
1658b2459715SRudolf Cornelissen 	if (!tvmode) return B_ERROR;
1659b2459715SRudolf Cornelissen 
1660efe9c7a6SRudolf Cornelissen 	/* read current output devices connection status */
1661efe9c7a6SRudolf Cornelissen 	BT_read_monstat(&monstat);
1662efe9c7a6SRudolf Cornelissen 
1663efe9c7a6SRudolf Cornelissen 	/* (pre)set TV mode */
1664efe9c7a6SRudolf Cornelissen 	/* note:
1665efe9c7a6SRudolf Cornelissen 	 * Manual config is non-dependent of the state of the PAL hardware input pin;
1666efe9c7a6SRudolf Cornelissen 	 * Also SDA lockups occur when setting EN_XCLK after autoconfig!
1667efe9c7a6SRudolf Cornelissen 	 * Make sure PAL_MD=0 for NTSC and PAL_MD = 1 for PAL... */
1668b2459715SRudolf Cornelissen 	switch (tvmode)
1669fb6cadf1Sshatty 	{
1670b2459715SRudolf Cornelissen 	case NTSC640:
1671b2459715SRudolf Cornelissen 	case NTSC640_TST:
1672efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1673efe9c7a6SRudolf Cornelissen 		BT_init_NTSC640();
1674b2459715SRudolf Cornelissen 		break;
1675b2459715SRudolf Cornelissen 	case NTSC800:
1676efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1677efe9c7a6SRudolf Cornelissen 		BT_init_NTSC800();
1678b2459715SRudolf Cornelissen 		break;
1679b2459715SRudolf Cornelissen 	case PAL640:
1680efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1681efe9c7a6SRudolf Cornelissen 		BT_init_PAL640();
1682b2459715SRudolf Cornelissen 		break;
1683b2459715SRudolf Cornelissen 	case PAL800:
1684b2459715SRudolf Cornelissen 	case PAL800_TST:
1685efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1686efe9c7a6SRudolf Cornelissen 		BT_init_PAL800();
1687b2459715SRudolf Cornelissen 		break;
1688b2459715SRudolf Cornelissen 	case NTSC640_OS:
1689efe9c7a6SRudolf Cornelissen 		BT_init_NTSC640_OS();
1690b2459715SRudolf Cornelissen 		break;
1691b2459715SRudolf Cornelissen 	case PAL800_OS:
1692efe9c7a6SRudolf Cornelissen 		BT_init_PAL800_OS();
1693b2459715SRudolf Cornelissen 		break;
1694b2459715SRudolf Cornelissen 	case NTSC720:
1695efe9c7a6SRudolf Cornelissen 		BT_init_NTSC720();
1696b2459715SRudolf Cornelissen 		break;
1697b2459715SRudolf Cornelissen 	case PAL720:
1698efe9c7a6SRudolf Cornelissen 		BT_init_PAL720();
1699b2459715SRudolf Cornelissen 		break;
1700fb6cadf1Sshatty 	}
1701fb6cadf1Sshatty 
1702efe9c7a6SRudolf Cornelissen 	/* modify BT Hphase signal to center TV image... */
1703efe9c7a6SRudolf Cornelissen 	BT_setup_hphase(tvmode);
1704fb6cadf1Sshatty 
1705efe9c7a6SRudolf Cornelissen 	/* disable Macro mode */
1706efe9c7a6SRudolf Cornelissen 	switch (tvmode)
1707efe9c7a6SRudolf Cornelissen 	{
1708efe9c7a6SRudolf Cornelissen 	case NTSC640:
1709efe9c7a6SRudolf Cornelissen 	case NTSC640_TST:
1710efe9c7a6SRudolf Cornelissen 	case NTSC800:
1711efe9c7a6SRudolf Cornelissen 	case NTSC640_OS:
1712efe9c7a6SRudolf Cornelissen 	case NTSC720:
1713efe9c7a6SRudolf Cornelissen 		/* NTSC */
1714efe9c7a6SRudolf Cornelissen 		BT_set_macro (0, 0);
1715efe9c7a6SRudolf Cornelissen 		break;
1716efe9c7a6SRudolf Cornelissen 	default:
1717efe9c7a6SRudolf Cornelissen 		/* PAL */
1718efe9c7a6SRudolf Cornelissen 		BT_set_macro (1, 0);
1719efe9c7a6SRudolf Cornelissen 		break;
1720efe9c7a6SRudolf Cornelissen 	}
1721fb6cadf1Sshatty 
1722efe9c7a6SRudolf Cornelissen 	/* setup output signal routing and flickerfilter */
1723efe9c7a6SRudolf Cornelissen //fixme: add output force settings in nv.settings, defaulting to autodetect.
1724efe9c7a6SRudolf Cornelissen 	BT_setup_output(monstat, 0, ffilter);
1725fb6cadf1Sshatty 
172685406c4dSRudolf Cornelissen 	/* update the GPU CRTC timing for the requested mode */
172785406c4dSRudolf Cornelissen 	BT_update_mode_for_gpu(&tv_target, tvmode);
1728fb6cadf1Sshatty 
1729efe9c7a6SRudolf Cornelissen 	/* setup GPU CRTC timing */
1730b2459715SRudolf Cornelissen 	head1_set_timing(tv_target);
1731fb6cadf1Sshatty 
1732b0fce481SRudolf Cornelissen //fixme: only testing singlehead cards for now...
1733b0fce481SRudolf Cornelissen if (si->ps.secondary_head)
1734b0fce481SRudolf Cornelissen {
1735b0fce481SRudolf Cornelissen 	BT_testsignal();
1736b0fce481SRudolf Cornelissen 	return B_OK;
1737b0fce481SRudolf Cornelissen }
1738b0fce481SRudolf Cornelissen 
173922a0d15bSRudolf Cornelissen 	/* now set GPU CRTC to slave mode */
1740b0fce481SRudolf Cornelissen 	BT_start_tvout();
1741efe9c7a6SRudolf Cornelissen 
1742efe9c7a6SRudolf Cornelissen //fixme: add code to disable VGA screen when TVout enabled
1743efe9c7a6SRudolf Cornelissen //(use via nv.setting preset)
1744fb6cadf1Sshatty 
1745b2459715SRudolf Cornelissen 	return B_OK;
1746fb6cadf1Sshatty }
1747