xref: /haiku/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c (revision da3804ee61b942d404c18c07235928d77f69ab27)
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 //fixme: remove rubbish..
1621f6ecabSRudolf Cornelissen enum
1721f6ecabSRudolf Cornelissen {	// TVoutput mode to set
18b2459715SRudolf Cornelissen 	NOT_SUPPORTED = 0,
1921f6ecabSRudolf Cornelissen 	NTSC640_TST,
2021f6ecabSRudolf Cornelissen 	NTSC640,
2121f6ecabSRudolf Cornelissen 	NTSC800,
2221f6ecabSRudolf Cornelissen 	PAL800_TST,
2321f6ecabSRudolf Cornelissen 	PAL640,
2421f6ecabSRudolf Cornelissen 	PAL800,
2521f6ecabSRudolf Cornelissen 	VGA,
2621f6ecabSRudolf Cornelissen 	EXIT,
2721f6ecabSRudolf Cornelissen 	NTSC720,
2821f6ecabSRudolf Cornelissen 	PAL720,
2921f6ecabSRudolf Cornelissen 	NTSC640_OS,
3021f6ecabSRudolf Cornelissen 	PAL800_OS
3121f6ecabSRudolf Cornelissen };
3221f6ecabSRudolf Cornelissen 
339a7218c5SRudolf Cornelissen /* Dirk Thierbach's Macro setup for registers 0xda-0xfe */
349a7218c5SRudolf Cornelissen static uint8 BtNtscMacro0 [] = {
359a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
369a7218c5SRudolf Cornelissen   0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x00,0x00};
379a7218c5SRudolf Cornelissen static uint8 BtNtscMacro1 [] = {
389a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
399a7218c5SRudolf Cornelissen   0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x63,0x00};
409a7218c5SRudolf Cornelissen static uint8 BtNtscMacro2 [] = {
419a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
429a7218c5SRudolf Cornelissen   0xbd,0x6c,0x31,0x92,0x32,0xdd,0xe3,0x00};
439a7218c5SRudolf Cornelissen static uint8 BtNtscMacro3 [] = {
449a7218c5SRudolf Cornelissen   0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09,
459a7218c5SRudolf Cornelissen   0xbd,0x66,0xb5,0x90,0xb2,0x7d,0xe3,0x00};
469a7218c5SRudolf Cornelissen 
479a7218c5SRudolf Cornelissen static uint8 BtPalMacro0 [] = {
489a7218c5SRudolf Cornelissen   0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05,
499a7218c5SRudolf Cornelissen   0xd3,0x78,0xa2,0x25,0x54,0xa5,0x00,0x00};
509a7218c5SRudolf Cornelissen static uint8 BtPalMacro1 [] = {
519a7218c5SRudolf Cornelissen   0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05,
529a7218c5SRudolf Cornelissen   0xd3,0x78,0xa2,0x25,0x54,0xa5,0x63,0x00};
539a7218c5SRudolf Cornelissen 
549a7218c5SRudolf Cornelissen static uint8 BT_set_macro (int std, int mode)
559a7218c5SRudolf Cornelissen {
569a7218c5SRudolf Cornelissen 	uint8 stat;
579a7218c5SRudolf Cornelissen 	uint8 buffer[21];
589a7218c5SRudolf Cornelissen 
599a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting Macro\n"));
609a7218c5SRudolf Cornelissen 
619a7218c5SRudolf Cornelissen 	if ((std < 0) | (std > 1) | (mode < 0) | (mode > 3))
629a7218c5SRudolf Cornelissen 	{
639a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Non existing mode or standard selected, aborting.\n"));
649a7218c5SRudolf Cornelissen 		return 0x80;
659a7218c5SRudolf Cornelissen 	}
669a7218c5SRudolf Cornelissen 
679a7218c5SRudolf Cornelissen 	switch (std)
689a7218c5SRudolf Cornelissen 	{
699a7218c5SRudolf Cornelissen 	case 0:
709a7218c5SRudolf Cornelissen 		/* NTSC */
719a7218c5SRudolf Cornelissen 		switch (mode)
729a7218c5SRudolf Cornelissen 		{
739a7218c5SRudolf Cornelissen 		case 0:
749a7218c5SRudolf Cornelissen 			/* disabled */
759a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro0, 19);
769a7218c5SRudolf Cornelissen 			break;
779a7218c5SRudolf Cornelissen 		case 1:
789a7218c5SRudolf Cornelissen 			/* enabled mode 1 */
799a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro1, 19);
809a7218c5SRudolf Cornelissen 			break;
819a7218c5SRudolf Cornelissen 		case 2:
829a7218c5SRudolf Cornelissen 			/* enabled mode 2 */
839a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro2, 19);
849a7218c5SRudolf Cornelissen 			break;
859a7218c5SRudolf Cornelissen 		case 3:
869a7218c5SRudolf Cornelissen 			/* enabled mode 3 */
879a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtNtscMacro3, 19);
889a7218c5SRudolf Cornelissen 			break;
899a7218c5SRudolf Cornelissen 		}
909a7218c5SRudolf Cornelissen 		break;
919a7218c5SRudolf Cornelissen 	case 1:
929a7218c5SRudolf Cornelissen 		/* PAL */
939a7218c5SRudolf Cornelissen 		switch (mode)
949a7218c5SRudolf Cornelissen 		{
959a7218c5SRudolf Cornelissen 		case 0:
969a7218c5SRudolf Cornelissen 			/* disabled */
979a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtPalMacro0, 19);
989a7218c5SRudolf Cornelissen 			break;
999a7218c5SRudolf Cornelissen 		case 1:
1009a7218c5SRudolf Cornelissen 		case 2:
1019a7218c5SRudolf Cornelissen 		case 3:
1029a7218c5SRudolf Cornelissen 			/* enabled */
1039a7218c5SRudolf Cornelissen 			memcpy(&buffer[2], &BtPalMacro1, 19);
1049a7218c5SRudolf Cornelissen 			break;
1059a7218c5SRudolf Cornelissen 		}
1069a7218c5SRudolf Cornelissen 		break;
1079a7218c5SRudolf Cornelissen 	}
1089a7218c5SRudolf Cornelissen 
1099a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
1109a7218c5SRudolf Cornelissen 	/* select first register to write to */
1119a7218c5SRudolf Cornelissen 	buffer[1] = 0xda;
1129a7218c5SRudolf Cornelissen 
1139a7218c5SRudolf Cornelissen 	/* reset status */
1149a7218c5SRudolf Cornelissen 	i2c_flag_error (-1);
1159a7218c5SRudolf Cornelissen 
1169a7218c5SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
1179a7218c5SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
1189a7218c5SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
1199a7218c5SRudolf Cornelissen 	/* log on errors */
1209a7218c5SRudolf Cornelissen 	stat = i2c_flag_error(0);
1219a7218c5SRudolf Cornelissen 	if (stat)
1229a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting Macro\n"));
1239a7218c5SRudolf Cornelissen 
1249a7218c5SRudolf Cornelissen 	return stat;
1259a7218c5SRudolf Cornelissen }//end BT_set_macro.
1269a7218c5SRudolf Cornelissen 
12712566cbdSRudolf Cornelissen /*
12812566cbdSRudolf Cornelissen  see if a (possible) BT/CX chip resides at the given adress.
12912566cbdSRudolf Cornelissen  Return zero if no errors occurred.
13012566cbdSRudolf Cornelissen */
13112566cbdSRudolf Cornelissen static uint8 BT_check (uint8 bus, uint8 adress)
13212566cbdSRudolf Cornelissen {
1330ece4905SRudolf Cornelissen 	uint8 buffer[3];
13412566cbdSRudolf Cornelissen 
1350ece4905SRudolf Cornelissen 	buffer[0] = adress + WR;
13612566cbdSRudolf Cornelissen 	/* set ESTATUS at b'00'; and enable bt chip-outputs
13712566cbdSRudolf Cornelissen 	 * WARNING:
13812566cbdSRudolf Cornelissen 	 * If bit0 = 0 is issued below (EN_OUT = disabled), the BT will lock SDA
13912566cbdSRudolf Cornelissen 	 * after writing adress $A0 (setting EN_XCLK)!!!
1409a7218c5SRudolf Cornelissen 	 * Until a reboot the corresponding I2C bus will be inacessable then!!! */
1410ece4905SRudolf Cornelissen 	buffer[1] = 0xc4;
14212566cbdSRudolf Cornelissen 	/* fixme: if testimage 'was' active txbuffer[3] should become 0x05...
14312566cbdSRudolf Cornelissen 	 * (currently this cannot be detected in a 'foolproof' way so don't touch...) */
14412566cbdSRudolf Cornelissen 	/* (ESTATUS b'0x' means: RX ID and VERSION info later..) */
1450ece4905SRudolf Cornelissen 	buffer[2] = 0x01;
1460ece4905SRudolf Cornelissen 
1470ece4905SRudolf Cornelissen 	/* reset status */
1480ece4905SRudolf Cornelissen 	i2c_flag_error (-1);
1490ece4905SRudolf Cornelissen 
1500ece4905SRudolf Cornelissen 	/* do check */
1510ece4905SRudolf Cornelissen 	i2c_bstart(bus);
1520ece4905SRudolf Cornelissen 	i2c_writebuffer(bus, buffer, sizeof(buffer));
15312566cbdSRudolf Cornelissen 	i2c_bstop(bus);
15412566cbdSRudolf Cornelissen 	return i2c_flag_error(0);
15512566cbdSRudolf Cornelissen }
15612566cbdSRudolf Cornelissen 
15712566cbdSRudolf Cornelissen /* identify chiptype */
15812566cbdSRudolf Cornelissen static uint8 BT_read_type (void)
15912566cbdSRudolf Cornelissen {
1600ece4905SRudolf Cornelissen 	uint8 id, type, stat;
1610ece4905SRudolf Cornelissen 	uint8 buffer[3];
1620ece4905SRudolf Cornelissen 
1630ece4905SRudolf Cornelissen 	/* Make sure a CX (Conexant) chip (if this turns out to be there) is set to
1640ece4905SRudolf Cornelissen 	 * BT-compatibility mode! (This command will do nothing on a BT chip...) */
1650ece4905SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
1660ece4905SRudolf Cornelissen 	/* select CX reg. for BT-compatible readback, video still off */
1670ece4905SRudolf Cornelissen 	buffer[1] = 0x6c;
1680ece4905SRudolf Cornelissen 	/* set it up */
1690ece4905SRudolf Cornelissen 	buffer[2] = 0x02;
17012566cbdSRudolf Cornelissen 
17112566cbdSRudolf Cornelissen 	/* reset status */
17212566cbdSRudolf Cornelissen 	i2c_flag_error (-1);
17312566cbdSRudolf Cornelissen 
17412566cbdSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
1750ece4905SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
17612566cbdSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
17712566cbdSRudolf Cornelissen 	/* abort on errors */
17812566cbdSRudolf Cornelissen 	stat = i2c_flag_error(0);
17912566cbdSRudolf Cornelissen 	if (stat) return stat;
18012566cbdSRudolf Cornelissen 
18112566cbdSRudolf Cornelissen 	/* Do actual readtype command */
18212566cbdSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
1839a7218c5SRudolf Cornelissen 	/* issue I2C read command */
18412566cbdSRudolf Cornelissen 	i2c_writebyte(si->ps.tv_encoder.bus, si->ps.tv_encoder.adress + RD);
18512566cbdSRudolf Cornelissen 	/* receive 1 byte;
1869a7218c5SRudolf Cornelissen 	 * ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec). */
18712566cbdSRudolf Cornelissen 	/* note:
18812566cbdSRudolf Cornelissen 	 * While the BT's don't care, CX chips will block the SDA line if
18912566cbdSRudolf Cornelissen 	 * an ACK gets sent! */
19012566cbdSRudolf Cornelissen 	id = i2c_readbyte(si->ps.tv_encoder.bus, true);
19112566cbdSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
19212566cbdSRudolf Cornelissen 	/* abort on errors */
19312566cbdSRudolf Cornelissen 	stat = i2c_flag_error(0);
19412566cbdSRudolf Cornelissen 	if (stat) return stat;
19512566cbdSRudolf Cornelissen 
1960ece4905SRudolf Cornelissen 	/* check type to be supported one */
1970ece4905SRudolf Cornelissen 	type = (id & 0xe0) >> 5;
1980ece4905SRudolf Cornelissen 	if (type > 3)
1990ece4905SRudolf Cornelissen 	{
2000ece4905SRudolf Cornelissen 		LOG(4,("Brooktree: Found unsupported encoder type %d, aborting.\n", type));
2010ece4905SRudolf Cornelissen 		return 0x80;
2020ece4905SRudolf Cornelissen 	}
2030ece4905SRudolf Cornelissen 
20412566cbdSRudolf Cornelissen 	/* inform driver about TV encoder found */
20512566cbdSRudolf Cornelissen 	si->ps.tvout = true;
2060ece4905SRudolf Cornelissen 	si->ps.tv_encoder.type = BT868 + type;
20712566cbdSRudolf Cornelissen 	si->ps.tv_encoder.version = id & 0x1f;
20812566cbdSRudolf Cornelissen 
20912566cbdSRudolf Cornelissen 	return stat;
21012566cbdSRudolf Cornelissen }
21112566cbdSRudolf Cornelissen 
21212566cbdSRudolf Cornelissen bool BT_probe()
21312566cbdSRudolf Cornelissen {
21412566cbdSRudolf Cornelissen 	bool btfound = false;
21512566cbdSRudolf Cornelissen 
2169a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Checking I2C bus(ses) for first possible TV encoder...\n"));
21712566cbdSRudolf Cornelissen 	if (si->ps.i2c_bus0)
21812566cbdSRudolf Cornelissen 	{
21912566cbdSRudolf Cornelissen 		/* try primary adress on bus 0 */
22012566cbdSRudolf Cornelissen 		if (!BT_check(0, PRADR))
22112566cbdSRudolf Cornelissen 		{
22212566cbdSRudolf Cornelissen 			btfound = true;
22312566cbdSRudolf Cornelissen 			si->ps.tv_encoder.adress = PRADR;
22412566cbdSRudolf Cornelissen 			si->ps.tv_encoder.bus = 0;
22512566cbdSRudolf Cornelissen 		}
22612566cbdSRudolf Cornelissen 		else
22712566cbdSRudolf Cornelissen 		{
22812566cbdSRudolf Cornelissen 			/* try secondary adress on bus 0 */
22912566cbdSRudolf Cornelissen 			if (!BT_check(0, SCADR))
23012566cbdSRudolf Cornelissen 			{
23112566cbdSRudolf Cornelissen 				btfound = true;
23212566cbdSRudolf Cornelissen 				si->ps.tv_encoder.adress = SCADR;
23312566cbdSRudolf Cornelissen 				si->ps.tv_encoder.bus = 0;
23412566cbdSRudolf Cornelissen 			}
23512566cbdSRudolf Cornelissen 		}
23612566cbdSRudolf Cornelissen 	}
23712566cbdSRudolf Cornelissen 
23812566cbdSRudolf Cornelissen 	if (si->ps.i2c_bus1 && !btfound)
23912566cbdSRudolf Cornelissen 	{
24012566cbdSRudolf Cornelissen 		/* try primary adress on bus 1 */
24112566cbdSRudolf Cornelissen 		if (!BT_check(1, PRADR))
24212566cbdSRudolf Cornelissen 		{
24312566cbdSRudolf Cornelissen 			btfound = true;
24412566cbdSRudolf Cornelissen 			si->ps.tv_encoder.adress = PRADR;
24512566cbdSRudolf Cornelissen 			si->ps.tv_encoder.bus = 1;
24612566cbdSRudolf Cornelissen 		}
24712566cbdSRudolf Cornelissen 		else
24812566cbdSRudolf Cornelissen 		{
24912566cbdSRudolf Cornelissen 			/* try secondary adress on bus 1 */
25012566cbdSRudolf Cornelissen 			if (!BT_check(1, SCADR))
25112566cbdSRudolf Cornelissen 			{
25212566cbdSRudolf Cornelissen 				btfound = true;
25312566cbdSRudolf Cornelissen 				si->ps.tv_encoder.adress = SCADR;
25412566cbdSRudolf Cornelissen 				si->ps.tv_encoder.bus = 1;
25512566cbdSRudolf Cornelissen 			}
25612566cbdSRudolf Cornelissen 		}
25712566cbdSRudolf Cornelissen 	}
25812566cbdSRudolf Cornelissen 
25912566cbdSRudolf Cornelissen 	/* identify exact TV encoder type */
26012566cbdSRudolf Cornelissen 	if (btfound)
26112566cbdSRudolf Cornelissen 	{
26212566cbdSRudolf Cornelissen 		/* if errors are found, retry */
26312566cbdSRudolf Cornelissen 		/* note:
26412566cbdSRudolf Cornelissen 		 * NACK: occurs on some ASUS V7700 GeForce cards!
26512566cbdSRudolf Cornelissen 		 * (apparantly the video-in chip or another chip resides at 'BT' adresses
26612566cbdSRudolf Cornelissen 		 * there..) */
26712566cbdSRudolf Cornelissen 		uint8 stat;
26812566cbdSRudolf Cornelissen 		uint8 cnt = 0;
26912566cbdSRudolf Cornelissen 		while ((stat = BT_read_type()) && (cnt < 3))
27012566cbdSRudolf Cornelissen 		{
2710ece4905SRudolf Cornelissen 			/* don't retry on unsupported chiptype */
2720ece4905SRudolf Cornelissen 			if (stat == 0x80)
2730ece4905SRudolf Cornelissen 			{
2740ece4905SRudolf Cornelissen 				btfound = 0;
2750ece4905SRudolf Cornelissen 				break;
2760ece4905SRudolf Cornelissen 			}
27712566cbdSRudolf Cornelissen 			cnt++;
27812566cbdSRudolf Cornelissen 		}
2790ece4905SRudolf Cornelissen 		if (stat & 0x7f)
28012566cbdSRudolf Cornelissen 		{
2819a7218c5SRudolf Cornelissen 			LOG(4,("Brooktree: Too much errors occurred, aborting.\n"));
28212566cbdSRudolf Cornelissen 			btfound = 0;
28312566cbdSRudolf Cornelissen 		}
28412566cbdSRudolf Cornelissen 	}
28512566cbdSRudolf Cornelissen 
28612566cbdSRudolf Cornelissen 	if (btfound)
28712566cbdSRudolf Cornelissen 		LOG(4,("Brooktree: Found TV encoder on bus %d, adress $%02x\n",
28812566cbdSRudolf Cornelissen 			si->ps.tv_encoder.bus, si->ps.tv_encoder.adress));
28912566cbdSRudolf Cornelissen 	else
29012566cbdSRudolf Cornelissen 		LOG(4,("Brooktree: No TV encoder Found\n"));
29112566cbdSRudolf Cornelissen 
29212566cbdSRudolf Cornelissen 	return btfound;
29312566cbdSRudolf Cornelissen }
29412566cbdSRudolf Cornelissen 
29577497c49SRudolf Cornelissen static uint8 BT_init_PAL640()
296fb6cadf1Sshatty {
29777497c49SRudolf Cornelissen 	uint8 stat;
298fb6cadf1Sshatty 
29977497c49SRudolf Cornelissen 	uint8 buffer[35];
300fb6cadf1Sshatty 
3019a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 640x480 desktop mode\n"));
3029a7218c5SRudolf Cornelissen 
3039a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
30477497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
30577497c49SRudolf Cornelissen 	buffer[2] = 0x60;
30677497c49SRudolf Cornelissen 	buffer[3] = 0x80;
30777497c49SRudolf Cornelissen 	buffer[4] = 0x8a;
30877497c49SRudolf Cornelissen 	buffer[5] = 0xa6;
30977497c49SRudolf Cornelissen 	buffer[6] = 0x68;
31077497c49SRudolf Cornelissen 	buffer[7] = 0xc1;
31177497c49SRudolf Cornelissen 	buffer[8] = 0x2e;
31277497c49SRudolf Cornelissen 	buffer[9] = 0xf2;
31377497c49SRudolf Cornelissen 	buffer[10] = 0x27;
31477497c49SRudolf Cornelissen 	buffer[11] = 0x00;
31577497c49SRudolf Cornelissen 	buffer[12] = 0xb0;
31677497c49SRudolf Cornelissen 	buffer[13] = 0x0a;
31777497c49SRudolf Cornelissen 	buffer[14] = 0x0b;
31877497c49SRudolf Cornelissen 	buffer[15] = 0x71;
31977497c49SRudolf Cornelissen 	buffer[16] = 0x5a;
32077497c49SRudolf Cornelissen 	buffer[17] = 0xe0;
32177497c49SRudolf Cornelissen 	buffer[18] = 0x36;
32277497c49SRudolf Cornelissen 	buffer[19] = 0x00;
32377497c49SRudolf Cornelissen 	buffer[20] = 0x50;
32477497c49SRudolf Cornelissen 	buffer[21] = 0x72;
32577497c49SRudolf Cornelissen 	buffer[22] = 0x1c;
32677497c49SRudolf Cornelissen 	buffer[23] = 0x8d;		//chip-pin CLKI is pixel clock (only non-default here!)
32777497c49SRudolf Cornelissen 	buffer[24] = 0x24;
32877497c49SRudolf Cornelissen 	buffer[25] = 0xf0;
32977497c49SRudolf Cornelissen 	buffer[26] = 0x58;
33077497c49SRudolf Cornelissen 	buffer[27] = 0x81;
33177497c49SRudolf Cornelissen 	buffer[28] = 0x49;
33277497c49SRudolf Cornelissen 	buffer[29] = 0x8c;
33377497c49SRudolf Cornelissen 	buffer[30] = 0x0c;
33477497c49SRudolf Cornelissen 	buffer[31] = 0x8c;
33577497c49SRudolf Cornelissen 	buffer[32] = 0x79;
33677497c49SRudolf Cornelissen 	buffer[33] = 0x26;
33777497c49SRudolf Cornelissen 	buffer[34] = 0x00;
33877497c49SRudolf Cornelissen 
33977497c49SRudolf Cornelissen 	/* reset status */
34077497c49SRudolf Cornelissen 	i2c_flag_error (-1);
34177497c49SRudolf Cornelissen 
34277497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
34377497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
34477497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
34577497c49SRudolf Cornelissen 	/* log on errors */
34677497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
34777497c49SRudolf Cornelissen 	if (stat)
34877497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL640\n"));
34977497c49SRudolf Cornelissen 
35077497c49SRudolf Cornelissen 	return stat;
35177497c49SRudolf Cornelissen }//end BT_init_PAL640.
35277497c49SRudolf Cornelissen 
35377497c49SRudolf Cornelissen static uint8 BT_init_PAL800()
354fb6cadf1Sshatty {
35577497c49SRudolf Cornelissen 	uint8 stat;
356fb6cadf1Sshatty 
35777497c49SRudolf Cornelissen 	uint8 buffer[35];
358fb6cadf1Sshatty 
3599a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 800x600 desktop mode\n"));
3609a7218c5SRudolf Cornelissen 
3619a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
36277497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
36377497c49SRudolf Cornelissen 	buffer[2] = 0x00;
36477497c49SRudolf Cornelissen 	buffer[3] = 0x20;
36577497c49SRudolf Cornelissen 	buffer[4] = 0xaa;
36677497c49SRudolf Cornelissen 	buffer[5] = 0xca;
36777497c49SRudolf Cornelissen 	buffer[6] = 0x9a;
36877497c49SRudolf Cornelissen 	buffer[7] = 0x0d;
36977497c49SRudolf Cornelissen 	buffer[8] = 0x29;
37077497c49SRudolf Cornelissen 	buffer[9] = 0xfc;
37177497c49SRudolf Cornelissen 	buffer[10] = 0x39;
37277497c49SRudolf Cornelissen 	buffer[11] = 0x00;
37377497c49SRudolf Cornelissen 	buffer[12] = 0xc0;
37477497c49SRudolf Cornelissen 	buffer[13] = 0x8c;
37577497c49SRudolf Cornelissen 	buffer[14] = 0x03;
37677497c49SRudolf Cornelissen 	buffer[15] = 0xee;
37777497c49SRudolf Cornelissen 	buffer[16] = 0x5f;
37877497c49SRudolf Cornelissen 	buffer[17] = 0x58;
37977497c49SRudolf Cornelissen 	buffer[18] = 0x3a;
38077497c49SRudolf Cornelissen 	buffer[19] = 0x66;
38177497c49SRudolf Cornelissen 	buffer[20] = 0x96;
38277497c49SRudolf Cornelissen 	buffer[21] = 0x00;
38377497c49SRudolf Cornelissen 	buffer[22] = 0x00;
38477497c49SRudolf Cornelissen 	buffer[23] = 0x90;		//chip-pin CLKI is pixel clock (only non-default here!)
38577497c49SRudolf Cornelissen 	buffer[24] = 0x24;
38677497c49SRudolf Cornelissen 	buffer[25] = 0xf0;
38777497c49SRudolf Cornelissen 	buffer[26] = 0x57;
38877497c49SRudolf Cornelissen 	buffer[27] = 0x80;
38977497c49SRudolf Cornelissen 	buffer[28] = 0x48;
39077497c49SRudolf Cornelissen 	buffer[29] = 0x8c;
39177497c49SRudolf Cornelissen 	buffer[30] = 0x18;
39277497c49SRudolf Cornelissen 	buffer[31] = 0x28;
39377497c49SRudolf Cornelissen 	buffer[32] = 0x87;
39477497c49SRudolf Cornelissen 	buffer[33] = 0x1f;
39577497c49SRudolf Cornelissen 	buffer[34] = 0x00;
39677497c49SRudolf Cornelissen 
39777497c49SRudolf Cornelissen 	/* reset status */
39877497c49SRudolf Cornelissen 	i2c_flag_error (-1);
39977497c49SRudolf Cornelissen 
40077497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
40177497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
40277497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
40377497c49SRudolf Cornelissen 	/* log on errors */
40477497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
40577497c49SRudolf Cornelissen 	if (stat)
40677497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n"));
40777497c49SRudolf Cornelissen 
40877497c49SRudolf Cornelissen 	return stat;
40977497c49SRudolf Cornelissen }//end BT_init_PAL800.
41077497c49SRudolf Cornelissen 
41177497c49SRudolf Cornelissen static uint8 BT_init_NTSC640()
412fb6cadf1Sshatty {
41377497c49SRudolf Cornelissen 	uint8 stat;
414fb6cadf1Sshatty 
41577497c49SRudolf Cornelissen 	uint8 buffer[35];
41677497c49SRudolf Cornelissen 
4179a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 640x480 desktop mode\n"));
4189a7218c5SRudolf Cornelissen 
4199a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
42077497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
42177497c49SRudolf Cornelissen 	buffer[2] = 0x00;
42277497c49SRudolf Cornelissen 	buffer[3] = 0x80;
42377497c49SRudolf Cornelissen 	buffer[4] = 0x84;
42477497c49SRudolf Cornelissen 	buffer[5] = 0x96;
42577497c49SRudolf Cornelissen 	buffer[6] = 0x60;
42677497c49SRudolf Cornelissen 	buffer[7] = 0x7d;
42777497c49SRudolf Cornelissen 	buffer[8] = 0x22;
42877497c49SRudolf Cornelissen 	buffer[9] = 0xd4;
42977497c49SRudolf Cornelissen 	buffer[10] = 0x27;
43077497c49SRudolf Cornelissen 	buffer[11] = 0x00;
43177497c49SRudolf Cornelissen 	buffer[12] = 0x10;
43277497c49SRudolf Cornelissen 	buffer[13] = 0x7e;
43377497c49SRudolf Cornelissen 	buffer[14] = 0x03;
43477497c49SRudolf Cornelissen 	buffer[15] = 0x58;
43577497c49SRudolf Cornelissen 	buffer[16] = 0x4b;
43677497c49SRudolf Cornelissen 	buffer[17] = 0xe0;
43777497c49SRudolf Cornelissen 	buffer[18] = 0x36;
43877497c49SRudolf Cornelissen 	buffer[19] = 0x92;
43977497c49SRudolf Cornelissen 	buffer[20] = 0x54;
44077497c49SRudolf Cornelissen 	buffer[21] = 0x0e;
44177497c49SRudolf Cornelissen 	buffer[22] = 0x88;
44277497c49SRudolf Cornelissen 	buffer[23] = 0x8c;		//chip-pin CLKI is pixel clock (only non-default here!)
44377497c49SRudolf Cornelissen 	buffer[24] = 0x0a;
44477497c49SRudolf Cornelissen 	buffer[25] = 0xe5;
44577497c49SRudolf Cornelissen 	buffer[26] = 0x76;
44677497c49SRudolf Cornelissen 	buffer[27] = 0x79;
44777497c49SRudolf Cornelissen 	buffer[28] = 0x44;
44877497c49SRudolf Cornelissen 	buffer[29] = 0x85;
44977497c49SRudolf Cornelissen 	buffer[30] = 0x00;
45077497c49SRudolf Cornelissen 	buffer[31] = 0x00;
45177497c49SRudolf Cornelissen 	buffer[32] = 0x80;
45277497c49SRudolf Cornelissen 	buffer[33] = 0x20;
45377497c49SRudolf Cornelissen 	buffer[34] = 0x00;
45477497c49SRudolf Cornelissen 
45577497c49SRudolf Cornelissen 	/* reset status */
45677497c49SRudolf Cornelissen 	i2c_flag_error (-1);
45777497c49SRudolf Cornelissen 
45877497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
45977497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
46077497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
46177497c49SRudolf Cornelissen 	/* log on errors */
46277497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
46377497c49SRudolf Cornelissen 	if (stat)
46477497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640\n"));
46577497c49SRudolf Cornelissen 
46677497c49SRudolf Cornelissen 	return stat;
46777497c49SRudolf Cornelissen }//end BT_init_NTSC640.
46877497c49SRudolf Cornelissen 
46977497c49SRudolf Cornelissen static uint8 BT_init_NTSC800()
470fb6cadf1Sshatty {
47177497c49SRudolf Cornelissen 	uint8 stat;
472fb6cadf1Sshatty 
47377497c49SRudolf Cornelissen 	uint8 buffer[35];
474fb6cadf1Sshatty 
4759a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 800x600 desktop mode\n"));
4769a7218c5SRudolf Cornelissen 
4779a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
47877497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
47977497c49SRudolf Cornelissen 	buffer[2] = 0xa0;
48077497c49SRudolf Cornelissen 	buffer[3] = 0x20;
48177497c49SRudolf Cornelissen 	buffer[4] = 0xb6;
48277497c49SRudolf Cornelissen 	buffer[5] = 0xce;
48377497c49SRudolf Cornelissen 	buffer[6] = 0x84;
48477497c49SRudolf Cornelissen 	buffer[7] = 0x55;
48577497c49SRudolf Cornelissen 	buffer[8] = 0x20;
48677497c49SRudolf Cornelissen 	buffer[9] = 0xd8;
48777497c49SRudolf Cornelissen 	buffer[10] = 0x39;
48877497c49SRudolf Cornelissen 	buffer[11] = 0x00;
48977497c49SRudolf Cornelissen 	buffer[12] = 0x70;
49077497c49SRudolf Cornelissen 	buffer[13] = 0x42;
49177497c49SRudolf Cornelissen 	buffer[14] = 0x03;
49277497c49SRudolf Cornelissen 	buffer[15] = 0xdf;
49377497c49SRudolf Cornelissen 	buffer[16] = 0x56;
49477497c49SRudolf Cornelissen 	buffer[17] = 0x58;
49577497c49SRudolf Cornelissen 	buffer[18] = 0x3a;
49677497c49SRudolf Cornelissen 	buffer[19] = 0xcd;
49777497c49SRudolf Cornelissen 	buffer[20] = 0x9c;
49877497c49SRudolf Cornelissen 	buffer[21] = 0x14;
49977497c49SRudolf Cornelissen 	buffer[22] = 0x3b;
50077497c49SRudolf Cornelissen 	buffer[23] = 0x91;		//chip-pin CLKI is pixel clock (only non-default here!)
50177497c49SRudolf Cornelissen 	buffer[24] = 0x0a;
50277497c49SRudolf Cornelissen 	buffer[25] = 0xe5;
50377497c49SRudolf Cornelissen 	buffer[26] = 0x74;
50477497c49SRudolf Cornelissen 	buffer[27] = 0x77;
50577497c49SRudolf Cornelissen 	buffer[28] = 0x43;
50677497c49SRudolf Cornelissen 	buffer[29] = 0x85;
50777497c49SRudolf Cornelissen 	buffer[30] = 0xba;
50877497c49SRudolf Cornelissen 	buffer[31] = 0xe8;
50977497c49SRudolf Cornelissen 	buffer[32] = 0xa2;
51077497c49SRudolf Cornelissen 	buffer[33] = 0x17;
51177497c49SRudolf Cornelissen 	buffer[34] = 0x00;
51277497c49SRudolf Cornelissen 
51377497c49SRudolf Cornelissen 	/* reset status */
51477497c49SRudolf Cornelissen 	i2c_flag_error (-1);
51577497c49SRudolf Cornelissen 
51677497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
51777497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
51877497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
51977497c49SRudolf Cornelissen 	/* log on errors */
52077497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
52177497c49SRudolf Cornelissen 	if (stat)
52277497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n"));
52377497c49SRudolf Cornelissen 
52477497c49SRudolf Cornelissen 	return stat;
52577497c49SRudolf Cornelissen }//end BT_init_NTSC800.
52677497c49SRudolf Cornelissen 
52777497c49SRudolf Cornelissen static uint8 BT_init_PAL720()
528fb6cadf1Sshatty {
52977497c49SRudolf Cornelissen 	uint8 stat;
53077497c49SRudolf Cornelissen 
53177497c49SRudolf Cornelissen 	uint8 buffer[35];
53277497c49SRudolf Cornelissen 
5339a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 720x576 overscanning DVD mode\n"));
5349a7218c5SRudolf Cornelissen 
5359a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
53677497c49SRudolf Cornelissen 	buffer[1] = 0x76;			//select first bt register to write to
53777497c49SRudolf Cornelissen 	buffer[2] = 0xf0;
53877497c49SRudolf Cornelissen 	buffer[3] = 0xd0;
53977497c49SRudolf Cornelissen 	buffer[4] = 0x82;
54077497c49SRudolf Cornelissen 	buffer[5] = 0x9c;
54177497c49SRudolf Cornelissen 	buffer[6] = 0x5a;
54277497c49SRudolf Cornelissen 	buffer[7] = 0x31;
54377497c49SRudolf Cornelissen 	buffer[8] = 0x16;
54477497c49SRudolf Cornelissen 	buffer[9] = 0x22;
54577497c49SRudolf Cornelissen 	buffer[10] = 0xa6;
54677497c49SRudolf Cornelissen 	buffer[11] = 0x00;
54777497c49SRudolf Cornelissen 	buffer[12] = 0x78;
54877497c49SRudolf Cornelissen 	buffer[13] = 0x93;
54977497c49SRudolf Cornelissen 	buffer[14] = 0x03;
55077497c49SRudolf Cornelissen 	buffer[15] = 0x71;
55177497c49SRudolf Cornelissen 	buffer[16] = 0x2a;
55277497c49SRudolf Cornelissen 	buffer[17] = 0x40;
55377497c49SRudolf Cornelissen 	buffer[18] = 0x0a;
55477497c49SRudolf Cornelissen 	buffer[19] = 0x00;
55577497c49SRudolf Cornelissen 	buffer[20] = 0x50;
55677497c49SRudolf Cornelissen 	buffer[21] = 0x55;
55777497c49SRudolf Cornelissen 	buffer[22] = 0x55;
55877497c49SRudolf Cornelissen 	buffer[23] = 0x8c;		//chip-pin CLKI is pixel clock (only non-default here!)
55977497c49SRudolf Cornelissen 	buffer[24] = 0x24;
56077497c49SRudolf Cornelissen 	buffer[25] = 0xf0;
56177497c49SRudolf Cornelissen 	buffer[26] = 0x59;
56277497c49SRudolf Cornelissen 	buffer[27] = 0x82;
56377497c49SRudolf Cornelissen 	buffer[28] = 0x49;
56477497c49SRudolf Cornelissen 	buffer[29] = 0x8c;
56577497c49SRudolf Cornelissen 	buffer[30] = 0x8e;
56677497c49SRudolf Cornelissen 	buffer[31] = 0xb0;
56777497c49SRudolf Cornelissen 	buffer[32] = 0xe6;
56877497c49SRudolf Cornelissen 	buffer[33] = 0x28;
56977497c49SRudolf Cornelissen 	buffer[34] = 0x00;
57077497c49SRudolf Cornelissen 
57177497c49SRudolf Cornelissen 	/* reset status */
57277497c49SRudolf Cornelissen 	i2c_flag_error (-1);
57377497c49SRudolf Cornelissen 
57477497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
57577497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
57677497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
57777497c49SRudolf Cornelissen 	/* log on errors */
57877497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
57977497c49SRudolf Cornelissen 	if (stat)
58077497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL720\n"));
58177497c49SRudolf Cornelissen 
58277497c49SRudolf Cornelissen 	return stat;
58377497c49SRudolf Cornelissen }//end BT_init_PAL720.
58477497c49SRudolf Cornelissen 
58577497c49SRudolf Cornelissen static uint8 BT_init_NTSC720()
586fb6cadf1Sshatty {
58777497c49SRudolf Cornelissen 	uint8 stat;
588fb6cadf1Sshatty 
58977497c49SRudolf Cornelissen 	uint8 buffer[35];
59077497c49SRudolf Cornelissen 
5919a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 720x480 overscanning DVD mode\n"));
5929a7218c5SRudolf Cornelissen 
5939a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
59477497c49SRudolf Cornelissen 	buffer[1] = 0x76;		//select first bt register to write to.
59577497c49SRudolf Cornelissen 	buffer[2] = 0xf0;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
59677497c49SRudolf Cornelissen 	buffer[3] = 0xd0;		//lsb h_active: h_active = 720 pixels wide port
59777497c49SRudolf Cornelissen 	buffer[4] = 0x83;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
59877497c49SRudolf Cornelissen 	buffer[5] = 0x98;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
59977497c49SRudolf Cornelissen 	buffer[6] = 0x5e;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
60077497c49SRudolf Cornelissen 
60177497c49SRudolf Cornelissen 	//How to find the correct values for h_blank_o and v_blank_o:
60277497c49SRudolf Cornelissen 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
60377497c49SRudolf 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
60477497c49SRudolf Cornelissen 	//    horizontal position is about OK;
60577497c49SRudolf Cornelissen 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
60677497c49SRudolf Cornelissen 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
60777497c49SRudolf Cornelissen 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
60877497c49SRudolf Cornelissen 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
60977497c49SRudolf Cornelissen 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
61077497c49SRudolf Cornelissen 
61177497c49SRudolf Cornelissen 	buffer[7] = 0x28;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
61277497c49SRudolf Cornelissen 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
61377497c49SRudolf Cornelissen 	buffer[8] = 0x18;	//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
61477497c49SRudolf Cornelissen 
61577497c49SRudolf Cornelissen 	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
61677497c49SRudolf Cornelissen 	buffer[10] = 0x26;		//lsn = msn h_clk_o;
61777497c49SRudolf Cornelissen 							//b4-5 = msbits h_active;
61877497c49SRudolf Cornelissen 							//b7 = b8 v_avtive_o.
61977497c49SRudolf Cornelissen 	buffer[11] = 0x00;		//h_fract is always 0.
62077497c49SRudolf Cornelissen 	buffer[12] = 0x78;		//lsb h_clk_i: h_clk_i is horizontal total = 888.
62177497c49SRudolf Cornelissen 	buffer[13] = 0x90; 	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
62277497c49SRudolf Cornelissen 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
62377497c49SRudolf Cornelissen 						//try-out: b3 = msn h_blank_i;
62477497c49SRudolf Cornelissen 							//b4 = vblankdly is always 0.
62577497c49SRudolf Cornelissen 	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
62677497c49SRudolf Cornelissen 	buffer[16] = 0x1a; 	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
62777497c49SRudolf Cornelissen 						//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
62877497c49SRudolf Cornelissen 	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
62977497c49SRudolf Cornelissen 	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
63077497c49SRudolf Cornelissen 							//b3-2 = msn v_active_i;
63177497c49SRudolf Cornelissen 							//b5-4 = ylpf = 3;
63277497c49SRudolf Cornelissen 							//b7-6 = clpf = 0.
63377497c49SRudolf Cornelissen 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
63477497c49SRudolf Cornelissen 	buffer[20] = 0x50;		//b5-0 = msn v_scale;
63577497c49SRudolf Cornelissen 						//scope: tuned. b7-6 = msn h_blank_o.
63677497c49SRudolf Cornelissen 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
63777497c49SRudolf Cornelissen 	buffer[21] = 0x98;		//lsb PLL fract: PLL fract = 0x6e98
63877497c49SRudolf Cornelissen 	buffer[22] = 0x6e;		//msb PLL fract
63977497c49SRudolf Cornelissen 	buffer[23] = 0x8c;		//b5-0 = PLL int: PLL int = 0x0c;
64077497c49SRudolf Cornelissen 							//b6 = by_pll: by_pll = 0;
64177497c49SRudolf Cornelissen 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
64277497c49SRudolf Cornelissen 	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
64377497c49SRudolf Cornelissen 							//b1 = setup = 1 for NTSC;
64477497c49SRudolf Cornelissen 							//b2 = 625line = 0 for NTSC;
64577497c49SRudolf Cornelissen 							//b3 = vsync_dur = 1 for NTSC;
64677497c49SRudolf Cornelissen 							//b4 = dic_screset is always 0;
64777497c49SRudolf Cornelissen 							//b5 = pal_md = 0 for NTSC;
64877497c49SRudolf Cornelissen 							//b6 = eclip is always 0;
64977497c49SRudolf Cornelissen 							//b7 = reserved (en_scart) is always 0.
65077497c49SRudolf Cornelissen 	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
65177497c49SRudolf Cornelissen 	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
65277497c49SRudolf Cornelissen 	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
65377497c49SRudolf Cornelissen 	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
65477497c49SRudolf Cornelissen 	buffer[29] = 0x85;		//my: y $85 for NTSC
65577497c49SRudolf Cornelissen 	buffer[30] = 0x3c;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
65677497c49SRudolf Cornelissen 	buffer[31] = 0x91;		//msc = $20c2913c
65777497c49SRudolf Cornelissen 	buffer[32] = 0xc2;
65877497c49SRudolf Cornelissen 	buffer[33] = 0x20;		//msb msc.
65977497c49SRudolf Cornelissen 	buffer[34] = 0x00;		//phase_off always $00
66077497c49SRudolf Cornelissen 
66177497c49SRudolf Cornelissen 	/* reset status */
66277497c49SRudolf Cornelissen 	i2c_flag_error (-1);
66377497c49SRudolf Cornelissen 
66477497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
66577497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
66677497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
66777497c49SRudolf Cornelissen 	/* log on errors */
66877497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
66977497c49SRudolf Cornelissen 	if (stat)
67077497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC720\n"));
67177497c49SRudolf Cornelissen 
67277497c49SRudolf Cornelissen 	return stat;
67377497c49SRudolf Cornelissen }//end BT_init_NTSC720.
67477497c49SRudolf Cornelissen 
67577497c49SRudolf Cornelissen static uint8 BT_init_PAL800_OS()
676fb6cadf1Sshatty {
67777497c49SRudolf Cornelissen 	uint8 stat;
678fb6cadf1Sshatty 
67977497c49SRudolf Cornelissen 	uint8 buffer[35];
68077497c49SRudolf Cornelissen 
6819a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting PAL 800x600 overscanning VCD mode\n"));
6829a7218c5SRudolf Cornelissen 
6839a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
68477497c49SRudolf Cornelissen 	buffer[1] = 0x76;		//select first bt register to write to.
68577497c49SRudolf Cornelissen 	buffer[2] = 0x60;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
68677497c49SRudolf Cornelissen 	buffer[3] = 0x20;		//lsb h_active: h_active = 800 pixels wide port
68777497c49SRudolf Cornelissen 	buffer[4] = 0x8b;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 64.0uS = 4.70uS for PAL
68877497c49SRudolf Cornelissen 	buffer[5] = 0xa5;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 64.0uS = 5.6uS for PAL
68977497c49SRudolf Cornelissen 	buffer[6] = 0x6b;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 64.0uS = 7.97uS for PAL
69077497c49SRudolf Cornelissen 
69177497c49SRudolf Cornelissen 	//How to find the correct values for h_blank_o and v_blank_o:
69277497c49SRudolf Cornelissen 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
69377497c49SRudolf 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
69477497c49SRudolf Cornelissen 	//    horizontal position is about OK;
69577497c49SRudolf Cornelissen 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
69677497c49SRudolf Cornelissen 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
69777497c49SRudolf Cornelissen 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
69877497c49SRudolf Cornelissen 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
69977497c49SRudolf Cornelissen 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
70077497c49SRudolf Cornelissen 
70177497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
702fb6cadf1Sshatty 	{
70377497c49SRudolf Cornelissen 		buffer[7] = 0xf4;
70477497c49SRudolf Cornelissen 		buffer[8] = 0x17;
705fb6cadf1Sshatty 	}
706fb6cadf1Sshatty 	else
70777497c49SRudolf Cornelissen 	{	//set BT value
70877497c49SRudolf Cornelissen 		buffer[7] = 0xc0;//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV
70977497c49SRudolf Cornelissen 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 64.0uS = 10.0uS for PAL)
71077497c49SRudolf Cornelissen 		buffer[8] = 0x18;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
71177497c49SRudolf Cornelissen 	}
71277497c49SRudolf Cornelissen 
71377497c49SRudolf Cornelissen 	buffer[9] = 0x2e;		//v_active_o: = (active output lines + 2) / field (on TV)
71477497c49SRudolf Cornelissen 	buffer[10] = 0xb7;		//lsn = msn h_clk_o;
71577497c49SRudolf Cornelissen 							//b4-5 = msbits h_active;
71677497c49SRudolf Cornelissen 							//b7 = b8 v_avtive_o.
71777497c49SRudolf Cornelissen 	buffer[11] = 0x00;		//h_fract is always 0.
71877497c49SRudolf Cornelissen 	buffer[12] = 0xb0;		//lsb h_clk_i: h_clk_i is horizontal total = 944.
71977497c49SRudolf Cornelissen 
72077497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
72177497c49SRudolf Cornelissen 		buffer[13] = 0x20;
72277497c49SRudolf Cornelissen 	else				//set BT value
72377497c49SRudolf Cornelissen 		buffer[13] = 0x14;//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
72477497c49SRudolf Cornelissen 
72577497c49SRudolf Cornelissen 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
72677497c49SRudolf Cornelissen 					 	//try-out: b3 = msn h_blank_i;
72777497c49SRudolf Cornelissen 							//b4 = vblankdly is always 0.
72877497c49SRudolf Cornelissen 	buffer[15] = 0x71;		//lsb v_lines_i: v_lines_i = 625
72977497c49SRudolf Cornelissen 
73077497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
73177497c49SRudolf Cornelissen 		buffer[16] = 0x08;
73277497c49SRudolf Cornelissen 	else				//set BT value
73377497c49SRudolf Cornelissen 		buffer[16] = 0x2a;//try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
73477497c49SRudolf Cornelissen 					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
73577497c49SRudolf Cornelissen 
73677497c49SRudolf Cornelissen 	buffer[17] = 0x58;		//lsb v_active_i: v_active_i = 600
73777497c49SRudolf Cornelissen 	buffer[18] = 0x3a;		//b1-0 = msn v_lines_i;
73877497c49SRudolf Cornelissen 							//b3-2 = msn v_active_i;
73977497c49SRudolf Cornelissen 							//b5-4 = ylpf = 3;
74077497c49SRudolf Cornelissen 							//b7-6 = clpf = 0.
74177497c49SRudolf Cornelissen 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
74277497c49SRudolf Cornelissen 	buffer[20] = 0x10;		//b5-0 = msn v_scale;
74377497c49SRudolf Cornelissen 						//scope: tuned. b7-6 = msn h_blank_o.
74477497c49SRudolf Cornelissen 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 50Hz)
74577497c49SRudolf Cornelissen 	buffer[21] = 0x72;		//lsb PLL fract: PLL fract = 0x1c72
74677497c49SRudolf Cornelissen 	buffer[22] = 0x1c;		//msb PLL fract
74777497c49SRudolf Cornelissen 	buffer[23] = 0x8d;		//b5-0 = PLL int: PLL int = 0x0d;
74877497c49SRudolf Cornelissen 							//b6 = by_pll: by_pll = 0;
74977497c49SRudolf Cornelissen 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
75077497c49SRudolf Cornelissen 	buffer[24] = 0x24;		//b0 = ni_out is always 0;
75177497c49SRudolf Cornelissen 							//b1 = setup = 0 for PAL;
75277497c49SRudolf Cornelissen 							//b2 = 625line = 1 for PAL;
75377497c49SRudolf Cornelissen 							//b3 = vsync_dur = 0 for PAL;
75477497c49SRudolf Cornelissen 							//b4 = dic_screset is always 0;
75577497c49SRudolf Cornelissen 							//b5 = pal_md = 1 for PAL;
75677497c49SRudolf Cornelissen 							//b6 = eclip is always 0;
75777497c49SRudolf Cornelissen 							//b7 = reserved (en_scart) is always 0.
75877497c49SRudolf Cornelissen 	buffer[25] = 0xf0;		//sync_amp $f0 for PAL
75977497c49SRudolf Cornelissen 	buffer[26] = 0x57;		//bst_amp $57-$58 for PAL
76077497c49SRudolf Cornelissen 	buffer[27] = 0x80;		//mcr: r-y $80-$81 for PAL
76177497c49SRudolf Cornelissen 	buffer[28] = 0x48;		//mcb: b-y $48-$49 for PAL
76277497c49SRudolf Cornelissen 	buffer[29] = 0x8c;		//my: y $8c for PAL
76377497c49SRudolf Cornelissen 	buffer[30] = 0x31;		//lsb msc: msc b31-0: PAL formula: ((4433619 / pixelclk) * 2^32) = MSC
76477497c49SRudolf Cornelissen 	buffer[31] = 0x8c;		//msc = $26798c31
76577497c49SRudolf Cornelissen 	buffer[32] = 0x79;
76677497c49SRudolf Cornelissen 	buffer[33] = 0x26;		//msb msc.
76777497c49SRudolf Cornelissen 	buffer[34] = 0x00;		//phase_off always $00
76877497c49SRudolf Cornelissen 
76977497c49SRudolf Cornelissen 	/* reset status */
77077497c49SRudolf Cornelissen 	i2c_flag_error (-1);
77177497c49SRudolf Cornelissen 
77277497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
77377497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
77477497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
77577497c49SRudolf Cornelissen 	/* log on errors */
77677497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
77777497c49SRudolf Cornelissen 	if (stat)
77877497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800 OS\n"));
77977497c49SRudolf Cornelissen 
78077497c49SRudolf Cornelissen 	return stat;
78177497c49SRudolf Cornelissen }//end BT_init_PAL800_OS.
78277497c49SRudolf Cornelissen 
78377497c49SRudolf Cornelissen static uint8 BT_init_NTSC640_OS()
784fb6cadf1Sshatty {
78577497c49SRudolf Cornelissen 	uint8 stat;
786fb6cadf1Sshatty 
78777497c49SRudolf Cornelissen 	uint8 buffer[35];
788fb6cadf1Sshatty 
7899a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Setting NTSC 640x480 overscanning VCD mode\n"));
7909a7218c5SRudolf Cornelissen 
7919a7218c5SRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;	//issue I2C write command
79277497c49SRudolf Cornelissen 	buffer[1] = 0x76;		//select first bt register to write to.
79377497c49SRudolf Cornelissen 	buffer[2] = 0x20;		//lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1)
79477497c49SRudolf Cornelissen 	buffer[3] = 0x80;		//lsb h_active: h_active = 640 pixels wide port
79577497c49SRudolf Cornelissen 	buffer[4] = 0x74;	//scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC
79677497c49SRudolf Cornelissen 	buffer[5] = 0x83;	//scope: OK	hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC
79777497c49SRudolf Cornelissen 	buffer[6] = 0x44;	//scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC
798fb6cadf1Sshatty 
79977497c49SRudolf Cornelissen 	//How to find the correct values for h_blank_o and v_blank_o:
80077497c49SRudolf Cornelissen 	// 1. Calculate h_blank_o according to initial setting guideline mentioned below;
80177497c49SRudolf 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
80277497c49SRudolf Cornelissen 	//    horizontal position is about OK;
80377497c49SRudolf Cornelissen 	// 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch);
80477497c49SRudolf Cornelissen 	// 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above);
80577497c49SRudolf Cornelissen 	// 5. If no vertical shivering occurs when image is centered, you're done. Else:
80677497c49SRudolf Cornelissen 	// 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!:
80777497c49SRudolf Cornelissen 	// 7. Make sure you update the Chrontel horizontal Phase setting also then!
808fb6cadf1Sshatty 
80977497c49SRudolf Cornelissen 	buffer[7] = 0xf7;	//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV:
81077497c49SRudolf Cornelissen 						//(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC)
811fb6cadf1Sshatty 
81277497c49SRudolf Cornelissen 	if (si->ps.tv_encoder.type >= CX25870)//set CX value
81377497c49SRudolf Cornelissen 		buffer[8] = 0x1d;
81477497c49SRudolf Cornelissen 	else				//set BT value
81577497c49SRudolf Cornelissen 		buffer[8] = 0x1c;//try-out; scope: checked against other modes, looks OK.	v_blank_o: 1e active line ('pixel')
816fb6cadf1Sshatty 
81777497c49SRudolf Cornelissen 	buffer[9] = 0xf2;		//v_active_o: = (active output lines + 2) / field (on TV)
81877497c49SRudolf Cornelissen 	buffer[10] = 0x26;		//lsn = msn h_clk_o;
81977497c49SRudolf Cornelissen 							//b4-5 = msbits h_active;
82077497c49SRudolf Cornelissen 							//b7 = b8 v_avtive_o.
82177497c49SRudolf Cornelissen 	buffer[11] = 0x00;		//h_fract is always 0.
82277497c49SRudolf Cornelissen 	buffer[12] = 0x10;		//lsb h_clk_i: h_clk_i is horizontal total = 784.
82377497c49SRudolf Cornelissen 	buffer[13] = 0x14;	//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync!
82477497c49SRudolf Cornelissen 	buffer[14] = 0x03;		//b2-0 = msn h_clk_i;
82577497c49SRudolf Cornelissen 						//try-out: b3 = msn h_blank_i;
82677497c49SRudolf Cornelissen 							//b4 = vblankdly is always 0.
82777497c49SRudolf Cornelissen 	buffer[15] = 0x0d;		//lsb v_lines_i: v_lines_i = 525
82877497c49SRudolf Cornelissen 	buffer[16] = 0x18;	//try-out;	v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync!
82977497c49SRudolf Cornelissen 					 	//Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV.
83077497c49SRudolf Cornelissen 	buffer[17] = 0xe0;		//lsb v_active_i: v_active_i = 480
83177497c49SRudolf Cornelissen 	buffer[18] = 0x36;		//b1-0 = msn v_lines_i;
83277497c49SRudolf Cornelissen 							//b3-2 = msn v_active_i;
83377497c49SRudolf Cornelissen 							//b5-4 = ylpf = 3;
83477497c49SRudolf Cornelissen 							//b7-6 = clpf = 0.
83577497c49SRudolf Cornelissen 	buffer[19] = 0x00;		//lsb v_scale: v_scale = off = $1000
83677497c49SRudolf Cornelissen 	buffer[20] = 0x10;		//b5-0 = msn v_scale;
83777497c49SRudolf Cornelissen 						//scope: tuned. b7-6 = msn h_blank_o.
83877497c49SRudolf Cornelissen 							//(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz)
83977497c49SRudolf Cornelissen 	buffer[21] = 0xdb;		//lsb PLL fract: PLL fract = 0xf9db
84077497c49SRudolf Cornelissen 	buffer[22] = 0xf9;		//msb PLL fract
84177497c49SRudolf Cornelissen 	buffer[23] = 0x8a;		//b5-0 = PLL int: PLL int = 0x0a;
84277497c49SRudolf Cornelissen 							//b6 = by_pll: by_pll = 0;
84377497c49SRudolf Cornelissen 							//b7 = EN_XCLK: chip-pin CLKI is pixel clock.
84477497c49SRudolf Cornelissen 	buffer[24] = 0x0a;		//b0 = ni_out is always 0;
84577497c49SRudolf Cornelissen 							//b1 = setup = 1 for NTSC;
84677497c49SRudolf Cornelissen 							//b2 = 625line = 0 for NTSC;
84777497c49SRudolf Cornelissen 							//b3 = vsync_dur = 1 for NTSC;
84877497c49SRudolf Cornelissen 							//b4 = dic_screset is always 0;
84977497c49SRudolf Cornelissen 							//b5 = pal_md = 0 for NTSC;
85077497c49SRudolf Cornelissen 							//b6 = eclip is always 0;
85177497c49SRudolf Cornelissen 							//b7 = reserved (en_scart) is always 0.
85277497c49SRudolf Cornelissen 	buffer[25] = 0xe5;		//sync_amp $e5 for NTSC
85377497c49SRudolf Cornelissen 	buffer[26] = 0x75;		//bst_amp $74-$76 for NTSC
85477497c49SRudolf Cornelissen 	buffer[27] = 0x78;		//mcr: r-y $77-$79 for NTSC
85577497c49SRudolf Cornelissen 	buffer[28] = 0x44;		//mcb: b-y $43-$44 for NTSC
85677497c49SRudolf Cornelissen 	buffer[29] = 0x85;		//my: y $85 for NTSC
85777497c49SRudolf Cornelissen 	buffer[30] = 0x37;		//lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC
85877497c49SRudolf Cornelissen 	buffer[31] = 0x12;		//msc = $251b1237
85977497c49SRudolf Cornelissen 	buffer[32] = 0x1b;
86077497c49SRudolf Cornelissen 	buffer[33] = 0x25;		//msb msc.
86177497c49SRudolf Cornelissen 	buffer[34] = 0x00;		//phase_off always $00
862fb6cadf1Sshatty 
86377497c49SRudolf Cornelissen 	/* reset status */
86477497c49SRudolf Cornelissen 	i2c_flag_error (-1);
865fb6cadf1Sshatty 
86677497c49SRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
86777497c49SRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
86877497c49SRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
86977497c49SRudolf Cornelissen 	/* log on errors */
87077497c49SRudolf Cornelissen 	stat = i2c_flag_error(0);
87177497c49SRudolf Cornelissen 	if (stat)
87277497c49SRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640 OS\n"));
873fb6cadf1Sshatty 
87477497c49SRudolf Cornelissen 	return stat;
87577497c49SRudolf Cornelissen }//end BT_init_NTSC640_OS.
876fb6cadf1Sshatty 
87721f6ecabSRudolf Cornelissen static uint8 BT_testsignal(void)
87821f6ecabSRudolf Cornelissen {
87921f6ecabSRudolf Cornelissen 	uint8 stat;
88021f6ecabSRudolf Cornelissen 
88121f6ecabSRudolf Cornelissen 	uint8 buffer[3];
88221f6ecabSRudolf Cornelissen 
8839a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Enabling testsignal\n"));
8849a7218c5SRudolf Cornelissen 
88521f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
88621f6ecabSRudolf Cornelissen 	/* select bt register for enabling colorbars and outputs */
88721f6ecabSRudolf Cornelissen 	buffer[1] = 0xc4;
88821f6ecabSRudolf Cornelissen 	/* issue the actual command */
88921f6ecabSRudolf Cornelissen 	buffer[2] = 0x05;
89021f6ecabSRudolf Cornelissen 
89121f6ecabSRudolf Cornelissen 	/* reset status */
89221f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
89321f6ecabSRudolf Cornelissen 
89421f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
89521f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
89621f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
89721f6ecabSRudolf Cornelissen 	/* log on errors */
89821f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
89921f6ecabSRudolf Cornelissen 	if (stat)
90021f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
90121f6ecabSRudolf Cornelissen 
90221f6ecabSRudolf Cornelissen 	return stat;
90321f6ecabSRudolf Cornelissen }//end BT_testsignal.
90421f6ecabSRudolf Cornelissen 
90521f6ecabSRudolf Cornelissen static uint8 BT_setup_output(uint8 monstat, uint8 output, uint8 ffilter)
90621f6ecabSRudolf Cornelissen {
90721f6ecabSRudolf Cornelissen 	uint8 stat;
90821f6ecabSRudolf Cornelissen 
90921f6ecabSRudolf Cornelissen 	uint8 buffer[7];
91021f6ecabSRudolf Cornelissen 
91121f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
91221f6ecabSRudolf Cornelissen 	/* select first TV config register to write */
91321f6ecabSRudolf Cornelissen 	buffer[1] = 0xc6;
91421f6ecabSRudolf Cornelissen 	/* input is 24bit mpx'd RGB, BLANK = out, sync = act. hi */
91521f6ecabSRudolf Cornelissen 	buffer[2] = 0x98;
91621f6ecabSRudolf Cornelissen 	/* disable all filters, exept flicker filter */
91721f6ecabSRudolf Cornelissen 	buffer[3] = 0x98;
91821f6ecabSRudolf Cornelissen 	if (!ffilter)
91921f6ecabSRudolf Cornelissen 	{
92021f6ecabSRudolf Cornelissen 		/* disable flicker filter */
92121f6ecabSRudolf Cornelissen 		buffer[3] = 0xc0;
9229a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Disabling flickerfilter\n"));
92321f6ecabSRudolf Cornelissen 	}
9249a7218c5SRudolf Cornelissen 	else
9259a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Enabling flickerfilter\n"));
9269a7218c5SRudolf Cornelissen 
92721f6ecabSRudolf Cornelissen 	/* (disable filters) */
92821f6ecabSRudolf Cornelissen 	buffer[4] = 0xc0;
92921f6ecabSRudolf Cornelissen 	/* (disable filters) */
93021f6ecabSRudolf Cornelissen 	buffer[5] = 0xc0;
93121f6ecabSRudolf Cornelissen 	switch (output)
93221f6ecabSRudolf Cornelissen 	/* Description of ELSA Erazor III hardware layout:
93321f6ecabSRudolf Cornelissen 	 * (This is the default (recommended) layout by NVIDIA)
93421f6ecabSRudolf Cornelissen 	 * DAC A = CVBS
93521f6ecabSRudolf Cornelissen 	 * DAC B = C (chrominance)
93621f6ecabSRudolf Cornelissen 	 * DAC C = Y (luminance) */
93721f6ecabSRudolf Cornelissen 
93821f6ecabSRudolf Cornelissen 	/* Description of Diamond VIPER550:
93921f6ecabSRudolf Cornelissen 	 * DAC A = Not connected
94021f6ecabSRudolf Cornelissen 	 * DAC B = C (chrominance)
94121f6ecabSRudolf Cornelissen 	 * DAC C = Y (luminance)
94221f6ecabSRudolf Cornelissen 	 * To be able to connect to CVBS TV's a special cable is supplied:
94321f6ecabSRudolf Cornelissen 	 * This cable connects the Y (DAC C) output to the TV CVBS input. */
94421f6ecabSRudolf Cornelissen 	{
9459a7218c5SRudolf Cornelissen 	case 1:
9469a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n"));
9479a7218c5SRudolf Cornelissen 		buffer[6] = 0x18;	// Y/C and CVBS out if all ports implemented
94821f6ecabSRudolf Cornelissen 							// in hardware, else only Y/C or CVBS out.
94921f6ecabSRudolf Cornelissen 		break;
9509a7218c5SRudolf Cornelissen 	case 2:
9519a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Outputting CVBS on all outputs\n"));
9529a7218c5SRudolf Cornelissen 		buffer[6] = 0x00;	// put CVBS on all outputs. Used for cards
95321f6ecabSRudolf Cornelissen 		break;				// with only Y/C out and 'translation cable'.
9549a7218c5SRudolf Cornelissen 	default:
9559a7218c5SRudolf Cornelissen 		LOG(4,("Brooktree: Outputting signals according to autodetect status\n"));
9569a7218c5SRudolf Cornelissen 		switch (monstat)	// only 'autodetect' remains...
95721f6ecabSRudolf Cornelissen 		{
9589a7218c5SRudolf Cornelissen 		case 1:
9599a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//only Y connected: must be CVBS!
96021f6ecabSRudolf Cornelissen 			break;
9619a7218c5SRudolf Cornelissen 		case 2:
9629a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//only C connected: must be CVBS!
96321f6ecabSRudolf Cornelissen 			break;				//(though cable is wired wrong...)
9649a7218c5SRudolf Cornelissen 		case 5:
9659a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//CVBS and only Y connected: 2x CVBS!
96621f6ecabSRudolf Cornelissen 			break;			   	//(officially not supported...)
9679a7218c5SRudolf Cornelissen 		case 6:
9689a7218c5SRudolf Cornelissen 			buffer[6] = 0x00;	//CVBS and only C connected: 2x CVBS!
96921f6ecabSRudolf Cornelissen 			break;			   	//(officially not supported...)
9709a7218c5SRudolf Cornelissen 		default:
9719a7218c5SRudolf Cornelissen 			buffer[6] = 0x18;	//nothing, or
97221f6ecabSRudolf Cornelissen 							 	//Y/C only, or
97321f6ecabSRudolf Cornelissen 							 	//CVBS only (but on CVBS output), or
97421f6ecabSRudolf Cornelissen 							 	//Y/C and CVBS connected:
97521f6ecabSRudolf Cornelissen 							 	//So activate recommended signals.
97621f6ecabSRudolf Cornelissen 		}
97721f6ecabSRudolf Cornelissen 	}
97821f6ecabSRudolf Cornelissen 
97921f6ecabSRudolf Cornelissen 	/* reset status */
98021f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
98121f6ecabSRudolf Cornelissen 
98221f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
98321f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
98421f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
98521f6ecabSRudolf Cornelissen 	/* log on errors */
98621f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
98721f6ecabSRudolf Cornelissen 	if (stat)
98821f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n"));
98921f6ecabSRudolf Cornelissen 
99021f6ecabSRudolf Cornelissen 	return stat;
99121f6ecabSRudolf Cornelissen }//end BT_setup_output.
99221f6ecabSRudolf Cornelissen 
99321f6ecabSRudolf Cornelissen static uint8 BT_setup_hphase(uint8 mode)
99421f6ecabSRudolf Cornelissen {
99521f6ecabSRudolf Cornelissen 	uint8 stat, hoffset;
99621f6ecabSRudolf Cornelissen 
99721f6ecabSRudolf Cornelissen 	uint8 buffer[7];
99821f6ecabSRudolf Cornelissen 
9999a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Tuning horizontal phase\n"));
10009a7218c5SRudolf Cornelissen 
100121f6ecabSRudolf Cornelissen 	/* CX needs timing reset (advised on BT also), first 1mS delay needed! */
100221f6ecabSRudolf Cornelissen 	snooze(1000);
100321f6ecabSRudolf Cornelissen 
100421f6ecabSRudolf Cornelissen 	/* values below are all tested on TNT1, TNT2 and GeForce2MX */
100521f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
100621f6ecabSRudolf Cornelissen 	/* select first TV output timing register to write */
100721f6ecabSRudolf Cornelissen 	buffer[1] = 0x6c;
100821f6ecabSRudolf Cornelissen 	/* turn on active video & generate timing reset on CX chips! */
100921f6ecabSRudolf Cornelissen 	buffer[2] = 0x86;
101021f6ecabSRudolf Cornelissen 	/* (set fail save values...) */
101121f6ecabSRudolf Cornelissen 	buffer[3] = 0x00;		//set default horizontal sync offset
101221f6ecabSRudolf Cornelissen 	buffer[4] = 0x02;		//set default horizontal sync width
101321f6ecabSRudolf Cornelissen 	buffer[5] = 0x00;		//set default vertical sync offset
101421f6ecabSRudolf Cornelissen 
101521f6ecabSRudolf Cornelissen 	/* do specific timing setup for all chips and modes: */
101621f6ecabSRudolf Cornelissen 	hoffset = 8;					//TNT2 and TNT2 M64...(8 pixels delayed hpos,
101721f6ecabSRudolf Cornelissen 									//so picture more to the right)
101821f6ecabSRudolf Cornelissen //fixme: check this out...
101921f6ecabSRudolf Cornelissen //	if (ddata->type == 1) hoffset = 0;	//TNT1 or GeForce2... (std hpos)
102021f6ecabSRudolf Cornelissen 									//NOTE: It might be that GeForce needs TNT2 offset:
102121f6ecabSRudolf Cornelissen 									//for now CX chips get seperate extra offset, until sure.
102221f6ecabSRudolf Cornelissen 									//(CX is only found AFAIK on GeForce cards, no BT tested
102321f6ecabSRudolf Cornelissen 									// on GeForce yet. CH was tested on GeForce and seemed to
102421f6ecabSRudolf Cornelissen 									// indicate TNT1 offset was needed.)
102521f6ecabSRudolf Cornelissen 
102621f6ecabSRudolf Cornelissen 	switch (mode)
102721f6ecabSRudolf Cornelissen 	{
102821f6ecabSRudolf Cornelissen 	case NTSC640_TST:
102921f6ecabSRudolf Cornelissen 	case NTSC640:
103021f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
103121f6ecabSRudolf Cornelissen 		buffer[3] = (0x25 + hoffset);	//set horizontal sync offset
103221f6ecabSRudolf Cornelissen 		break;
103321f6ecabSRudolf Cornelissen 	case NTSC800:
103421f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
103521f6ecabSRudolf Cornelissen 		buffer[3] = (0xe1 + hoffset);	//set horizontal sync offset
103621f6ecabSRudolf Cornelissen 		buffer[4] = 0xc2;
103721f6ecabSRudolf Cornelissen 		//Vsync offset reg. does not exist on CX: mode is checked and OK.
103821f6ecabSRudolf Cornelissen 		buffer[5] = 0x40;				//set VSync offset (on BT's only)
103921f6ecabSRudolf Cornelissen 		break;
104021f6ecabSRudolf Cornelissen 	case PAL640:
104121f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
104221f6ecabSRudolf Cornelissen 		buffer[3] = (0xa8 + hoffset);
104321f6ecabSRudolf Cornelissen 		break;
104421f6ecabSRudolf Cornelissen 	case PAL800_TST:
104521f6ecabSRudolf Cornelissen 	case PAL800:
104621f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more...
104721f6ecabSRudolf Cornelissen 		buffer[3] = (0x2c + hoffset);
104821f6ecabSRudolf Cornelissen 		break;
104921f6ecabSRudolf Cornelissen 	case NTSC720:
105021f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870)
105121f6ecabSRudolf Cornelissen 			buffer[3] = (0xb2 + hoffset); //set horizontal sync offset CX
105221f6ecabSRudolf Cornelissen 		else
105321f6ecabSRudolf Cornelissen 			buffer[3] = (0xd0 + hoffset); //set horizontal sync offset BT
105421f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;				//hsync width = max:
105521f6ecabSRudolf Cornelissen 		break;							//to prevent vertical image 'shivering'.
105621f6ecabSRudolf Cornelissen 	case PAL720:
105721f6ecabSRudolf Cornelissen 		buffer[3] = (0xd4 + hoffset);
105821f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;
105921f6ecabSRudolf Cornelissen 		break;
106021f6ecabSRudolf Cornelissen 	case NTSC640_OS:
106121f6ecabSRudolf Cornelissen 		buffer[3] = (0xc8 + hoffset);
106221f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;
106321f6ecabSRudolf Cornelissen 		break;
106421f6ecabSRudolf Cornelissen 	case PAL800_OS:
106521f6ecabSRudolf Cornelissen 		if (si->ps.tv_encoder.type >= CX25870)
106621f6ecabSRudolf Cornelissen 			buffer[3] = (0x78 + hoffset); //set horizontal sync offset CX
106721f6ecabSRudolf Cornelissen 		else
106821f6ecabSRudolf Cornelissen 			buffer[3] = (0xc4 + hoffset); //set horizontal sync offset BT
106921f6ecabSRudolf Cornelissen 		buffer[4] = 0xff;
107021f6ecabSRudolf Cornelissen 		break;
107121f6ecabSRudolf Cornelissen 	default: //nothing to be done here...
107221f6ecabSRudolf Cornelissen 		break;
107321f6ecabSRudolf Cornelissen 	}
107421f6ecabSRudolf Cornelissen 
107521f6ecabSRudolf Cornelissen 	buffer[6] = 0x01;		//set default vertical sync width
107621f6ecabSRudolf Cornelissen 
107721f6ecabSRudolf Cornelissen 	/* reset status */
107821f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
107921f6ecabSRudolf Cornelissen 
108021f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
108121f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
108221f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
108321f6ecabSRudolf Cornelissen 	/* log on errors */
108421f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
108521f6ecabSRudolf Cornelissen 	if (stat)
108621f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while setting up h_phase\n"));
108721f6ecabSRudolf Cornelissen 
108821f6ecabSRudolf Cornelissen 	return stat;
108921f6ecabSRudolf Cornelissen }//end BT_setup_hphase.
109021f6ecabSRudolf Cornelissen 
109121f6ecabSRudolf Cornelissen static uint8 BT_read_monstat(uint8* monstat)
109221f6ecabSRudolf Cornelissen {
109321f6ecabSRudolf Cornelissen 	uint8 stat;
109421f6ecabSRudolf Cornelissen 	uint8 buffer[3];
109521f6ecabSRudolf Cornelissen 
1096efe9c7a6SRudolf Cornelissen 	/* make sure we have the recommended failsafe selected */
1097efe9c7a6SRudolf Cornelissen 	*monstat = 0;
1098efe9c7a6SRudolf Cornelissen 
10999a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Autodetecting connected output devices\n"));
11009a7218c5SRudolf Cornelissen 
110121f6ecabSRudolf Cornelissen 	/* set BT to return connection status in ESTATUS on next read CMD: */
110221f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
110321f6ecabSRudolf Cornelissen 	/* set ESTATUS at b'01' (return conn.stat.) */
110421f6ecabSRudolf Cornelissen 	buffer[1] = 0xc4;
110521f6ecabSRudolf Cornelissen 	/* and leave chip outputs on. */
110621f6ecabSRudolf Cornelissen 	buffer[2] = 0x41;
110721f6ecabSRudolf Cornelissen 
110821f6ecabSRudolf Cornelissen 	/* reset status */
110921f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
111021f6ecabSRudolf Cornelissen 
111121f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
111221f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
111321f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
111421f6ecabSRudolf Cornelissen 	/* log on errors */
111521f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
111621f6ecabSRudolf Cornelissen 	if (stat)
111721f6ecabSRudolf Cornelissen 	{
111821f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (1)\n"));
111921f6ecabSRudolf Cornelissen 		return stat;
112021f6ecabSRudolf Cornelissen 	}
112121f6ecabSRudolf Cornelissen 
112221f6ecabSRudolf Cornelissen 	/* do actual read connection status: */
112321f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
112421f6ecabSRudolf Cornelissen 	/* select register with CHECK_STAT CMD */
112521f6ecabSRudolf Cornelissen 	buffer[1] = 0xba;
112621f6ecabSRudolf Cornelissen 	/* issue actual command. */
112721f6ecabSRudolf Cornelissen 	buffer[2] = 0x40;
112821f6ecabSRudolf Cornelissen 
112921f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
113021f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
113121f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
113221f6ecabSRudolf Cornelissen 	/* log on errors */
113321f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
113421f6ecabSRudolf Cornelissen 	if (stat)
113521f6ecabSRudolf Cornelissen 	{
113621f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (2)\n"));
113721f6ecabSRudolf Cornelissen 		return stat;
113821f6ecabSRudolf Cornelissen 	}
113921f6ecabSRudolf Cornelissen 
114021f6ecabSRudolf Cornelissen 	/* CX: Wait 600uS for signals to stabilize (see datasheet) */
114121f6ecabSRudolf Cornelissen 	/* warning, note:
114221f6ecabSRudolf Cornelissen 	 * datasheet is in error! 60mS needed!! */
114321f6ecabSRudolf Cornelissen 	snooze(60000);
114421f6ecabSRudolf Cornelissen 
114521f6ecabSRudolf Cornelissen 	/* read back updated connection status: */
114621f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + RD;
114721f6ecabSRudolf Cornelissen 
114821f6ecabSRudolf Cornelissen 	/* transmit 1 byte */
114921f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
115021f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 1);
115121f6ecabSRudolf Cornelissen 
115221f6ecabSRudolf Cornelissen 	/* receive 1 byte */
11539a7218c5SRudolf Cornelissen 	/* ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec)
115421f6ecabSRudolf Cornelissen 	 * While the BT's don't care, CX chips will block the SDA line if an ACK gets sent! */
115521f6ecabSRudolf Cornelissen 	buffer[0] = 1;
115621f6ecabSRudolf Cornelissen 	i2c_readbuffer(si->ps.tv_encoder.bus, buffer, 1);
115721f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
115821f6ecabSRudolf Cornelissen 	/* log on errors */
115921f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
116021f6ecabSRudolf Cornelissen 	if (stat)
116121f6ecabSRudolf Cornelissen 	{
116221f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (3)\n"));
116321f6ecabSRudolf Cornelissen 		return stat;
116421f6ecabSRudolf Cornelissen 	}
116521f6ecabSRudolf Cornelissen 
116621f6ecabSRudolf Cornelissen 	*monstat = ((buffer[0] & 0xe0) >> 5);
116721f6ecabSRudolf Cornelissen 	LOG(4,("Brooktree: TV output monitor status = %d\n", *monstat));
116821f6ecabSRudolf Cornelissen 
116921f6ecabSRudolf Cornelissen 	/* instruct BT to go back to normal operation: */
117021f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
117121f6ecabSRudolf Cornelissen 	/* select register with CHECK_STAT CMD */
117221f6ecabSRudolf Cornelissen 	buffer[1] = 0xba;
117321f6ecabSRudolf Cornelissen 	/* issue actual command. */
117421f6ecabSRudolf Cornelissen 	buffer[2] = 0x00;
117521f6ecabSRudolf Cornelissen 
117621f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
117721f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
117821f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
117921f6ecabSRudolf Cornelissen 	/* log on errors */
118021f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
118121f6ecabSRudolf Cornelissen 	if (stat)
118221f6ecabSRudolf Cornelissen 	{
118321f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while reading connection status (4)\n"));
118421f6ecabSRudolf Cornelissen 		return stat;
118521f6ecabSRudolf Cornelissen 	}
118621f6ecabSRudolf Cornelissen 
118721f6ecabSRudolf Cornelissen 	return stat;
118821f6ecabSRudolf Cornelissen }//end BT_read_monstat.
118921f6ecabSRudolf Cornelissen 
119021f6ecabSRudolf Cornelissen static uint8 BT_killclk_blackout(void)
119121f6ecabSRudolf Cornelissen {
119221f6ecabSRudolf Cornelissen 	uint8 stat;
119321f6ecabSRudolf Cornelissen 
119421f6ecabSRudolf Cornelissen 	uint8 buffer[4];
119521f6ecabSRudolf Cornelissen 
11969a7218c5SRudolf Cornelissen 	LOG(4,("Brooktree: Killing clock and/or blacking out (blocking output signals)\n"));
11979a7218c5SRudolf Cornelissen 
119821f6ecabSRudolf Cornelissen 	/* reset status */
119921f6ecabSRudolf Cornelissen 	i2c_flag_error (-1);
120021f6ecabSRudolf Cornelissen 
120121f6ecabSRudolf Cornelissen 	if (si->ps.tv_encoder.type <= BT869) //BT...
120221f6ecabSRudolf Cornelissen 	{
120321f6ecabSRudolf Cornelissen 		/* Only disable external pixelclock input on BT's.
120421f6ecabSRudolf Cornelissen 		 * CX chips will lock the bus if you do this.
120521f6ecabSRudolf Cornelissen 		 * (It looks like the external pixelclock is always OK as long as a valid
120621f6ecabSRudolf Cornelissen 		 * mode is programmed for the TVout chip. This means that disabling the use
120721f6ecabSRudolf Cornelissen 		 * of this clock is not needed anyway.
120821f6ecabSRudolf Cornelissen 		 * If you do disable this input, this pixelclock will rise to about 60Mhz BTW..) */
120921f6ecabSRudolf Cornelissen 
121021f6ecabSRudolf Cornelissen 		/* disable use of external pixelclock source... */
121121f6ecabSRudolf Cornelissen 		/* (should prevent BT for being 'overclocked' by RIVA in VGA-only mode...) */
121221f6ecabSRudolf Cornelissen 		buffer[0] = si->ps.tv_encoder.adress + WR;
121321f6ecabSRudolf Cornelissen 		/* select BT register for setting EN_XCLK */
121421f6ecabSRudolf Cornelissen 		buffer[1] = 0xa0;
121521f6ecabSRudolf Cornelissen 		/* clear it */
121621f6ecabSRudolf Cornelissen 		buffer[2] = 0x00;
121721f6ecabSRudolf Cornelissen 
121821f6ecabSRudolf Cornelissen 		i2c_bstart(si->ps.tv_encoder.bus);
121921f6ecabSRudolf Cornelissen 		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
122021f6ecabSRudolf Cornelissen 		i2c_bstop(si->ps.tv_encoder.bus);
122121f6ecabSRudolf Cornelissen 		/* log on errors */
122221f6ecabSRudolf Cornelissen 		stat = i2c_flag_error(0);
122321f6ecabSRudolf Cornelissen 		if (stat)
122421f6ecabSRudolf Cornelissen 		{
122521f6ecabSRudolf Cornelissen 			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-BT)\n"));
122621f6ecabSRudolf Cornelissen 			return stat;
122721f6ecabSRudolf Cornelissen 		}
122821f6ecabSRudolf Cornelissen 	}
122921f6ecabSRudolf Cornelissen 	else //CX...
123021f6ecabSRudolf Cornelissen 	{
123121f6ecabSRudolf Cornelissen 		/* Disable CX video out (or wild output will be seen on TV..) */
123221f6ecabSRudolf Cornelissen 		buffer[0] = si->ps.tv_encoder.adress + WR;
123321f6ecabSRudolf Cornelissen 		/* select register in CX */
123421f6ecabSRudolf Cornelissen 		buffer[1] = 0x6c;
123521f6ecabSRudolf Cornelissen 		/* disable active video out. */
123621f6ecabSRudolf Cornelissen 		buffer[2] = 0x02;
123721f6ecabSRudolf Cornelissen 
123821f6ecabSRudolf Cornelissen 		i2c_bstart(si->ps.tv_encoder.bus);
123921f6ecabSRudolf Cornelissen 		i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3);
124021f6ecabSRudolf Cornelissen 		i2c_bstop(si->ps.tv_encoder.bus);
124121f6ecabSRudolf Cornelissen 		/* log on errors */
124221f6ecabSRudolf Cornelissen 		stat = i2c_flag_error(0);
124321f6ecabSRudolf Cornelissen 		if (stat)
124421f6ecabSRudolf Cornelissen 		{
124521f6ecabSRudolf Cornelissen 			LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-CX)\n"));
124621f6ecabSRudolf Cornelissen 			return stat;
124721f6ecabSRudolf Cornelissen 		}
124821f6ecabSRudolf Cornelissen 	}
124921f6ecabSRudolf Cornelissen 
125021f6ecabSRudolf Cornelissen 	/* black-out TVout while outputs are enabled... */
125121f6ecabSRudolf Cornelissen 	buffer[0] = si->ps.tv_encoder.adress + WR;
125221f6ecabSRudolf Cornelissen 	/* select first TV config register to write */
125321f6ecabSRudolf Cornelissen 	buffer[1] = 0xc4;
125421f6ecabSRudolf Cornelissen 	/* disable testimage while outputs remain enabled */
125521f6ecabSRudolf Cornelissen 	buffer[2] = 0x01;
125621f6ecabSRudolf Cornelissen 	/* input is 24bit mpx'd RGB, BLANK = in, sync = act. hi */
125721f6ecabSRudolf Cornelissen 	buffer[3] = 0x18;
125821f6ecabSRudolf Cornelissen 
125921f6ecabSRudolf Cornelissen 	i2c_bstart(si->ps.tv_encoder.bus);
126021f6ecabSRudolf Cornelissen 	i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer));
126121f6ecabSRudolf Cornelissen 	i2c_bstop(si->ps.tv_encoder.bus);
126221f6ecabSRudolf Cornelissen 	/* log on errors */
126321f6ecabSRudolf Cornelissen 	stat = i2c_flag_error(0);
126421f6ecabSRudolf Cornelissen 	if (stat)
126521f6ecabSRudolf Cornelissen 	{
126621f6ecabSRudolf Cornelissen 		LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (2)\n"));
126721f6ecabSRudolf Cornelissen 		return stat;
126821f6ecabSRudolf Cornelissen 	}
126921f6ecabSRudolf Cornelissen 
127021f6ecabSRudolf Cornelissen 	return stat;
127121f6ecabSRudolf Cornelissen }//end BT_killclk_blackout.
127221f6ecabSRudolf Cornelissen 
1273b2459715SRudolf Cornelissen uint8 BT_check_tvmode(display_mode target)
1274fb6cadf1Sshatty {
1275b2459715SRudolf Cornelissen 	uint8 status = NOT_SUPPORTED;
1276b2459715SRudolf Cornelissen 	uint32 mode = ((target.timing.h_display) | ((target.timing.v_display) << 16));
1277b2459715SRudolf Cornelissen 
1278b2459715SRudolf Cornelissen 	switch (mode)
1279b2459715SRudolf Cornelissen 	{
1280b2459715SRudolf Cornelissen 	case (640 | (480 << 16)):
1281c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1282c5fe5f2dSRudolf Cornelissen 			status = PAL640;
1283b2459715SRudolf Cornelissen 		if ((target.flags & TV_BITS) == TV_NTSC)
1284b2459715SRudolf Cornelissen 		{
1285b2459715SRudolf Cornelissen 			if (!(target.flags & TV_VIDEO)) status = NTSC640;
1286b2459715SRudolf Cornelissen 			else status = NTSC640_OS;
1287b2459715SRudolf Cornelissen 		}
1288b2459715SRudolf Cornelissen 		break;
1289c5fe5f2dSRudolf Cornelissen 	case (768 | (576 << 16)):
1290c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1291c5fe5f2dSRudolf Cornelissen 			status = PAL800_OS;
1292c5fe5f2dSRudolf Cornelissen 		break;
1293b2459715SRudolf Cornelissen 	case (800 | (600 << 16)):
1294c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO)))
1295c5fe5f2dSRudolf Cornelissen 			status = PAL800;
1296c5fe5f2dSRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_NTSC) && (!(target.flags & TV_VIDEO)))
1297c5fe5f2dSRudolf Cornelissen 			status = NTSC800;
1298b2459715SRudolf Cornelissen 		break;
1299b2459715SRudolf Cornelissen 	case (720 | (480 << 16)):
1300b2459715SRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_NTSC) && (target.flags & TV_VIDEO))
1301b2459715SRudolf Cornelissen 			status = NTSC720;
1302b2459715SRudolf Cornelissen 		break;
1303b2459715SRudolf Cornelissen 	case (720 | (576 << 16)):
1304b2459715SRudolf Cornelissen 		if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO))
1305b2459715SRudolf Cornelissen 			status = PAL720;
1306b2459715SRudolf Cornelissen 		break;
1307b2459715SRudolf Cornelissen 	}
1308b2459715SRudolf Cornelissen 
1309b2459715SRudolf Cornelissen 	return status;
1310b2459715SRudolf Cornelissen }//end BT_check_tvmode.
1311b2459715SRudolf Cornelissen 
1312bd7693f2SRudolf Cornelissen 
1313bd7693f2SRudolf Cornelissen /*
1314*da3804eeSRudolf Cornelissen //BeTVOut's SwitchRIVAtoTV(vtot) timing formula: (note: vtot = (v_total - 2))
1315bd7693f2SRudolf Cornelissen //-----------------------------------------------------------------------------------
1316bd7693f2SRudolf Cornelissen //HORIZONTAL:
1317bd7693f2SRudolf Cornelissen //-----------
1318bd7693f2SRudolf Cornelissen h_sync_start = h_display;
1319bd7693f2SRudolf Cornelissen 
1320bd7693f2SRudolf Cornelissen //fixme, note, checkout:
1321bd7693f2SRudolf Cornelissen //feels like in fact TNT2-M64 nv_crtc.c registerprogramming should be adapted...
1322bd7693f2SRudolf Cornelissen if (TNT2-M64)
1323bd7693f2SRudolf Cornelissen {
1324bd7693f2SRudolf Cornelissen 	h_sync_end = h_display + 8;
1325bd7693f2SRudolf Cornelissen 	h_total = h_display + 56;
1326bd7693f2SRudolf Cornelissen }
1327bd7693f2SRudolf Cornelissen else //TNT1, TNT2, Geforce2... (so default)
1328bd7693f2SRudolf Cornelissen {
1329bd7693f2SRudolf Cornelissen 	h_sync_end = h_display + 16;
1330bd7693f2SRudolf Cornelissen 	h_total = h_display + 48;
1331bd7693f2SRudolf Cornelissen }
1332bd7693f2SRudolf Cornelissen 
1333bd7693f2SRudolf Cornelissen //fixme, note, checkout:
1334bd7693f2SRudolf Cornelissen //BeTVOut uses two 'tweaks':
1335bd7693f2SRudolf Cornelissen // - on TNT2-M64 only:
1336bd7693f2SRudolf Cornelissen //   register h_blank_e is increased with 1 (so should be done in nv_crtc.c here)
1337bd7693f2SRudolf Cornelissen // - all cards:
1338bd7693f2SRudolf Cornelissen //   register h_blank_e b6 = 0.
1339bd7693f2SRudolf Cornelissen //-----------------------------------------------------------------------------------
1340bd7693f2SRudolf Cornelissen //VERTICAL:
1341bd7693f2SRudolf Cornelissen //---------
1342*da3804eeSRudolf Cornelissen v_sync_start = v_display;
1343*da3804eeSRudolf Cornelissen v_total = vtot + 2;
1344*da3804eeSRudolf Cornelissen v_sync_end = v_total - 1; //(This takes care of the 'cursor trash' on TNT1's...)
1345bd7693f2SRudolf Cornelissen //-----------------------------------------------------------------------------------
1346bd7693f2SRudolf Cornelissen */
134785406c4dSRudolf Cornelissen static status_t BT_update_mode_for_gpu(display_mode *target, uint8 tvmode)
134885406c4dSRudolf Cornelissen {
134985406c4dSRudolf Cornelissen 	switch (tvmode)
135085406c4dSRudolf Cornelissen 	{
135185406c4dSRudolf Cornelissen 	case NTSC640:
135285406c4dSRudolf Cornelissen 	case NTSC640_TST:
1353bd7693f2SRudolf Cornelissen 		target->timing.h_display = 640;
1354bd7693f2SRudolf Cornelissen 		target->timing.h_sync_start = 640;
1355bd7693f2SRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1356bd7693f2SRudolf Cornelissen 		{
1357bd7693f2SRudolf Cornelissen 			target->timing.h_sync_end = 648;
1358bd7693f2SRudolf Cornelissen 			target->timing.h_total = 696;
1359bd7693f2SRudolf Cornelissen 		}
1360bd7693f2SRudolf Cornelissen 		else
1361bd7693f2SRudolf Cornelissen 		{
1362bd7693f2SRudolf Cornelissen 			target->timing.h_sync_end = 656;
1363bd7693f2SRudolf Cornelissen 			target->timing.h_total = 688;
1364bd7693f2SRudolf Cornelissen 		}
1365bd7693f2SRudolf Cornelissen 		target->timing.v_display = 480;
1366*da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 480;
1367*da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 555;	//This prevents 'cursor trash' on TNT1's
1368*da3804eeSRudolf Cornelissen 		target->timing.v_total = 556;		//Above 525 because mode scales down
1369bd7693f2SRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
1370*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1371*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((696 * 556 * 60) / 1000);
1372*da3804eeSRudolf Cornelissen 		else
1373*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((688 * 556 * 60) / 1000);
137485406c4dSRudolf Cornelissen 		break;
137585406c4dSRudolf Cornelissen 	case NTSC800:
1376*da3804eeSRudolf Cornelissen 		target->timing.h_display = 800;
1377*da3804eeSRudolf Cornelissen 		target->timing.h_sync_start = 800;
1378*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1379*da3804eeSRudolf Cornelissen 		{
1380*da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 808;
1381*da3804eeSRudolf Cornelissen 			target->timing.h_total = 856;
1382*da3804eeSRudolf Cornelissen 		}
1383*da3804eeSRudolf Cornelissen 		else
1384*da3804eeSRudolf Cornelissen 		{
1385*da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 816;
1386*da3804eeSRudolf Cornelissen 			target->timing.h_total = 848;
1387*da3804eeSRudolf Cornelissen 		}
1388*da3804eeSRudolf Cornelissen 		target->timing.v_display = 600;
1389*da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 600;
1390*da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 685;	//This prevents 'cursor trash' on TNT1's
1391*da3804eeSRudolf Cornelissen 		target->timing.v_total = 686;		//Above 525 because mode scales down
1392*da3804eeSRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
1393*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1394*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((856 * 686 * 60) / 1000);
1395*da3804eeSRudolf Cornelissen 		else
1396*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((848 * 686 * 60) / 1000);
139785406c4dSRudolf Cornelissen 		break;
139885406c4dSRudolf Cornelissen 	case PAL640:
1399bd7693f2SRudolf Cornelissen 		target->timing.h_display = 640;
1400*da3804eeSRudolf Cornelissen 		target->timing.h_sync_start = 640;
1401*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1402*da3804eeSRudolf Cornelissen 		{
1403*da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 648;
1404*da3804eeSRudolf Cornelissen 			target->timing.h_total = 696;
1405*da3804eeSRudolf Cornelissen 		}
1406*da3804eeSRudolf Cornelissen 		else
1407*da3804eeSRudolf Cornelissen 		{
1408*da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 656;
1409*da3804eeSRudolf Cornelissen 			target->timing.h_total = 688;
1410*da3804eeSRudolf Cornelissen 		}
1411bd7693f2SRudolf Cornelissen 		target->timing.v_display = 480;
1412*da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 480;
1413*da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 570;	//This prevents 'cursor trash' on TNT1's
1414*da3804eeSRudolf Cornelissen 		target->timing.v_total = 571;		//Below 625 because mode scales up
1415bd7693f2SRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
1416*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1417*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((696 * 571 * 50) / 1000);
1418*da3804eeSRudolf Cornelissen 		else
1419*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((688 * 571 * 50) / 1000);
142085406c4dSRudolf Cornelissen 		break;
142185406c4dSRudolf Cornelissen 	case PAL800:
142285406c4dSRudolf Cornelissen 	case PAL800_TST:
1423*da3804eeSRudolf Cornelissen 		target->timing.h_display = 800;
1424*da3804eeSRudolf Cornelissen 		target->timing.h_sync_start = 800;
1425*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1426*da3804eeSRudolf Cornelissen 		{
1427*da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 808;
1428*da3804eeSRudolf Cornelissen 			target->timing.h_total = 856;
1429*da3804eeSRudolf Cornelissen 		}
1430*da3804eeSRudolf Cornelissen 		else
1431*da3804eeSRudolf Cornelissen 		{
1432*da3804eeSRudolf Cornelissen 			target->timing.h_sync_end = 816;
1433*da3804eeSRudolf Cornelissen 			target->timing.h_total = 848;
1434*da3804eeSRudolf Cornelissen 		}
1435*da3804eeSRudolf Cornelissen 		target->timing.v_display = 600;
1436*da3804eeSRudolf Cornelissen 		target->timing.v_sync_start = 600;
1437*da3804eeSRudolf Cornelissen 		target->timing.v_sync_end = 695;	//This prevents 'cursor trash' on TNT1's
1438*da3804eeSRudolf Cornelissen 		target->timing.v_total = 696;		//Above 625 because mode scales down
1439*da3804eeSRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
1440*da3804eeSRudolf Cornelissen 		if (si->ps.card_type == NV05M64)
1441*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((856 * 696 * 50) / 1000);
1442*da3804eeSRudolf Cornelissen 		else
1443*da3804eeSRudolf Cornelissen 			target->timing.pixel_clock = ((848 * 696 * 50) / 1000);
144485406c4dSRudolf Cornelissen 		break;
144585406c4dSRudolf Cornelissen 	case NTSC640_OS:
144685406c4dSRudolf Cornelissen 		target->timing.h_display = 640;			//BT H_ACTIVE
144785406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 744;		//set for CH/BT compatible TV output
144885406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 744+20;		//delta is BT H_BLANKI
144985406c4dSRudolf Cornelissen 		target->timing.h_total = 784;			//BT H_CLKI
145085406c4dSRudolf Cornelissen 		target->timing.v_display = 480;			//BT  V_ACTIVEI
145185406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 490;		//set for centered sync pulse
145285406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 490+25;		//delta is BT V_BLANKI
1453*da3804eeSRudolf Cornelissen 		target->timing.v_total = 525;			//BT V_LINESI (== 525: 1:1 scaled mode)
145485406c4dSRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
145585406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((784 * 525 * 60) / 1000); //refresh
145685406c4dSRudolf Cornelissen 		break;
145785406c4dSRudolf Cornelissen 	case PAL800_OS:
145885406c4dSRudolf Cornelissen 		target->timing.h_display = 768;			//H_ACTIVE
145985406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 848;		//set for centered TV output
146085406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 848+20;		//delta is BT H_BLANKI
146185406c4dSRudolf Cornelissen 		target->timing.h_total = 944;			//BT H_CLKI
146285406c4dSRudolf Cornelissen 		target->timing.v_display = 576;			//V_ACTIVEI
146385406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 579;		//set for centered sync pulse
146485406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1465*da3804eeSRudolf Cornelissen 		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
146685406c4dSRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
146785406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((944 * 625 * 50) / 1000); //refresh
146885406c4dSRudolf Cornelissen 		break;
146985406c4dSRudolf Cornelissen 	case NTSC720:
147085406c4dSRudolf Cornelissen 		/* (tested on TNT2 with BT869) */
147185406c4dSRudolf Cornelissen 		target->timing.h_display = 720;			//H_ACTIVE
147285406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 744;		//do not change!
147385406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 744+144;	//delta is H_sync_pulse
147485406c4dSRudolf Cornelissen 		target->timing.h_total = 888;			//BT H_TOTAL
147585406c4dSRudolf Cornelissen 		target->timing.v_display = 480;			//V_ACTIVEI
147685406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 490;		//set for centered sync pulse
147785406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 490+26;		//delta is V_sync_pulse
1478*da3804eeSRudolf Cornelissen 		target->timing.v_total = 525;			//CH V_TOTAL (== 525: 1:1 scaled mode)
147985406c4dSRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
148085406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((888 * 525 * 60) / 1000); //refresh
148185406c4dSRudolf Cornelissen 		break;
148285406c4dSRudolf Cornelissen 	case PAL720:
148385406c4dSRudolf Cornelissen 		target->timing.h_display = 720;			//BT H_ACTIVE
148485406c4dSRudolf Cornelissen 		target->timing.h_sync_start = 744;		//set for centered sync pulse
148585406c4dSRudolf Cornelissen 		target->timing.h_sync_end = 744+140;	//delta is BT H_BLANKI
148685406c4dSRudolf Cornelissen 		target->timing.h_total = 888;			//BT H_CLKI
148785406c4dSRudolf Cornelissen 		target->timing.v_display = 576;			//BT  V_ACTIVEI
148885406c4dSRudolf Cornelissen 		target->timing.v_sync_start = 579;		//set for centered sync pulse
148985406c4dSRudolf Cornelissen 		target->timing.v_sync_end = 579+42;		//delta is BT V_BLANKI
1490*da3804eeSRudolf Cornelissen 		target->timing.v_total = 625;			//BT V_LINESI (== 625: 1:1 scaled mode)
149185406c4dSRudolf Cornelissen //fixme: not actually programmed because PLL is programmed earlier...
149285406c4dSRudolf Cornelissen 		target->timing.pixel_clock = ((888 * 625 * 50) / 1000); //refresh
149385406c4dSRudolf Cornelissen 		break;
149485406c4dSRudolf Cornelissen 	default:
149585406c4dSRudolf Cornelissen 		return B_ERROR;
149685406c4dSRudolf Cornelissen 	}
149785406c4dSRudolf Cornelissen 
149885406c4dSRudolf Cornelissen 	return B_OK;
149985406c4dSRudolf Cornelissen }//end BT_update_mode_for_gpu.
150085406c4dSRudolf Cornelissen 
1501b2459715SRudolf Cornelissen status_t BT_setmode(display_mode target)
1502b2459715SRudolf Cornelissen {
1503efe9c7a6SRudolf Cornelissen 	uint8 tvmode, monstat;
1504efe9c7a6SRudolf Cornelissen 	/* enable flickerfilter in desktop modes, disable it in video modes. */
1505efe9c7a6SRudolf Cornelissen 	uint8 ffilter = 0;
1506b2459715SRudolf Cornelissen 
1507fb6cadf1Sshatty 	/* use a display_mode copy because we might tune it for TVout compatibility */
1508fb6cadf1Sshatty 	display_mode tv_target = target;
1509fb6cadf1Sshatty 
1510fb6cadf1Sshatty 	/* preset new TVout mode */
1511b2459715SRudolf Cornelissen 	tvmode = BT_check_tvmode(tv_target);
1512b2459715SRudolf Cornelissen 	if (!tvmode) return B_ERROR;
1513b2459715SRudolf Cornelissen 
1514b2459715SRudolf Cornelissen //fixme: only testing singlehead cards for now...
1515b2459715SRudolf Cornelissen if (si->ps.secondary_head)
1516fb6cadf1Sshatty {
1517b2459715SRudolf Cornelissen 	head1_set_timing(tv_target);
1518b2459715SRudolf Cornelissen 	return B_ERROR;
1519fb6cadf1Sshatty }
1520b2459715SRudolf Cornelissen 
1521efe9c7a6SRudolf Cornelissen 	/* fixme: reset BT should be here...
1522efe9c7a6SRudolf Cornelissen 	 * (but: beware of the 'locked SDA' syndrome then!) */
1523efe9c7a6SRudolf Cornelissen 	BT_killclk_blackout();
1524efe9c7a6SRudolf Cornelissen 
1525efe9c7a6SRudolf Cornelissen 	/* read current output devices connection status */
1526efe9c7a6SRudolf Cornelissen 	BT_read_monstat(&monstat);
1527efe9c7a6SRudolf Cornelissen 
1528efe9c7a6SRudolf Cornelissen 	//fixme?
1529efe9c7a6SRudolf Cornelissen 	//'slowdown RIVA clock' if TVout is requested:
1530efe9c7a6SRudolf Cornelissen 	//makes sure TVout chip is not being overclocked! (VESA640/800 is safe..)
1531efe9c7a6SRudolf Cornelissen 	//NOTE: it looks like this is unnesessary after all..
1532efe9c7a6SRudolf Cornelissen 
1533efe9c7a6SRudolf Cornelissen 	/* (pre)set TV mode */
1534efe9c7a6SRudolf Cornelissen 	/* note:
1535efe9c7a6SRudolf Cornelissen 	 * Manual config is non-dependent of the state of the PAL hardware input pin;
1536efe9c7a6SRudolf Cornelissen 	 * Also SDA lockups occur when setting EN_XCLK after autoconfig!
1537efe9c7a6SRudolf Cornelissen 	 * Make sure PAL_MD=0 for NTSC and PAL_MD = 1 for PAL... */
1538b2459715SRudolf Cornelissen 	switch (tvmode)
1539fb6cadf1Sshatty 	{
1540b2459715SRudolf Cornelissen 	case NTSC640:
1541b2459715SRudolf Cornelissen 	case NTSC640_TST:
1542efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1543efe9c7a6SRudolf Cornelissen 		BT_init_NTSC640();
1544b2459715SRudolf Cornelissen 		break;
1545b2459715SRudolf Cornelissen 	case NTSC800:
1546efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1547efe9c7a6SRudolf Cornelissen 		BT_init_NTSC800();
1548b2459715SRudolf Cornelissen 		break;
1549b2459715SRudolf Cornelissen 	case PAL640:
1550efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1551efe9c7a6SRudolf Cornelissen 		BT_init_PAL640();
1552b2459715SRudolf Cornelissen 		break;
1553b2459715SRudolf Cornelissen 	case PAL800:
1554b2459715SRudolf Cornelissen 	case PAL800_TST:
1555efe9c7a6SRudolf Cornelissen 		ffilter = 1;
1556efe9c7a6SRudolf Cornelissen 		BT_init_PAL800();
1557b2459715SRudolf Cornelissen 		break;
1558b2459715SRudolf Cornelissen 	case NTSC640_OS:
1559efe9c7a6SRudolf Cornelissen 		BT_init_NTSC640_OS();
1560b2459715SRudolf Cornelissen 		break;
1561b2459715SRudolf Cornelissen 	case PAL800_OS:
1562efe9c7a6SRudolf Cornelissen 		BT_init_PAL800_OS();
1563b2459715SRudolf Cornelissen 		break;
1564b2459715SRudolf Cornelissen 	case NTSC720:
1565efe9c7a6SRudolf Cornelissen 		BT_init_NTSC720();
1566b2459715SRudolf Cornelissen 		break;
1567b2459715SRudolf Cornelissen 	case PAL720:
1568efe9c7a6SRudolf Cornelissen 		BT_init_PAL720();
1569b2459715SRudolf Cornelissen 		break;
1570fb6cadf1Sshatty 	}
1571fb6cadf1Sshatty 
1572efe9c7a6SRudolf Cornelissen 	/* modify BT Hphase signal to center TV image... */
1573efe9c7a6SRudolf Cornelissen 	BT_setup_hphase(tvmode);
1574fb6cadf1Sshatty 
1575efe9c7a6SRudolf Cornelissen 	/* disable Macro mode */
1576efe9c7a6SRudolf Cornelissen 	switch (tvmode)
1577efe9c7a6SRudolf Cornelissen 	{
1578efe9c7a6SRudolf Cornelissen 	case NTSC640:
1579efe9c7a6SRudolf Cornelissen 	case NTSC640_TST:
1580efe9c7a6SRudolf Cornelissen 	case NTSC800:
1581efe9c7a6SRudolf Cornelissen 	case NTSC640_OS:
1582efe9c7a6SRudolf Cornelissen 	case NTSC720:
1583efe9c7a6SRudolf Cornelissen 		/* NTSC */
1584efe9c7a6SRudolf Cornelissen 		BT_set_macro (0, 0);
1585efe9c7a6SRudolf Cornelissen 		break;
1586efe9c7a6SRudolf Cornelissen 	default:
1587efe9c7a6SRudolf Cornelissen 		/* PAL */
1588efe9c7a6SRudolf Cornelissen 		BT_set_macro (1, 0);
1589efe9c7a6SRudolf Cornelissen 		break;
1590efe9c7a6SRudolf Cornelissen 	}
1591fb6cadf1Sshatty 
1592efe9c7a6SRudolf Cornelissen 	/* setup output signal routing and flickerfilter */
1593efe9c7a6SRudolf Cornelissen 	//fixme: add output force settings in nv.settings, defaulting to autodetect.
1594efe9c7a6SRudolf Cornelissen 	BT_setup_output(monstat, 0, ffilter);
1595fb6cadf1Sshatty 
1596efe9c7a6SRudolf Cornelissen //tmp: enabling testimage...
1597efe9c7a6SRudolf Cornelissen BT_testsignal();
1598fb6cadf1Sshatty 
159985406c4dSRudolf Cornelissen 	/* update the GPU CRTC timing for the requested mode */
160085406c4dSRudolf Cornelissen 	BT_update_mode_for_gpu(&tv_target, tvmode);
1601fb6cadf1Sshatty 
1602efe9c7a6SRudolf Cornelissen 	/* setup GPU CRTC timing */
1603b2459715SRudolf Cornelissen 	head1_set_timing(tv_target);
1604fb6cadf1Sshatty 
1605efe9c7a6SRudolf Cornelissen 	//fixme: set GPU CRTC to slave mode...
1606efe9c7a6SRudolf Cornelissen 
1607efe9c7a6SRudolf Cornelissen 	//fixme: add code to disable VGA screen when TVout enabled
1608efe9c7a6SRudolf Cornelissen 	//(use via nv.setting preset)
1609fb6cadf1Sshatty 
1610b2459715SRudolf Cornelissen 	return B_OK;
1611fb6cadf1Sshatty }
1612