112566cbdSRudolf Cornelissen /* 212566cbdSRudolf Cornelissen Author: 3b2459715SRudolf Cornelissen Rudolf Cornelissen 4/2002-10/2005 4fb6cadf1Sshatty */ 5fb6cadf1Sshatty 6fb6cadf1Sshatty #define MODULE_BIT 0x00100000 7fb6cadf1Sshatty 8fb6cadf1Sshatty #include "nv_std.h" 9fb6cadf1Sshatty 1012566cbdSRudolf Cornelissen #define PRADR 0x88 1112566cbdSRudolf Cornelissen #define SCADR 0x8a 1212566cbdSRudolf Cornelissen #define WR 0x00 1312566cbdSRudolf Cornelissen #define RD 0x01 1412566cbdSRudolf Cornelissen 1521f6ecabSRudolf Cornelissen enum 1621f6ecabSRudolf Cornelissen { // TVoutput mode to set 17b2459715SRudolf Cornelissen NOT_SUPPORTED = 0, 1821f6ecabSRudolf Cornelissen NTSC640_TST, 1921f6ecabSRudolf Cornelissen NTSC640, 2021f6ecabSRudolf Cornelissen NTSC800, 2121f6ecabSRudolf Cornelissen PAL800_TST, 2221f6ecabSRudolf Cornelissen PAL640, 2321f6ecabSRudolf Cornelissen PAL800, 2421f6ecabSRudolf Cornelissen NTSC720, 2521f6ecabSRudolf Cornelissen PAL720, 2621f6ecabSRudolf Cornelissen NTSC640_OS, 2721f6ecabSRudolf Cornelissen PAL800_OS 2821f6ecabSRudolf Cornelissen }; 2921f6ecabSRudolf Cornelissen 30b0fce481SRudolf Cornelissen /* Dirk Thierbach's Macro setup for registers 0xda-0xfe. 31b0fce481SRudolf Cornelissen * (also see http://sourceforge.net/projects/nv-tv-out/) */ 329a7218c5SRudolf Cornelissen static uint8 BtNtscMacro0 [] = { 339a7218c5SRudolf Cornelissen 0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09, 349a7218c5SRudolf Cornelissen 0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x00,0x00}; 359a7218c5SRudolf Cornelissen static uint8 BtNtscMacro1 [] = { 369a7218c5SRudolf Cornelissen 0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09, 379a7218c5SRudolf Cornelissen 0xbd,0x67,0xb5,0x90,0xb2,0x7d,0x63,0x00}; 389a7218c5SRudolf Cornelissen static uint8 BtNtscMacro2 [] = { 399a7218c5SRudolf Cornelissen 0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09, 409a7218c5SRudolf Cornelissen 0xbd,0x6c,0x31,0x92,0x32,0xdd,0xe3,0x00}; 419a7218c5SRudolf Cornelissen static uint8 BtNtscMacro3 [] = { 429a7218c5SRudolf Cornelissen 0x0f,0xfc,0x20,0xd0,0x6f,0x0f,0x00,0x00,0x0c,0xf3,0x09, 439a7218c5SRudolf Cornelissen 0xbd,0x66,0xb5,0x90,0xb2,0x7d,0xe3,0x00}; 449a7218c5SRudolf Cornelissen 459a7218c5SRudolf Cornelissen static uint8 BtPalMacro0 [] = { 469a7218c5SRudolf Cornelissen 0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05, 479a7218c5SRudolf Cornelissen 0xd3,0x78,0xa2,0x25,0x54,0xa5,0x00,0x00}; 489a7218c5SRudolf Cornelissen static uint8 BtPalMacro1 [] = { 499a7218c5SRudolf Cornelissen 0x05,0x57,0x20,0x40,0x6e,0x7e,0xf4,0x51,0x0f,0xf1,0x05, 509a7218c5SRudolf Cornelissen 0xd3,0x78,0xa2,0x25,0x54,0xa5,0x63,0x00}; 519a7218c5SRudolf Cornelissen 529a7218c5SRudolf Cornelissen static uint8 BT_set_macro (int std, int mode) 539a7218c5SRudolf Cornelissen { 549a7218c5SRudolf Cornelissen uint8 stat; 559a7218c5SRudolf Cornelissen uint8 buffer[21]; 569a7218c5SRudolf Cornelissen 57b0fce481SRudolf Cornelissen LOG(4,("Brooktree: Setting Macro:\n")); 589a7218c5SRudolf Cornelissen 599a7218c5SRudolf Cornelissen if ((std < 0) | (std > 1) | (mode < 0) | (mode > 3)) 609a7218c5SRudolf Cornelissen { 619a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Non existing mode or standard selected, aborting.\n")); 629a7218c5SRudolf Cornelissen return 0x80; 639a7218c5SRudolf Cornelissen } 649a7218c5SRudolf Cornelissen 659a7218c5SRudolf Cornelissen switch (std) 669a7218c5SRudolf Cornelissen { 679a7218c5SRudolf Cornelissen case 0: 689a7218c5SRudolf Cornelissen /* NTSC */ 699a7218c5SRudolf Cornelissen switch (mode) 709a7218c5SRudolf Cornelissen { 719a7218c5SRudolf Cornelissen case 0: 729a7218c5SRudolf Cornelissen /* disabled */ 73b0fce481SRudolf Cornelissen LOG(4,("Brooktree: NTSC, disabled\n")); 749a7218c5SRudolf Cornelissen memcpy(&buffer[2], &BtNtscMacro0, 19); 759a7218c5SRudolf Cornelissen break; 769a7218c5SRudolf Cornelissen case 1: 779a7218c5SRudolf Cornelissen /* enabled mode 1 */ 78b0fce481SRudolf Cornelissen LOG(4,("Brooktree: NTSC, mode 1\n")); 799a7218c5SRudolf Cornelissen memcpy(&buffer[2], &BtNtscMacro1, 19); 809a7218c5SRudolf Cornelissen break; 819a7218c5SRudolf Cornelissen case 2: 829a7218c5SRudolf Cornelissen /* enabled mode 2 */ 83b0fce481SRudolf Cornelissen LOG(4,("Brooktree: NTSC, mode 2\n")); 849a7218c5SRudolf Cornelissen memcpy(&buffer[2], &BtNtscMacro2, 19); 859a7218c5SRudolf Cornelissen break; 869a7218c5SRudolf Cornelissen case 3: 879a7218c5SRudolf Cornelissen /* enabled mode 3 */ 88b0fce481SRudolf Cornelissen LOG(4,("Brooktree: NTSC, mode 3\n")); 899a7218c5SRudolf Cornelissen memcpy(&buffer[2], &BtNtscMacro3, 19); 909a7218c5SRudolf Cornelissen break; 919a7218c5SRudolf Cornelissen } 929a7218c5SRudolf Cornelissen break; 939a7218c5SRudolf Cornelissen case 1: 949a7218c5SRudolf Cornelissen /* PAL */ 959a7218c5SRudolf Cornelissen switch (mode) 969a7218c5SRudolf Cornelissen { 979a7218c5SRudolf Cornelissen case 0: 989a7218c5SRudolf Cornelissen /* disabled */ 99b0fce481SRudolf Cornelissen LOG(4,("Brooktree: PAL, disabled\n")); 1009a7218c5SRudolf Cornelissen memcpy(&buffer[2], &BtPalMacro0, 19); 1019a7218c5SRudolf Cornelissen break; 1029a7218c5SRudolf Cornelissen case 1: 1039a7218c5SRudolf Cornelissen case 2: 1049a7218c5SRudolf Cornelissen case 3: 1059a7218c5SRudolf Cornelissen /* enabled */ 106b0fce481SRudolf Cornelissen LOG(4,("Brooktree: PAL, enabled\n")); 1079a7218c5SRudolf Cornelissen memcpy(&buffer[2], &BtPalMacro1, 19); 1089a7218c5SRudolf Cornelissen break; 1099a7218c5SRudolf Cornelissen } 1109a7218c5SRudolf Cornelissen break; 1119a7218c5SRudolf Cornelissen } 1129a7218c5SRudolf Cornelissen 1139a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 1149a7218c5SRudolf Cornelissen /* select first register to write to */ 1159a7218c5SRudolf Cornelissen buffer[1] = 0xda; 1169a7218c5SRudolf Cornelissen 1179a7218c5SRudolf Cornelissen /* reset status */ 1189a7218c5SRudolf Cornelissen i2c_flag_error (-1); 1199a7218c5SRudolf Cornelissen 1209a7218c5SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 1219a7218c5SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 1229a7218c5SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 1239a7218c5SRudolf Cornelissen /* log on errors */ 1249a7218c5SRudolf Cornelissen stat = i2c_flag_error(0); 1259a7218c5SRudolf Cornelissen if (stat) 1269a7218c5SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting Macro\n")); 1279a7218c5SRudolf Cornelissen 1289a7218c5SRudolf Cornelissen return stat; 1299a7218c5SRudolf Cornelissen }//end BT_set_macro. 1309a7218c5SRudolf Cornelissen 13112566cbdSRudolf Cornelissen /* 13212566cbdSRudolf Cornelissen see if a (possible) BT/CX chip resides at the given adress. 13312566cbdSRudolf Cornelissen Return zero if no errors occurred. 13412566cbdSRudolf Cornelissen */ 13512566cbdSRudolf Cornelissen static uint8 BT_check (uint8 bus, uint8 adress) 13612566cbdSRudolf Cornelissen { 1370ece4905SRudolf Cornelissen uint8 buffer[3]; 13812566cbdSRudolf Cornelissen 1390ece4905SRudolf Cornelissen buffer[0] = adress + WR; 14012566cbdSRudolf Cornelissen /* set ESTATUS at b'00'; and enable bt chip-outputs 14112566cbdSRudolf Cornelissen * WARNING: 14212566cbdSRudolf Cornelissen * If bit0 = 0 is issued below (EN_OUT = disabled), the BT will lock SDA 14312566cbdSRudolf Cornelissen * after writing adress $A0 (setting EN_XCLK)!!! 1449a7218c5SRudolf Cornelissen * Until a reboot the corresponding I2C bus will be inacessable then!!! */ 1450ece4905SRudolf Cornelissen buffer[1] = 0xc4; 14612566cbdSRudolf Cornelissen /* fixme: if testimage 'was' active txbuffer[3] should become 0x05... 14712566cbdSRudolf Cornelissen * (currently this cannot be detected in a 'foolproof' way so don't touch...) */ 14812566cbdSRudolf Cornelissen /* (ESTATUS b'0x' means: RX ID and VERSION info later..) */ 1490ece4905SRudolf Cornelissen buffer[2] = 0x01; 1500ece4905SRudolf Cornelissen 1510ece4905SRudolf Cornelissen /* reset status */ 1520ece4905SRudolf Cornelissen i2c_flag_error (-1); 1530ece4905SRudolf Cornelissen 1540ece4905SRudolf Cornelissen /* do check */ 1550ece4905SRudolf Cornelissen i2c_bstart(bus); 1560ece4905SRudolf Cornelissen i2c_writebuffer(bus, buffer, sizeof(buffer)); 15712566cbdSRudolf Cornelissen i2c_bstop(bus); 15812566cbdSRudolf Cornelissen return i2c_flag_error(0); 15912566cbdSRudolf Cornelissen } 16012566cbdSRudolf Cornelissen 16112566cbdSRudolf Cornelissen /* identify chiptype */ 16212566cbdSRudolf Cornelissen static uint8 BT_read_type (void) 16312566cbdSRudolf Cornelissen { 1640ece4905SRudolf Cornelissen uint8 id, type, stat; 1650ece4905SRudolf Cornelissen uint8 buffer[3]; 1660ece4905SRudolf Cornelissen 1670ece4905SRudolf Cornelissen /* Make sure a CX (Conexant) chip (if this turns out to be there) is set to 1680ece4905SRudolf Cornelissen * BT-compatibility mode! (This command will do nothing on a BT chip...) */ 1690ece4905SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 1700ece4905SRudolf Cornelissen /* select CX reg. for BT-compatible readback, video still off */ 1710ece4905SRudolf Cornelissen buffer[1] = 0x6c; 1720ece4905SRudolf Cornelissen /* set it up */ 1730ece4905SRudolf Cornelissen buffer[2] = 0x02; 17412566cbdSRudolf Cornelissen 17512566cbdSRudolf Cornelissen /* reset status */ 17612566cbdSRudolf Cornelissen i2c_flag_error (-1); 17712566cbdSRudolf Cornelissen 17812566cbdSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 1790ece4905SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 18012566cbdSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 18112566cbdSRudolf Cornelissen /* abort on errors */ 18212566cbdSRudolf Cornelissen stat = i2c_flag_error(0); 18312566cbdSRudolf Cornelissen if (stat) return stat; 18412566cbdSRudolf Cornelissen 18512566cbdSRudolf Cornelissen /* Do actual readtype command */ 18612566cbdSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 1879a7218c5SRudolf Cornelissen /* issue I2C read command */ 18812566cbdSRudolf Cornelissen i2c_writebyte(si->ps.tv_encoder.bus, si->ps.tv_encoder.adress + RD); 18912566cbdSRudolf Cornelissen /* receive 1 byte; 1909a7218c5SRudolf Cornelissen * ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec). */ 19112566cbdSRudolf Cornelissen /* note: 19212566cbdSRudolf Cornelissen * While the BT's don't care, CX chips will block the SDA line if 19312566cbdSRudolf Cornelissen * an ACK gets sent! */ 19412566cbdSRudolf Cornelissen id = i2c_readbyte(si->ps.tv_encoder.bus, true); 19512566cbdSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 19612566cbdSRudolf Cornelissen /* abort on errors */ 19712566cbdSRudolf Cornelissen stat = i2c_flag_error(0); 19812566cbdSRudolf Cornelissen if (stat) return stat; 19912566cbdSRudolf Cornelissen 2000ece4905SRudolf Cornelissen /* check type to be supported one */ 2010ece4905SRudolf Cornelissen type = (id & 0xe0) >> 5; 2020ece4905SRudolf Cornelissen if (type > 3) 2030ece4905SRudolf Cornelissen { 2040ece4905SRudolf Cornelissen LOG(4,("Brooktree: Found unsupported encoder type %d, aborting.\n", type)); 2050ece4905SRudolf Cornelissen return 0x80; 2060ece4905SRudolf Cornelissen } 2070ece4905SRudolf Cornelissen 20812566cbdSRudolf Cornelissen /* inform driver about TV encoder found */ 20912566cbdSRudolf Cornelissen si->ps.tvout = true; 2100ece4905SRudolf Cornelissen si->ps.tv_encoder.type = BT868 + type; 21112566cbdSRudolf Cornelissen si->ps.tv_encoder.version = id & 0x1f; 21212566cbdSRudolf Cornelissen 21312566cbdSRudolf Cornelissen return stat; 21412566cbdSRudolf Cornelissen } 21512566cbdSRudolf Cornelissen 21612566cbdSRudolf Cornelissen bool BT_probe() 21712566cbdSRudolf Cornelissen { 21812566cbdSRudolf Cornelissen bool btfound = false; 21912566cbdSRudolf Cornelissen 2209a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Checking I2C bus(ses) for first possible TV encoder...\n")); 22112566cbdSRudolf Cornelissen if (si->ps.i2c_bus0) 22212566cbdSRudolf Cornelissen { 22312566cbdSRudolf Cornelissen /* try primary adress on bus 0 */ 22412566cbdSRudolf Cornelissen if (!BT_check(0, PRADR)) 22512566cbdSRudolf Cornelissen { 22612566cbdSRudolf Cornelissen btfound = true; 22712566cbdSRudolf Cornelissen si->ps.tv_encoder.adress = PRADR; 22812566cbdSRudolf Cornelissen si->ps.tv_encoder.bus = 0; 22912566cbdSRudolf Cornelissen } 23012566cbdSRudolf Cornelissen else 23112566cbdSRudolf Cornelissen { 23212566cbdSRudolf Cornelissen /* try secondary adress on bus 0 */ 23312566cbdSRudolf Cornelissen if (!BT_check(0, SCADR)) 23412566cbdSRudolf Cornelissen { 23512566cbdSRudolf Cornelissen btfound = true; 23612566cbdSRudolf Cornelissen si->ps.tv_encoder.adress = SCADR; 23712566cbdSRudolf Cornelissen si->ps.tv_encoder.bus = 0; 23812566cbdSRudolf Cornelissen } 23912566cbdSRudolf Cornelissen } 24012566cbdSRudolf Cornelissen } 24112566cbdSRudolf Cornelissen 24212566cbdSRudolf Cornelissen if (si->ps.i2c_bus1 && !btfound) 24312566cbdSRudolf Cornelissen { 24412566cbdSRudolf Cornelissen /* try primary adress on bus 1 */ 24512566cbdSRudolf Cornelissen if (!BT_check(1, PRADR)) 24612566cbdSRudolf Cornelissen { 24712566cbdSRudolf Cornelissen btfound = true; 24812566cbdSRudolf Cornelissen si->ps.tv_encoder.adress = PRADR; 24912566cbdSRudolf Cornelissen si->ps.tv_encoder.bus = 1; 25012566cbdSRudolf Cornelissen } 25112566cbdSRudolf Cornelissen else 25212566cbdSRudolf Cornelissen { 25312566cbdSRudolf Cornelissen /* try secondary adress on bus 1 */ 25412566cbdSRudolf Cornelissen if (!BT_check(1, SCADR)) 25512566cbdSRudolf Cornelissen { 25612566cbdSRudolf Cornelissen btfound = true; 25712566cbdSRudolf Cornelissen si->ps.tv_encoder.adress = SCADR; 25812566cbdSRudolf Cornelissen si->ps.tv_encoder.bus = 1; 25912566cbdSRudolf Cornelissen } 26012566cbdSRudolf Cornelissen } 26112566cbdSRudolf Cornelissen } 26212566cbdSRudolf Cornelissen 26312566cbdSRudolf Cornelissen /* identify exact TV encoder type */ 26412566cbdSRudolf Cornelissen if (btfound) 26512566cbdSRudolf Cornelissen { 26612566cbdSRudolf Cornelissen /* if errors are found, retry */ 26712566cbdSRudolf Cornelissen /* note: 26812566cbdSRudolf Cornelissen * NACK: occurs on some ASUS V7700 GeForce cards! 26912566cbdSRudolf Cornelissen * (apparantly the video-in chip or another chip resides at 'BT' adresses 27012566cbdSRudolf Cornelissen * there..) */ 27112566cbdSRudolf Cornelissen uint8 stat; 27212566cbdSRudolf Cornelissen uint8 cnt = 0; 27312566cbdSRudolf Cornelissen while ((stat = BT_read_type()) && (cnt < 3)) 27412566cbdSRudolf Cornelissen { 2750ece4905SRudolf Cornelissen /* don't retry on unsupported chiptype */ 2760ece4905SRudolf Cornelissen if (stat == 0x80) 2770ece4905SRudolf Cornelissen { 2780ece4905SRudolf Cornelissen btfound = 0; 2790ece4905SRudolf Cornelissen break; 2800ece4905SRudolf Cornelissen } 28112566cbdSRudolf Cornelissen cnt++; 28212566cbdSRudolf Cornelissen } 2830ece4905SRudolf Cornelissen if (stat & 0x7f) 28412566cbdSRudolf Cornelissen { 2859a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Too much errors occurred, aborting.\n")); 28612566cbdSRudolf Cornelissen btfound = 0; 28712566cbdSRudolf Cornelissen } 28812566cbdSRudolf Cornelissen } 28912566cbdSRudolf Cornelissen 29012566cbdSRudolf Cornelissen if (btfound) 29112566cbdSRudolf Cornelissen LOG(4,("Brooktree: Found TV encoder on bus %d, adress $%02x\n", 29212566cbdSRudolf Cornelissen si->ps.tv_encoder.bus, si->ps.tv_encoder.adress)); 29312566cbdSRudolf Cornelissen else 29412566cbdSRudolf Cornelissen LOG(4,("Brooktree: No TV encoder Found\n")); 29512566cbdSRudolf Cornelissen 29612566cbdSRudolf Cornelissen return btfound; 29712566cbdSRudolf Cornelissen } 29812566cbdSRudolf Cornelissen 29977497c49SRudolf Cornelissen static uint8 BT_init_PAL640() 300fb6cadf1Sshatty { 30177497c49SRudolf Cornelissen uint8 stat; 302fb6cadf1Sshatty 30377497c49SRudolf Cornelissen uint8 buffer[35]; 304fb6cadf1Sshatty 3059a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting PAL 640x480 desktop mode\n")); 3069a7218c5SRudolf Cornelissen 3079a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 30877497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to 30977497c49SRudolf Cornelissen buffer[2] = 0x60; 31077497c49SRudolf Cornelissen buffer[3] = 0x80; 31177497c49SRudolf Cornelissen buffer[4] = 0x8a; 31277497c49SRudolf Cornelissen buffer[5] = 0xa6; 31377497c49SRudolf Cornelissen buffer[6] = 0x68; 31477497c49SRudolf Cornelissen buffer[7] = 0xc1; 31577497c49SRudolf Cornelissen buffer[8] = 0x2e; 31677497c49SRudolf Cornelissen buffer[9] = 0xf2; 31777497c49SRudolf Cornelissen buffer[10] = 0x27; 31877497c49SRudolf Cornelissen buffer[11] = 0x00; 31977497c49SRudolf Cornelissen buffer[12] = 0xb0; 32077497c49SRudolf Cornelissen buffer[13] = 0x0a; 32177497c49SRudolf Cornelissen buffer[14] = 0x0b; 32277497c49SRudolf Cornelissen buffer[15] = 0x71; 32377497c49SRudolf Cornelissen buffer[16] = 0x5a; 32477497c49SRudolf Cornelissen buffer[17] = 0xe0; 32577497c49SRudolf Cornelissen buffer[18] = 0x36; 32677497c49SRudolf Cornelissen buffer[19] = 0x00; 32777497c49SRudolf Cornelissen buffer[20] = 0x50; 32877497c49SRudolf Cornelissen buffer[21] = 0x72; 32977497c49SRudolf Cornelissen buffer[22] = 0x1c; 33077497c49SRudolf Cornelissen buffer[23] = 0x8d; //chip-pin CLKI is pixel clock (only non-default here!) 33177497c49SRudolf Cornelissen buffer[24] = 0x24; 33277497c49SRudolf Cornelissen buffer[25] = 0xf0; 33377497c49SRudolf Cornelissen buffer[26] = 0x58; 33477497c49SRudolf Cornelissen buffer[27] = 0x81; 33577497c49SRudolf Cornelissen buffer[28] = 0x49; 33677497c49SRudolf Cornelissen buffer[29] = 0x8c; 33777497c49SRudolf Cornelissen buffer[30] = 0x0c; 33877497c49SRudolf Cornelissen buffer[31] = 0x8c; 33977497c49SRudolf Cornelissen buffer[32] = 0x79; 34077497c49SRudolf Cornelissen buffer[33] = 0x26; 34177497c49SRudolf Cornelissen buffer[34] = 0x00; 34277497c49SRudolf Cornelissen 34377497c49SRudolf Cornelissen /* reset status */ 34477497c49SRudolf Cornelissen i2c_flag_error (-1); 34577497c49SRudolf Cornelissen 34677497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 34777497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 34877497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 34977497c49SRudolf Cornelissen /* log on errors */ 35077497c49SRudolf Cornelissen stat = i2c_flag_error(0); 35177497c49SRudolf Cornelissen if (stat) 35277497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode PAL640\n")); 35377497c49SRudolf Cornelissen 35477497c49SRudolf Cornelissen return stat; 35577497c49SRudolf Cornelissen }//end BT_init_PAL640. 35677497c49SRudolf Cornelissen 35777497c49SRudolf Cornelissen static uint8 BT_init_PAL800() 358fb6cadf1Sshatty { 35977497c49SRudolf Cornelissen uint8 stat; 360fb6cadf1Sshatty 36177497c49SRudolf Cornelissen uint8 buffer[35]; 362fb6cadf1Sshatty 3639a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting PAL 800x600 desktop mode\n")); 3649a7218c5SRudolf Cornelissen 3659a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 36677497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to 36777497c49SRudolf Cornelissen buffer[2] = 0x00; 36877497c49SRudolf Cornelissen buffer[3] = 0x20; 36977497c49SRudolf Cornelissen buffer[4] = 0xaa; 37077497c49SRudolf Cornelissen buffer[5] = 0xca; 37177497c49SRudolf Cornelissen buffer[6] = 0x9a; 37277497c49SRudolf Cornelissen buffer[7] = 0x0d; 37377497c49SRudolf Cornelissen buffer[8] = 0x29; 37477497c49SRudolf Cornelissen buffer[9] = 0xfc; 37577497c49SRudolf Cornelissen buffer[10] = 0x39; 37677497c49SRudolf Cornelissen buffer[11] = 0x00; 37777497c49SRudolf Cornelissen buffer[12] = 0xc0; 37877497c49SRudolf Cornelissen buffer[13] = 0x8c; 37977497c49SRudolf Cornelissen buffer[14] = 0x03; 38077497c49SRudolf Cornelissen buffer[15] = 0xee; 38177497c49SRudolf Cornelissen buffer[16] = 0x5f; 38277497c49SRudolf Cornelissen buffer[17] = 0x58; 38377497c49SRudolf Cornelissen buffer[18] = 0x3a; 38477497c49SRudolf Cornelissen buffer[19] = 0x66; 38577497c49SRudolf Cornelissen buffer[20] = 0x96; 38677497c49SRudolf Cornelissen buffer[21] = 0x00; 38777497c49SRudolf Cornelissen buffer[22] = 0x00; 38877497c49SRudolf Cornelissen buffer[23] = 0x90; //chip-pin CLKI is pixel clock (only non-default here!) 38977497c49SRudolf Cornelissen buffer[24] = 0x24; 39077497c49SRudolf Cornelissen buffer[25] = 0xf0; 39177497c49SRudolf Cornelissen buffer[26] = 0x57; 39277497c49SRudolf Cornelissen buffer[27] = 0x80; 39377497c49SRudolf Cornelissen buffer[28] = 0x48; 39477497c49SRudolf Cornelissen buffer[29] = 0x8c; 39577497c49SRudolf Cornelissen buffer[30] = 0x18; 39677497c49SRudolf Cornelissen buffer[31] = 0x28; 39777497c49SRudolf Cornelissen buffer[32] = 0x87; 39877497c49SRudolf Cornelissen buffer[33] = 0x1f; 39977497c49SRudolf Cornelissen buffer[34] = 0x00; 40077497c49SRudolf Cornelissen 40177497c49SRudolf Cornelissen /* reset status */ 40277497c49SRudolf Cornelissen i2c_flag_error (-1); 40377497c49SRudolf Cornelissen 40477497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 40577497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 40677497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 40777497c49SRudolf Cornelissen /* log on errors */ 40877497c49SRudolf Cornelissen stat = i2c_flag_error(0); 40977497c49SRudolf Cornelissen if (stat) 41077497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n")); 41177497c49SRudolf Cornelissen 41277497c49SRudolf Cornelissen return stat; 41377497c49SRudolf Cornelissen }//end BT_init_PAL800. 41477497c49SRudolf Cornelissen 41577497c49SRudolf Cornelissen static uint8 BT_init_NTSC640() 416fb6cadf1Sshatty { 41777497c49SRudolf Cornelissen uint8 stat; 418fb6cadf1Sshatty 41977497c49SRudolf Cornelissen uint8 buffer[35]; 42077497c49SRudolf Cornelissen 4219a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting NTSC 640x480 desktop mode\n")); 4229a7218c5SRudolf Cornelissen 4239a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 42477497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to 42577497c49SRudolf Cornelissen buffer[2] = 0x00; 42677497c49SRudolf Cornelissen buffer[3] = 0x80; 42777497c49SRudolf Cornelissen buffer[4] = 0x84; 42877497c49SRudolf Cornelissen buffer[5] = 0x96; 42977497c49SRudolf Cornelissen buffer[6] = 0x60; 43077497c49SRudolf Cornelissen buffer[7] = 0x7d; 43177497c49SRudolf Cornelissen buffer[8] = 0x22; 43277497c49SRudolf Cornelissen buffer[9] = 0xd4; 43377497c49SRudolf Cornelissen buffer[10] = 0x27; 43477497c49SRudolf Cornelissen buffer[11] = 0x00; 43577497c49SRudolf Cornelissen buffer[12] = 0x10; 43677497c49SRudolf Cornelissen buffer[13] = 0x7e; 43777497c49SRudolf Cornelissen buffer[14] = 0x03; 43877497c49SRudolf Cornelissen buffer[15] = 0x58; 43977497c49SRudolf Cornelissen buffer[16] = 0x4b; 44077497c49SRudolf Cornelissen buffer[17] = 0xe0; 44177497c49SRudolf Cornelissen buffer[18] = 0x36; 44277497c49SRudolf Cornelissen buffer[19] = 0x92; 44377497c49SRudolf Cornelissen buffer[20] = 0x54; 44477497c49SRudolf Cornelissen buffer[21] = 0x0e; 44577497c49SRudolf Cornelissen buffer[22] = 0x88; 44677497c49SRudolf Cornelissen buffer[23] = 0x8c; //chip-pin CLKI is pixel clock (only non-default here!) 44777497c49SRudolf Cornelissen buffer[24] = 0x0a; 44877497c49SRudolf Cornelissen buffer[25] = 0xe5; 44977497c49SRudolf Cornelissen buffer[26] = 0x76; 45077497c49SRudolf Cornelissen buffer[27] = 0x79; 45177497c49SRudolf Cornelissen buffer[28] = 0x44; 45277497c49SRudolf Cornelissen buffer[29] = 0x85; 45377497c49SRudolf Cornelissen buffer[30] = 0x00; 45477497c49SRudolf Cornelissen buffer[31] = 0x00; 45577497c49SRudolf Cornelissen buffer[32] = 0x80; 45677497c49SRudolf Cornelissen buffer[33] = 0x20; 45777497c49SRudolf Cornelissen buffer[34] = 0x00; 45877497c49SRudolf Cornelissen 45977497c49SRudolf Cornelissen /* reset status */ 46077497c49SRudolf Cornelissen i2c_flag_error (-1); 46177497c49SRudolf Cornelissen 46277497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 46377497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 46477497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 46577497c49SRudolf Cornelissen /* log on errors */ 46677497c49SRudolf Cornelissen stat = i2c_flag_error(0); 46777497c49SRudolf Cornelissen if (stat) 46877497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640\n")); 46977497c49SRudolf Cornelissen 47077497c49SRudolf Cornelissen return stat; 47177497c49SRudolf Cornelissen }//end BT_init_NTSC640. 47277497c49SRudolf Cornelissen 47377497c49SRudolf Cornelissen static uint8 BT_init_NTSC800() 474fb6cadf1Sshatty { 47577497c49SRudolf Cornelissen uint8 stat; 476fb6cadf1Sshatty 47777497c49SRudolf Cornelissen uint8 buffer[35]; 478fb6cadf1Sshatty 4799a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting NTSC 800x600 desktop mode\n")); 4809a7218c5SRudolf Cornelissen 4819a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 48277497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to 48377497c49SRudolf Cornelissen buffer[2] = 0xa0; 48477497c49SRudolf Cornelissen buffer[3] = 0x20; 48577497c49SRudolf Cornelissen buffer[4] = 0xb6; 48677497c49SRudolf Cornelissen buffer[5] = 0xce; 48777497c49SRudolf Cornelissen buffer[6] = 0x84; 48877497c49SRudolf Cornelissen buffer[7] = 0x55; 48977497c49SRudolf Cornelissen buffer[8] = 0x20; 49077497c49SRudolf Cornelissen buffer[9] = 0xd8; 49177497c49SRudolf Cornelissen buffer[10] = 0x39; 49277497c49SRudolf Cornelissen buffer[11] = 0x00; 49377497c49SRudolf Cornelissen buffer[12] = 0x70; 49477497c49SRudolf Cornelissen buffer[13] = 0x42; 49577497c49SRudolf Cornelissen buffer[14] = 0x03; 49677497c49SRudolf Cornelissen buffer[15] = 0xdf; 49777497c49SRudolf Cornelissen buffer[16] = 0x56; 49877497c49SRudolf Cornelissen buffer[17] = 0x58; 49977497c49SRudolf Cornelissen buffer[18] = 0x3a; 50077497c49SRudolf Cornelissen buffer[19] = 0xcd; 50177497c49SRudolf Cornelissen buffer[20] = 0x9c; 50277497c49SRudolf Cornelissen buffer[21] = 0x14; 50377497c49SRudolf Cornelissen buffer[22] = 0x3b; 50477497c49SRudolf Cornelissen buffer[23] = 0x91; //chip-pin CLKI is pixel clock (only non-default here!) 50577497c49SRudolf Cornelissen buffer[24] = 0x0a; 50677497c49SRudolf Cornelissen buffer[25] = 0xe5; 50777497c49SRudolf Cornelissen buffer[26] = 0x74; 50877497c49SRudolf Cornelissen buffer[27] = 0x77; 50977497c49SRudolf Cornelissen buffer[28] = 0x43; 51077497c49SRudolf Cornelissen buffer[29] = 0x85; 51177497c49SRudolf Cornelissen buffer[30] = 0xba; 51277497c49SRudolf Cornelissen buffer[31] = 0xe8; 51377497c49SRudolf Cornelissen buffer[32] = 0xa2; 51477497c49SRudolf Cornelissen buffer[33] = 0x17; 51577497c49SRudolf Cornelissen buffer[34] = 0x00; 51677497c49SRudolf Cornelissen 51777497c49SRudolf Cornelissen /* reset status */ 51877497c49SRudolf Cornelissen i2c_flag_error (-1); 51977497c49SRudolf Cornelissen 52077497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 52177497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 52277497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 52377497c49SRudolf Cornelissen /* log on errors */ 52477497c49SRudolf Cornelissen stat = i2c_flag_error(0); 52577497c49SRudolf Cornelissen if (stat) 52677497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800\n")); 52777497c49SRudolf Cornelissen 52877497c49SRudolf Cornelissen return stat; 52977497c49SRudolf Cornelissen }//end BT_init_NTSC800. 53077497c49SRudolf Cornelissen 53177497c49SRudolf Cornelissen static uint8 BT_init_PAL720() 532fb6cadf1Sshatty { 53377497c49SRudolf Cornelissen uint8 stat; 53477497c49SRudolf Cornelissen 53577497c49SRudolf Cornelissen uint8 buffer[35]; 53677497c49SRudolf Cornelissen 5379a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting PAL 720x576 overscanning DVD mode\n")); 5389a7218c5SRudolf Cornelissen 5399a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 54077497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to 54177497c49SRudolf Cornelissen buffer[2] = 0xf0; 54277497c49SRudolf Cornelissen buffer[3] = 0xd0; 54377497c49SRudolf Cornelissen buffer[4] = 0x82; 54477497c49SRudolf Cornelissen buffer[5] = 0x9c; 54577497c49SRudolf Cornelissen buffer[6] = 0x5a; 54677497c49SRudolf Cornelissen buffer[7] = 0x31; 54777497c49SRudolf Cornelissen buffer[8] = 0x16; 54877497c49SRudolf Cornelissen buffer[9] = 0x22; 54977497c49SRudolf Cornelissen buffer[10] = 0xa6; 55077497c49SRudolf Cornelissen buffer[11] = 0x00; 55177497c49SRudolf Cornelissen buffer[12] = 0x78; 55277497c49SRudolf Cornelissen buffer[13] = 0x93; 55377497c49SRudolf Cornelissen buffer[14] = 0x03; 55477497c49SRudolf Cornelissen buffer[15] = 0x71; 55577497c49SRudolf Cornelissen buffer[16] = 0x2a; 55677497c49SRudolf Cornelissen buffer[17] = 0x40; 55777497c49SRudolf Cornelissen buffer[18] = 0x0a; 55877497c49SRudolf Cornelissen buffer[19] = 0x00; 55977497c49SRudolf Cornelissen buffer[20] = 0x50; 56077497c49SRudolf Cornelissen buffer[21] = 0x55; 56177497c49SRudolf Cornelissen buffer[22] = 0x55; 56277497c49SRudolf Cornelissen buffer[23] = 0x8c; //chip-pin CLKI is pixel clock (only non-default here!) 56377497c49SRudolf Cornelissen buffer[24] = 0x24; 56477497c49SRudolf Cornelissen buffer[25] = 0xf0; 56577497c49SRudolf Cornelissen buffer[26] = 0x59; 56677497c49SRudolf Cornelissen buffer[27] = 0x82; 56777497c49SRudolf Cornelissen buffer[28] = 0x49; 56877497c49SRudolf Cornelissen buffer[29] = 0x8c; 56977497c49SRudolf Cornelissen buffer[30] = 0x8e; 57077497c49SRudolf Cornelissen buffer[31] = 0xb0; 57177497c49SRudolf Cornelissen buffer[32] = 0xe6; 57277497c49SRudolf Cornelissen buffer[33] = 0x28; 57377497c49SRudolf Cornelissen buffer[34] = 0x00; 57477497c49SRudolf Cornelissen 57577497c49SRudolf Cornelissen /* reset status */ 57677497c49SRudolf Cornelissen i2c_flag_error (-1); 57777497c49SRudolf Cornelissen 57877497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 57977497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 58077497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 58177497c49SRudolf Cornelissen /* log on errors */ 58277497c49SRudolf Cornelissen stat = i2c_flag_error(0); 58377497c49SRudolf Cornelissen if (stat) 58477497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode PAL720\n")); 58577497c49SRudolf Cornelissen 58677497c49SRudolf Cornelissen return stat; 58777497c49SRudolf Cornelissen }//end BT_init_PAL720. 58877497c49SRudolf Cornelissen 58977497c49SRudolf Cornelissen static uint8 BT_init_NTSC720() 590fb6cadf1Sshatty { 59177497c49SRudolf Cornelissen uint8 stat; 592fb6cadf1Sshatty 59377497c49SRudolf Cornelissen uint8 buffer[35]; 59477497c49SRudolf Cornelissen 5959a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting NTSC 720x480 overscanning DVD mode\n")); 5969a7218c5SRudolf Cornelissen 5979a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 59877497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to. 59977497c49SRudolf Cornelissen buffer[2] = 0xf0; //lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1) 60077497c49SRudolf Cornelissen buffer[3] = 0xd0; //lsb h_active: h_active = 720 pixels wide port 60177497c49SRudolf Cornelissen buffer[4] = 0x83; //scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC 60277497c49SRudolf Cornelissen buffer[5] = 0x98; //scope: OK hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC 60377497c49SRudolf Cornelissen buffer[6] = 0x5e; //scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC 60477497c49SRudolf Cornelissen 60577497c49SRudolf Cornelissen //How to find the correct values for h_blank_o and v_blank_o: 60677497c49SRudolf Cornelissen // 1. Calculate h_blank_o according to initial setting guideline mentioned below; 60777497c49SRudolf Cornelissen // 2. Set v_blank_o in the neighbourhood of $18, so that TV picture does not have ghosts on right side in it while 60877497c49SRudolf Cornelissen // horizontal position is about OK; 60977497c49SRudolf Cornelissen // 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch); 61077497c49SRudolf Cornelissen // 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above); 61177497c49SRudolf Cornelissen // 5. If no vertical shivering occurs when image is centered, you're done. Else: 61277497c49SRudolf Cornelissen // 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!: 61377497c49SRudolf Cornelissen // 7. Make sure you update the Chrontel horizontal Phase setting also then! 61477497c49SRudolf Cornelissen 6155cadaa5fSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870)//set CX value 6165cadaa5fSRudolf Cornelissen { 617195828c4SRudolf Cornelissen /* confirmed on NV11 using 4:3 TV and 16:9 TV */ 6185cadaa5fSRudolf Cornelissen buffer[7] = 0x0c; //scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV 6195cadaa5fSRudolf Cornelissen //(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC) 6205cadaa5fSRudolf Cornelissen } 6215cadaa5fSRudolf Cornelissen else //set BT value 6225cadaa5fSRudolf Cornelissen { 6235cadaa5fSRudolf Cornelissen /* confirmed on TNT1 using 4:3 TV and 16:9 TV */ 62477497c49SRudolf Cornelissen buffer[7] = 0x28; //scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV 62577497c49SRudolf Cornelissen //(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC) 6265cadaa5fSRudolf Cornelissen } 62777497c49SRudolf Cornelissen buffer[8] = 0x18; //try-out; scope: checked against other modes, looks OK. v_blank_o: 1e active line ('pixel') 62877497c49SRudolf Cornelissen 62977497c49SRudolf Cornelissen buffer[9] = 0xf2; //v_active_o: = (active output lines + 2) / field (on TV) 63077497c49SRudolf Cornelissen buffer[10] = 0x26; //lsn = msn h_clk_o; 63177497c49SRudolf Cornelissen //b4-5 = msbits h_active; 63277497c49SRudolf Cornelissen //b7 = b8 v_avtive_o. 63377497c49SRudolf Cornelissen buffer[11] = 0x00; //h_fract is always 0. 63477497c49SRudolf Cornelissen buffer[12] = 0x78; //lsb h_clk_i: h_clk_i is horizontal total = 888. 63577497c49SRudolf Cornelissen buffer[13] = 0x90; //try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync! 63677497c49SRudolf Cornelissen buffer[14] = 0x03; //b2-0 = msn h_clk_i; 63777497c49SRudolf Cornelissen //try-out: b3 = msn h_blank_i; 63877497c49SRudolf Cornelissen //b4 = vblankdly is always 0. 63977497c49SRudolf Cornelissen buffer[15] = 0x0d; //lsb v_lines_i: v_lines_i = 525 64077497c49SRudolf Cornelissen buffer[16] = 0x1a; //try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync! 64177497c49SRudolf Cornelissen //Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV. 64277497c49SRudolf Cornelissen buffer[17] = 0xe0; //lsb v_active_i: v_active_i = 480 64377497c49SRudolf Cornelissen buffer[18] = 0x36; //b1-0 = msn v_lines_i; 64477497c49SRudolf Cornelissen //b3-2 = msn v_active_i; 64577497c49SRudolf Cornelissen //b5-4 = ylpf = 3; 64677497c49SRudolf Cornelissen //b7-6 = clpf = 0. 64777497c49SRudolf Cornelissen buffer[19] = 0x00; //lsb v_scale: v_scale = off = $1000 64877497c49SRudolf Cornelissen buffer[20] = 0x50; //b5-0 = msn v_scale; 64977497c49SRudolf Cornelissen //scope: tuned. b7-6 = msn h_blank_o. 65077497c49SRudolf Cornelissen //(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz) 65177497c49SRudolf Cornelissen buffer[21] = 0x98; //lsb PLL fract: PLL fract = 0x6e98 65277497c49SRudolf Cornelissen buffer[22] = 0x6e; //msb PLL fract 65377497c49SRudolf Cornelissen buffer[23] = 0x8c; //b5-0 = PLL int: PLL int = 0x0c; 65477497c49SRudolf Cornelissen //b6 = by_pll: by_pll = 0; 65577497c49SRudolf Cornelissen //b7 = EN_XCLK: chip-pin CLKI is pixel clock. 65677497c49SRudolf Cornelissen buffer[24] = 0x0a; //b0 = ni_out is always 0; 65777497c49SRudolf Cornelissen //b1 = setup = 1 for NTSC; 65877497c49SRudolf Cornelissen //b2 = 625line = 0 for NTSC; 65977497c49SRudolf Cornelissen //b3 = vsync_dur = 1 for NTSC; 66077497c49SRudolf Cornelissen //b4 = dic_screset is always 0; 66177497c49SRudolf Cornelissen //b5 = pal_md = 0 for NTSC; 66277497c49SRudolf Cornelissen //b6 = eclip is always 0; 66377497c49SRudolf Cornelissen //b7 = reserved (en_scart) is always 0. 66477497c49SRudolf Cornelissen buffer[25] = 0xe5; //sync_amp $e5 for NTSC 66577497c49SRudolf Cornelissen buffer[26] = 0x75; //bst_amp $74-$76 for NTSC 66677497c49SRudolf Cornelissen buffer[27] = 0x78; //mcr: r-y $77-$79 for NTSC 66777497c49SRudolf Cornelissen buffer[28] = 0x44; //mcb: b-y $43-$44 for NTSC 66877497c49SRudolf Cornelissen buffer[29] = 0x85; //my: y $85 for NTSC 66977497c49SRudolf Cornelissen buffer[30] = 0x3c; //lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC 67077497c49SRudolf Cornelissen buffer[31] = 0x91; //msc = $20c2913c 67177497c49SRudolf Cornelissen buffer[32] = 0xc2; 67277497c49SRudolf Cornelissen buffer[33] = 0x20; //msb msc. 67377497c49SRudolf Cornelissen buffer[34] = 0x00; //phase_off always $00 67477497c49SRudolf Cornelissen 67577497c49SRudolf Cornelissen /* reset status */ 67677497c49SRudolf Cornelissen i2c_flag_error (-1); 67777497c49SRudolf Cornelissen 67877497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 67977497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 68077497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 68177497c49SRudolf Cornelissen /* log on errors */ 68277497c49SRudolf Cornelissen stat = i2c_flag_error(0); 68377497c49SRudolf Cornelissen if (stat) 68477497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC720\n")); 68577497c49SRudolf Cornelissen 68677497c49SRudolf Cornelissen return stat; 68777497c49SRudolf Cornelissen }//end BT_init_NTSC720. 68877497c49SRudolf Cornelissen 68977497c49SRudolf Cornelissen static uint8 BT_init_PAL800_OS() 690fb6cadf1Sshatty { 69177497c49SRudolf Cornelissen uint8 stat; 692fb6cadf1Sshatty 69377497c49SRudolf Cornelissen uint8 buffer[35]; 69477497c49SRudolf Cornelissen 6959a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting PAL 800x600 overscanning VCD mode\n")); 6969a7218c5SRudolf Cornelissen 6979a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 69877497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to. 69977497c49SRudolf Cornelissen buffer[2] = 0x60; //lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1) 70077497c49SRudolf Cornelissen buffer[3] = 0x20; //lsb h_active: h_active = 800 pixels wide port 70177497c49SRudolf Cornelissen buffer[4] = 0x8b; //scope: OK hsync_width: (hsync_width / h_clk_o) * 64.0uS = 4.70uS for PAL 70277497c49SRudolf Cornelissen buffer[5] = 0xa5; //scope: OK hburst_begin: (hburst_begin / h_clk_o) * 64.0uS = 5.6uS for PAL 70377497c49SRudolf Cornelissen buffer[6] = 0x6b; //scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 64.0uS = 7.97uS for PAL 70477497c49SRudolf Cornelissen 70577497c49SRudolf Cornelissen //How to find the correct values for h_blank_o and v_blank_o: 70677497c49SRudolf Cornelissen // 1. Calculate h_blank_o according to initial setting guideline mentioned below; 70777497c49SRudolf 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 70877497c49SRudolf Cornelissen // horizontal position is about OK; 70977497c49SRudolf Cornelissen // 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch); 71077497c49SRudolf Cornelissen // 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above); 71177497c49SRudolf Cornelissen // 5. If no vertical shivering occurs when image is centered, you're done. Else: 71277497c49SRudolf Cornelissen // 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!: 71377497c49SRudolf Cornelissen // 7. Make sure you update the Chrontel horizontal Phase setting also then! 71477497c49SRudolf Cornelissen 71577497c49SRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870)//set CX value 716fb6cadf1Sshatty { 717195828c4SRudolf Cornelissen /* confirmed on NV11 using 4:3 TV and 16:9 TV */ 7185cadaa5fSRudolf Cornelissen buffer[7] = 0xf0; 71977497c49SRudolf Cornelissen buffer[8] = 0x17; 720fb6cadf1Sshatty } 7215cadaa5fSRudolf Cornelissen else //set BT value 7225cadaa5fSRudolf Cornelissen { 7234e918a7cSRudolf Cornelissen /* confirmed on TNT1 using 4:3 TV and 16:9 TV */ 7246245f19cSRudolf Cornelissen buffer[7] = 0xd0;//scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV 72577497c49SRudolf Cornelissen //(guideline for initial setting: (h_blank_o / h_clk_0) * 64.0uS = 10.0uS for PAL) 72677497c49SRudolf Cornelissen buffer[8] = 0x18;//try-out; scope: checked against other modes, looks OK. v_blank_o: 1e active line ('pixel') 72777497c49SRudolf Cornelissen } 72877497c49SRudolf Cornelissen 72977497c49SRudolf Cornelissen buffer[9] = 0x2e; //v_active_o: = (active output lines + 2) / field (on TV) 73077497c49SRudolf Cornelissen buffer[10] = 0xb7; //lsn = msn h_clk_o; 73177497c49SRudolf Cornelissen //b4-5 = msbits h_active; 73277497c49SRudolf Cornelissen //b7 = b8 v_avtive_o. 73377497c49SRudolf Cornelissen buffer[11] = 0x00; //h_fract is always 0. 73477497c49SRudolf Cornelissen buffer[12] = 0xb0; //lsb h_clk_i: h_clk_i is horizontal total = 944. 73577497c49SRudolf Cornelissen 73677497c49SRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870)//set CX value 73777497c49SRudolf Cornelissen buffer[13] = 0x20; 73877497c49SRudolf Cornelissen else //set BT value 73977497c49SRudolf Cornelissen buffer[13] = 0x14;//try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync! 74077497c49SRudolf Cornelissen 74177497c49SRudolf Cornelissen buffer[14] = 0x03; //b2-0 = msn h_clk_i; 74277497c49SRudolf Cornelissen //try-out: b3 = msn h_blank_i; 74377497c49SRudolf Cornelissen //b4 = vblankdly is always 0. 74477497c49SRudolf Cornelissen buffer[15] = 0x71; //lsb v_lines_i: v_lines_i = 625 74577497c49SRudolf Cornelissen 74677497c49SRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870)//set CX value 74777497c49SRudolf Cornelissen buffer[16] = 0x08; 74877497c49SRudolf Cornelissen else //set BT value 74977497c49SRudolf Cornelissen buffer[16] = 0x2a;//try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync! 75077497c49SRudolf Cornelissen //Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV. 75177497c49SRudolf Cornelissen 75277497c49SRudolf Cornelissen buffer[17] = 0x58; //lsb v_active_i: v_active_i = 600 75377497c49SRudolf Cornelissen buffer[18] = 0x3a; //b1-0 = msn v_lines_i; 75477497c49SRudolf Cornelissen //b3-2 = msn v_active_i; 75577497c49SRudolf Cornelissen //b5-4 = ylpf = 3; 75677497c49SRudolf Cornelissen //b7-6 = clpf = 0. 75777497c49SRudolf Cornelissen buffer[19] = 0x00; //lsb v_scale: v_scale = off = $1000 75877497c49SRudolf Cornelissen buffer[20] = 0x10; //b5-0 = msn v_scale; 75977497c49SRudolf Cornelissen //scope: tuned. b7-6 = msn h_blank_o. 76077497c49SRudolf Cornelissen //(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 50Hz) 76177497c49SRudolf Cornelissen buffer[21] = 0x72; //lsb PLL fract: PLL fract = 0x1c72 76277497c49SRudolf Cornelissen buffer[22] = 0x1c; //msb PLL fract 76377497c49SRudolf Cornelissen buffer[23] = 0x8d; //b5-0 = PLL int: PLL int = 0x0d; 76477497c49SRudolf Cornelissen //b6 = by_pll: by_pll = 0; 76577497c49SRudolf Cornelissen //b7 = EN_XCLK: chip-pin CLKI is pixel clock. 76677497c49SRudolf Cornelissen buffer[24] = 0x24; //b0 = ni_out is always 0; 76777497c49SRudolf Cornelissen //b1 = setup = 0 for PAL; 76877497c49SRudolf Cornelissen //b2 = 625line = 1 for PAL; 76977497c49SRudolf Cornelissen //b3 = vsync_dur = 0 for PAL; 77077497c49SRudolf Cornelissen //b4 = dic_screset is always 0; 77177497c49SRudolf Cornelissen //b5 = pal_md = 1 for PAL; 77277497c49SRudolf Cornelissen //b6 = eclip is always 0; 77377497c49SRudolf Cornelissen //b7 = reserved (en_scart) is always 0. 77477497c49SRudolf Cornelissen buffer[25] = 0xf0; //sync_amp $f0 for PAL 77577497c49SRudolf Cornelissen buffer[26] = 0x57; //bst_amp $57-$58 for PAL 77677497c49SRudolf Cornelissen buffer[27] = 0x80; //mcr: r-y $80-$81 for PAL 77777497c49SRudolf Cornelissen buffer[28] = 0x48; //mcb: b-y $48-$49 for PAL 77877497c49SRudolf Cornelissen buffer[29] = 0x8c; //my: y $8c for PAL 77977497c49SRudolf Cornelissen buffer[30] = 0x31; //lsb msc: msc b31-0: PAL formula: ((4433619 / pixelclk) * 2^32) = MSC 78077497c49SRudolf Cornelissen buffer[31] = 0x8c; //msc = $26798c31 78177497c49SRudolf Cornelissen buffer[32] = 0x79; 78277497c49SRudolf Cornelissen buffer[33] = 0x26; //msb msc. 78377497c49SRudolf Cornelissen buffer[34] = 0x00; //phase_off always $00 78477497c49SRudolf Cornelissen 78577497c49SRudolf Cornelissen /* reset status */ 78677497c49SRudolf Cornelissen i2c_flag_error (-1); 78777497c49SRudolf Cornelissen 78877497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 78977497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 79077497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 79177497c49SRudolf Cornelissen /* log on errors */ 79277497c49SRudolf Cornelissen stat = i2c_flag_error(0); 79377497c49SRudolf Cornelissen if (stat) 79477497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode PAL800 OS\n")); 79577497c49SRudolf Cornelissen 79677497c49SRudolf Cornelissen return stat; 79777497c49SRudolf Cornelissen }//end BT_init_PAL800_OS. 79877497c49SRudolf Cornelissen 79977497c49SRudolf Cornelissen static uint8 BT_init_NTSC640_OS() 800fb6cadf1Sshatty { 80177497c49SRudolf Cornelissen uint8 stat; 802fb6cadf1Sshatty 80377497c49SRudolf Cornelissen uint8 buffer[35]; 804fb6cadf1Sshatty 8059a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Setting NTSC 640x480 overscanning VCD mode\n")); 8069a7218c5SRudolf Cornelissen 8079a7218c5SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; //issue I2C write command 80877497c49SRudolf Cornelissen buffer[1] = 0x76; //select first bt register to write to. 80977497c49SRudolf Cornelissen buffer[2] = 0x20; //lsb h_clk_o: overscan comp = 0, so h_clk_o = 2 * h_clk_i (VSR=2 = scaling=1) 81077497c49SRudolf Cornelissen buffer[3] = 0x80; //lsb h_active: h_active = 640 pixels wide port 81177497c49SRudolf Cornelissen buffer[4] = 0x74; //scope: OK hsync_width: (hsync_width / h_clk_o) * 63.55556uS = 4.70uS for NTSC 81277497c49SRudolf Cornelissen buffer[5] = 0x83; //scope: OK hburst_begin: (hburst_begin / h_clk_o) * 63.55556uS = 5.3uS for NTSC 81377497c49SRudolf Cornelissen buffer[6] = 0x44; //scope: OK hburst_end: ((hburst_end + 128) / h_clk_o) * 63.55556uS = 7.94uS for NTSC 814fb6cadf1Sshatty 81577497c49SRudolf Cornelissen //How to find the correct values for h_blank_o and v_blank_o: 81677497c49SRudolf Cornelissen // 1. Calculate h_blank_o according to initial setting guideline mentioned below; 81777497c49SRudolf 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 81877497c49SRudolf Cornelissen // horizontal position is about OK; 81977497c49SRudolf Cornelissen // 3. Then tune h_blank_o for centered output on scope (look at front porch and back porch); 82077497c49SRudolf Cornelissen // 4. Now shift the TV output using Hsync_offset for centered output while looking at TV (in method 'SetBT_Hphase' above); 82177497c49SRudolf Cornelissen // 5. If no vertical shivering occurs when image is centered, you're done. Else: 82277497c49SRudolf Cornelissen // 6. Modify the RIVA (BeScreen) h_sync_start setting somewhat to get stable centered picture possible on TV AND!: 82377497c49SRudolf Cornelissen // 7. Make sure you update the Chrontel horizontal Phase setting also then! 824fb6cadf1Sshatty 82577497c49SRudolf Cornelissen buffer[7] = 0xf7; //scope: tuned. lsb h_blank_o: h_blank_o = horizontal viewport location on TV: 82677497c49SRudolf Cornelissen //(guideline for initial setting: (h_blank_o / h_clk_0) * 63.55556uS = 9.5uS for NTSC) 827fb6cadf1Sshatty 82877497c49SRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870)//set CX value 82977497c49SRudolf Cornelissen buffer[8] = 0x1d; 83077497c49SRudolf Cornelissen else //set BT value 83177497c49SRudolf Cornelissen buffer[8] = 0x1c;//try-out; scope: checked against other modes, looks OK. v_blank_o: 1e active line ('pixel') 832fb6cadf1Sshatty 83377497c49SRudolf Cornelissen buffer[9] = 0xf2; //v_active_o: = (active output lines + 2) / field (on TV) 83477497c49SRudolf Cornelissen buffer[10] = 0x26; //lsn = msn h_clk_o; 83577497c49SRudolf Cornelissen //b4-5 = msbits h_active; 83677497c49SRudolf Cornelissen //b7 = b8 v_avtive_o. 83777497c49SRudolf Cornelissen buffer[11] = 0x00; //h_fract is always 0. 83877497c49SRudolf Cornelissen buffer[12] = 0x10; //lsb h_clk_i: h_clk_i is horizontal total = 784. 83977497c49SRudolf Cornelissen buffer[13] = 0x14; //try-out; lsb h_blank_i: #clks between start sync and new line 1st pixel; copy to VGA delta-sync! 84077497c49SRudolf Cornelissen buffer[14] = 0x03; //b2-0 = msn h_clk_i; 84177497c49SRudolf Cornelissen //try-out: b3 = msn h_blank_i; 84277497c49SRudolf Cornelissen //b4 = vblankdly is always 0. 84377497c49SRudolf Cornelissen buffer[15] = 0x0d; //lsb v_lines_i: v_lines_i = 525 84477497c49SRudolf Cornelissen buffer[16] = 0x18; //try-out; v_blank_i: #input lines between start sync and new line (pixel); copy to VGA delta-sync! 84577497c49SRudolf Cornelissen //Make sure though that this value for the BT is *even*, or image will shiver a *lot* horizontally on TV. 84677497c49SRudolf Cornelissen buffer[17] = 0xe0; //lsb v_active_i: v_active_i = 480 84777497c49SRudolf Cornelissen buffer[18] = 0x36; //b1-0 = msn v_lines_i; 84877497c49SRudolf Cornelissen //b3-2 = msn v_active_i; 84977497c49SRudolf Cornelissen //b5-4 = ylpf = 3; 85077497c49SRudolf Cornelissen //b7-6 = clpf = 0. 85177497c49SRudolf Cornelissen buffer[19] = 0x00; //lsb v_scale: v_scale = off = $1000 85277497c49SRudolf Cornelissen buffer[20] = 0x10; //b5-0 = msn v_scale; 85377497c49SRudolf Cornelissen //scope: tuned. b7-6 = msn h_blank_o. 85477497c49SRudolf Cornelissen //(((PLL_INT + (PLL_FRACT/65536)) / 6) * 13500000) = PIXEL_CLK = (hor.tot. * v_lines_i * 60Hz) 85577497c49SRudolf Cornelissen buffer[21] = 0xdb; //lsb PLL fract: PLL fract = 0xf9db 85677497c49SRudolf Cornelissen buffer[22] = 0xf9; //msb PLL fract 85777497c49SRudolf Cornelissen buffer[23] = 0x8a; //b5-0 = PLL int: PLL int = 0x0a; 85877497c49SRudolf Cornelissen //b6 = by_pll: by_pll = 0; 85977497c49SRudolf Cornelissen //b7 = EN_XCLK: chip-pin CLKI is pixel clock. 86077497c49SRudolf Cornelissen buffer[24] = 0x0a; //b0 = ni_out is always 0; 86177497c49SRudolf Cornelissen //b1 = setup = 1 for NTSC; 86277497c49SRudolf Cornelissen //b2 = 625line = 0 for NTSC; 86377497c49SRudolf Cornelissen //b3 = vsync_dur = 1 for NTSC; 86477497c49SRudolf Cornelissen //b4 = dic_screset is always 0; 86577497c49SRudolf Cornelissen //b5 = pal_md = 0 for NTSC; 86677497c49SRudolf Cornelissen //b6 = eclip is always 0; 86777497c49SRudolf Cornelissen //b7 = reserved (en_scart) is always 0. 86877497c49SRudolf Cornelissen buffer[25] = 0xe5; //sync_amp $e5 for NTSC 86977497c49SRudolf Cornelissen buffer[26] = 0x75; //bst_amp $74-$76 for NTSC 87077497c49SRudolf Cornelissen buffer[27] = 0x78; //mcr: r-y $77-$79 for NTSC 87177497c49SRudolf Cornelissen buffer[28] = 0x44; //mcb: b-y $43-$44 for NTSC 87277497c49SRudolf Cornelissen buffer[29] = 0x85; //my: y $85 for NTSC 87377497c49SRudolf Cornelissen buffer[30] = 0x37; //lsb msc: msc b31-0: NTSC formula: ((3579545 / pixelclk) * 2^32) = MSC 87477497c49SRudolf Cornelissen buffer[31] = 0x12; //msc = $251b1237 87577497c49SRudolf Cornelissen buffer[32] = 0x1b; 87677497c49SRudolf Cornelissen buffer[33] = 0x25; //msb msc. 87777497c49SRudolf Cornelissen buffer[34] = 0x00; //phase_off always $00 878fb6cadf1Sshatty 87977497c49SRudolf Cornelissen /* reset status */ 88077497c49SRudolf Cornelissen i2c_flag_error (-1); 881fb6cadf1Sshatty 88277497c49SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 88377497c49SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 88477497c49SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 88577497c49SRudolf Cornelissen /* log on errors */ 88677497c49SRudolf Cornelissen stat = i2c_flag_error(0); 88777497c49SRudolf Cornelissen if (stat) 88877497c49SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting mode NTSC640 OS\n")); 889fb6cadf1Sshatty 89077497c49SRudolf Cornelissen return stat; 89177497c49SRudolf Cornelissen }//end BT_init_NTSC640_OS. 892fb6cadf1Sshatty 89321f6ecabSRudolf Cornelissen static uint8 BT_testsignal(void) 89421f6ecabSRudolf Cornelissen { 89521f6ecabSRudolf Cornelissen uint8 stat; 89621f6ecabSRudolf Cornelissen 89721f6ecabSRudolf Cornelissen uint8 buffer[3]; 89821f6ecabSRudolf Cornelissen 8999a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Enabling testsignal\n")); 9009a7218c5SRudolf Cornelissen 90121f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 90221f6ecabSRudolf Cornelissen /* select bt register for enabling colorbars and outputs */ 90321f6ecabSRudolf Cornelissen buffer[1] = 0xc4; 90421f6ecabSRudolf Cornelissen /* issue the actual command */ 90521f6ecabSRudolf Cornelissen buffer[2] = 0x05; 90621f6ecabSRudolf Cornelissen 90721f6ecabSRudolf Cornelissen /* reset status */ 90821f6ecabSRudolf Cornelissen i2c_flag_error (-1); 90921f6ecabSRudolf Cornelissen 91021f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 91121f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 91221f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 91321f6ecabSRudolf Cornelissen /* log on errors */ 91421f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 91521f6ecabSRudolf Cornelissen if (stat) 91621f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n")); 91721f6ecabSRudolf Cornelissen 91821f6ecabSRudolf Cornelissen return stat; 91921f6ecabSRudolf Cornelissen }//end BT_testsignal. 92021f6ecabSRudolf Cornelissen 92121f6ecabSRudolf Cornelissen static uint8 BT_setup_output(uint8 monstat, uint8 output, uint8 ffilter) 92221f6ecabSRudolf Cornelissen { 92321f6ecabSRudolf Cornelissen uint8 stat; 92421f6ecabSRudolf Cornelissen 92521f6ecabSRudolf Cornelissen uint8 buffer[7]; 92621f6ecabSRudolf Cornelissen 92721f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 92821f6ecabSRudolf Cornelissen /* select first TV config register to write */ 92921f6ecabSRudolf Cornelissen buffer[1] = 0xc6; 93021f6ecabSRudolf Cornelissen /* input is 24bit mpx'd RGB, BLANK = out, sync = act. hi */ 93121f6ecabSRudolf Cornelissen buffer[2] = 0x98; 93221f6ecabSRudolf Cornelissen /* disable all filters, exept flicker filter */ 93321f6ecabSRudolf Cornelissen buffer[3] = 0x98; 93421f6ecabSRudolf Cornelissen if (!ffilter) 93521f6ecabSRudolf Cornelissen { 93621f6ecabSRudolf Cornelissen /* disable flicker filter */ 93721f6ecabSRudolf Cornelissen buffer[3] = 0xc0; 9389a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Disabling flickerfilter\n")); 93921f6ecabSRudolf Cornelissen } 9409a7218c5SRudolf Cornelissen else 9419a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Enabling flickerfilter\n")); 9429a7218c5SRudolf Cornelissen 94321f6ecabSRudolf Cornelissen /* (disable filters) */ 94421f6ecabSRudolf Cornelissen buffer[4] = 0xc0; 94521f6ecabSRudolf Cornelissen /* (disable filters) */ 94621f6ecabSRudolf Cornelissen buffer[5] = 0xc0; 94721f6ecabSRudolf Cornelissen switch (output) 94821f6ecabSRudolf Cornelissen /* Description of ELSA Erazor III hardware layout: 94921f6ecabSRudolf Cornelissen * (This is the default (recommended) layout by NVIDIA) 95021f6ecabSRudolf Cornelissen * DAC A = CVBS 95121f6ecabSRudolf Cornelissen * DAC B = C (chrominance) 95221f6ecabSRudolf Cornelissen * DAC C = Y (luminance) */ 95321f6ecabSRudolf Cornelissen 95421f6ecabSRudolf Cornelissen /* Description of Diamond VIPER550: 95521f6ecabSRudolf Cornelissen * DAC A = Not connected 95621f6ecabSRudolf Cornelissen * DAC B = C (chrominance) 95721f6ecabSRudolf Cornelissen * DAC C = Y (luminance) 95821f6ecabSRudolf Cornelissen * To be able to connect to CVBS TV's a special cable is supplied: 95921f6ecabSRudolf Cornelissen * This cable connects the Y (DAC C) output to the TV CVBS input. */ 96021f6ecabSRudolf Cornelissen { 9619a7218c5SRudolf Cornelissen case 1: 9629a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n")); 9639a7218c5SRudolf Cornelissen buffer[6] = 0x18; // Y/C and CVBS out if all ports implemented 96421f6ecabSRudolf Cornelissen // in hardware, else only Y/C or CVBS out. 96521f6ecabSRudolf Cornelissen break; 9669a7218c5SRudolf Cornelissen case 2: 9679a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Outputting CVBS on all outputs\n")); 9689a7218c5SRudolf Cornelissen buffer[6] = 0x00; // put CVBS on all outputs. Used for cards 96921f6ecabSRudolf Cornelissen break; // with only Y/C out and 'translation cable'. 9709a7218c5SRudolf Cornelissen default: 971b0fce481SRudolf Cornelissen LOG(4,("Brooktree: Outputting signals according to autodetect status:\n")); 9729a7218c5SRudolf Cornelissen switch (monstat) // only 'autodetect' remains... 97321f6ecabSRudolf Cornelissen { 9749a7218c5SRudolf Cornelissen case 1: 975b0fce481SRudolf Cornelissen LOG(4,("Brooktree: Only Y connected, outputting CVBS on all outputs\n")); 9769a7218c5SRudolf Cornelissen buffer[6] = 0x00; //only Y connected: must be CVBS! 97721f6ecabSRudolf Cornelissen break; 9789a7218c5SRudolf Cornelissen case 2: 979b0fce481SRudolf Cornelissen LOG(4,("Brooktree: Only C connected, outputting CVBS on all outputs\n")); 9809a7218c5SRudolf Cornelissen buffer[6] = 0x00; //only C connected: must be CVBS! 98121f6ecabSRudolf Cornelissen break; //(though cable is wired wrong...) 9829a7218c5SRudolf Cornelissen case 5: 983b0fce481SRudolf Cornelissen LOG(4,("Brooktree: CVBS and only Y connected, outputting CVBS on all outputs\n")); 9849a7218c5SRudolf Cornelissen buffer[6] = 0x00; //CVBS and only Y connected: 2x CVBS! 98521f6ecabSRudolf Cornelissen break; //(officially not supported...) 9869a7218c5SRudolf Cornelissen case 6: 987b0fce481SRudolf Cornelissen LOG(4,("Brooktree: CVBS and only C connected, outputting CVBS on all outputs\n")); 9889a7218c5SRudolf Cornelissen buffer[6] = 0x00; //CVBS and only C connected: 2x CVBS! 98921f6ecabSRudolf Cornelissen break; //(officially not supported...) 9909a7218c5SRudolf Cornelissen default: 991b0fce481SRudolf Cornelissen LOG(4,("Brooktree: Outputting both Y/C and CVBS where supported by hardware\n")); 9929a7218c5SRudolf Cornelissen buffer[6] = 0x18; //nothing, or 99321f6ecabSRudolf Cornelissen //Y/C only, or 99421f6ecabSRudolf Cornelissen //CVBS only (but on CVBS output), or 99521f6ecabSRudolf Cornelissen //Y/C and CVBS connected: 99621f6ecabSRudolf Cornelissen //So activate recommended signals. 99721f6ecabSRudolf Cornelissen } 99821f6ecabSRudolf Cornelissen } 99921f6ecabSRudolf Cornelissen 100021f6ecabSRudolf Cornelissen /* reset status */ 100121f6ecabSRudolf Cornelissen i2c_flag_error (-1); 100221f6ecabSRudolf Cornelissen 100321f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 100421f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 100521f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 100621f6ecabSRudolf Cornelissen /* log on errors */ 100721f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 100821f6ecabSRudolf Cornelissen if (stat) 100921f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting up flickerfilter and outputs\n")); 101021f6ecabSRudolf Cornelissen 101121f6ecabSRudolf Cornelissen return stat; 101221f6ecabSRudolf Cornelissen }//end BT_setup_output. 101321f6ecabSRudolf Cornelissen 101421f6ecabSRudolf Cornelissen static uint8 BT_setup_hphase(uint8 mode) 101521f6ecabSRudolf Cornelissen { 101621f6ecabSRudolf Cornelissen uint8 stat, hoffset; 101721f6ecabSRudolf Cornelissen 101821f6ecabSRudolf Cornelissen uint8 buffer[7]; 101921f6ecabSRudolf Cornelissen 10209a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Tuning horizontal phase\n")); 10219a7218c5SRudolf Cornelissen 102221f6ecabSRudolf Cornelissen /* CX needs timing reset (advised on BT also), first 1mS delay needed! */ 102321f6ecabSRudolf Cornelissen snooze(1000); 102421f6ecabSRudolf Cornelissen 102521f6ecabSRudolf Cornelissen /* values below are all tested on TNT1, TNT2 and GeForce2MX */ 102621f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 102721f6ecabSRudolf Cornelissen /* select first TV output timing register to write */ 102821f6ecabSRudolf Cornelissen buffer[1] = 0x6c; 102921f6ecabSRudolf Cornelissen /* turn on active video & generate timing reset on CX chips! */ 103021f6ecabSRudolf Cornelissen buffer[2] = 0x86; 103121f6ecabSRudolf Cornelissen /* (set fail save values...) */ 103221f6ecabSRudolf Cornelissen buffer[3] = 0x00; //set default horizontal sync offset 103321f6ecabSRudolf Cornelissen buffer[4] = 0x02; //set default horizontal sync width 103421f6ecabSRudolf Cornelissen buffer[5] = 0x00; //set default vertical sync offset 103521f6ecabSRudolf Cornelissen 103621f6ecabSRudolf Cornelissen /* do specific timing setup for all chips and modes: */ 10374594e58aSRudolf Cornelissen switch (si->ps.card_type) 1038b0fce481SRudolf Cornelissen { 10394594e58aSRudolf Cornelissen case NV05: 10404594e58aSRudolf Cornelissen case NV05M64: 10414594e58aSRudolf Cornelissen case NV15: 10424594e58aSRudolf Cornelissen /* confirmed TNT2, TNT2M64, GeForce2Ti. 1043b0fce481SRudolf Cornelissen * (8 pixels delayed hpos, so picture more to the right) */ 1044b0fce481SRudolf Cornelissen hoffset = 8; 10454594e58aSRudolf Cornelissen break; 10464594e58aSRudolf Cornelissen default: 10474594e58aSRudolf Cornelissen /* confirmed TNT1, GeForce256, GeForce2MX. 1048b0fce481SRudolf Cornelissen * (std hpos) 1049b0fce481SRudolf Cornelissen * NOTE: It might be that GeForce needs TNT2 offset: 1050b0fce481SRudolf Cornelissen * for now CX chips get seperate extra offset, until sure. 1051b0fce481SRudolf Cornelissen * (CX is only found AFAIK on GeForce cards, no BT tested 1052b0fce481SRudolf Cornelissen * on GeForce yet. CH was tested on GeForce and seemed to 1053b0fce481SRudolf Cornelissen * indicate TNT1 offset was needed.) */ 1054b0fce481SRudolf Cornelissen hoffset = 0; 10554594e58aSRudolf Cornelissen break; 1056b0fce481SRudolf Cornelissen } 105721f6ecabSRudolf Cornelissen 105821f6ecabSRudolf Cornelissen switch (mode) 105921f6ecabSRudolf Cornelissen { 106021f6ecabSRudolf Cornelissen case NTSC640_TST: 106121f6ecabSRudolf Cornelissen case NTSC640: 106221f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more... 10634e918a7cSRudolf Cornelissen /* confirmed on TNT1 with BT869 using 4:3 TV and 16:9 TV */ 1064f2069d6cSRudolf Cornelissen buffer[3] = (0x1e + hoffset); //set horizontal sync offset 106521f6ecabSRudolf Cornelissen break; 106621f6ecabSRudolf Cornelissen case NTSC800: 106721f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more... 106821f6ecabSRudolf Cornelissen buffer[3] = (0xe1 + hoffset); //set horizontal sync offset 106921f6ecabSRudolf Cornelissen buffer[4] = 0xc2; 107021f6ecabSRudolf Cornelissen //Vsync offset reg. does not exist on CX: mode is checked and OK. 107121f6ecabSRudolf Cornelissen buffer[5] = 0x40; //set VSync offset (on BT's only) 107221f6ecabSRudolf Cornelissen break; 107321f6ecabSRudolf Cornelissen case PAL640: 107421f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more... 107521f6ecabSRudolf Cornelissen buffer[3] = (0xa8 + hoffset); 107621f6ecabSRudolf Cornelissen break; 107721f6ecabSRudolf Cornelissen case PAL800_TST: 107821f6ecabSRudolf Cornelissen case PAL800: 107921f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870) hoffset +=8; //if CX shift picture right some more... 108021f6ecabSRudolf Cornelissen buffer[3] = (0x2c + hoffset); 108121f6ecabSRudolf Cornelissen break; 108221f6ecabSRudolf Cornelissen case NTSC720: 108321f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870) 108421f6ecabSRudolf Cornelissen buffer[3] = (0xb2 + hoffset); //set horizontal sync offset CX 108521f6ecabSRudolf Cornelissen else 108621f6ecabSRudolf Cornelissen buffer[3] = (0xd0 + hoffset); //set horizontal sync offset BT 108721f6ecabSRudolf Cornelissen buffer[4] = 0xff; //hsync width = max: 108821f6ecabSRudolf Cornelissen break; //to prevent vertical image 'shivering'. 108921f6ecabSRudolf Cornelissen case PAL720: 109021f6ecabSRudolf Cornelissen buffer[3] = (0xd4 + hoffset); 109121f6ecabSRudolf Cornelissen buffer[4] = 0xff; 109221f6ecabSRudolf Cornelissen break; 109321f6ecabSRudolf Cornelissen case NTSC640_OS: 109421f6ecabSRudolf Cornelissen buffer[3] = (0xc8 + hoffset); 109521f6ecabSRudolf Cornelissen buffer[4] = 0xff; 109621f6ecabSRudolf Cornelissen break; 109721f6ecabSRudolf Cornelissen case PAL800_OS: 109821f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type >= CX25870) 109921f6ecabSRudolf Cornelissen buffer[3] = (0x78 + hoffset); //set horizontal sync offset CX 110021f6ecabSRudolf Cornelissen else 110121f6ecabSRudolf Cornelissen buffer[3] = (0xc4 + hoffset); //set horizontal sync offset BT 110221f6ecabSRudolf Cornelissen buffer[4] = 0xff; 110321f6ecabSRudolf Cornelissen break; 110421f6ecabSRudolf Cornelissen default: //nothing to be done here... 110521f6ecabSRudolf Cornelissen break; 110621f6ecabSRudolf Cornelissen } 110721f6ecabSRudolf Cornelissen 110821f6ecabSRudolf Cornelissen buffer[6] = 0x01; //set default vertical sync width 110921f6ecabSRudolf Cornelissen 111021f6ecabSRudolf Cornelissen /* reset status */ 111121f6ecabSRudolf Cornelissen i2c_flag_error (-1); 111221f6ecabSRudolf Cornelissen 111321f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 111421f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 111521f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 111621f6ecabSRudolf Cornelissen /* log on errors */ 111721f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 111821f6ecabSRudolf Cornelissen if (stat) 111921f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting up h_phase\n")); 112021f6ecabSRudolf Cornelissen 112121f6ecabSRudolf Cornelissen return stat; 112221f6ecabSRudolf Cornelissen }//end BT_setup_hphase. 112321f6ecabSRudolf Cornelissen 112421f6ecabSRudolf Cornelissen static uint8 BT_read_monstat(uint8* monstat) 112521f6ecabSRudolf Cornelissen { 112621f6ecabSRudolf Cornelissen uint8 stat; 112721f6ecabSRudolf Cornelissen uint8 buffer[3]; 112821f6ecabSRudolf Cornelissen 1129efe9c7a6SRudolf Cornelissen /* make sure we have the recommended failsafe selected */ 1130efe9c7a6SRudolf Cornelissen *monstat = 0; 1131efe9c7a6SRudolf Cornelissen 11329a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Autodetecting connected output devices\n")); 11339a7218c5SRudolf Cornelissen 113421f6ecabSRudolf Cornelissen /* set BT to return connection status in ESTATUS on next read CMD: */ 113521f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 113621f6ecabSRudolf Cornelissen /* set ESTATUS at b'01' (return conn.stat.) */ 113721f6ecabSRudolf Cornelissen buffer[1] = 0xc4; 113821f6ecabSRudolf Cornelissen /* and leave chip outputs on. */ 113921f6ecabSRudolf Cornelissen buffer[2] = 0x41; 114021f6ecabSRudolf Cornelissen 114121f6ecabSRudolf Cornelissen /* reset status */ 114221f6ecabSRudolf Cornelissen i2c_flag_error (-1); 114321f6ecabSRudolf Cornelissen 114421f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 114521f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 114621f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 114721f6ecabSRudolf Cornelissen /* log on errors */ 114821f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 114921f6ecabSRudolf Cornelissen if (stat) 115021f6ecabSRudolf Cornelissen { 115121f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while reading connection status (1)\n")); 115221f6ecabSRudolf Cornelissen return stat; 115321f6ecabSRudolf Cornelissen } 115421f6ecabSRudolf Cornelissen 115521f6ecabSRudolf Cornelissen /* do actual read connection status: */ 115621f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 115721f6ecabSRudolf Cornelissen /* select register with CHECK_STAT CMD */ 115821f6ecabSRudolf Cornelissen buffer[1] = 0xba; 115921f6ecabSRudolf Cornelissen /* issue actual command. */ 116021f6ecabSRudolf Cornelissen buffer[2] = 0x40; 116121f6ecabSRudolf Cornelissen 116221f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 116321f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 116421f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 116521f6ecabSRudolf Cornelissen /* log on errors */ 116621f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 116721f6ecabSRudolf Cornelissen if (stat) 116821f6ecabSRudolf Cornelissen { 116921f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while reading connection status (2)\n")); 117021f6ecabSRudolf Cornelissen return stat; 117121f6ecabSRudolf Cornelissen } 117221f6ecabSRudolf Cornelissen 117321f6ecabSRudolf Cornelissen /* CX: Wait 600uS for signals to stabilize (see datasheet) */ 117421f6ecabSRudolf Cornelissen /* warning, note: 117521f6ecabSRudolf Cornelissen * datasheet is in error! 60mS needed!! */ 117621f6ecabSRudolf Cornelissen snooze(60000); 117721f6ecabSRudolf Cornelissen 117821f6ecabSRudolf Cornelissen /* read back updated connection status: */ 117921f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + RD; 118021f6ecabSRudolf Cornelissen 118121f6ecabSRudolf Cornelissen /* transmit 1 byte */ 118221f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 118321f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 1); 118421f6ecabSRudolf Cornelissen 118521f6ecabSRudolf Cornelissen /* receive 1 byte */ 11869a7218c5SRudolf Cornelissen /* ACK level to TX after last byte to RX should be 1 (= NACK) (see I2C spec) 118721f6ecabSRudolf Cornelissen * While the BT's don't care, CX chips will block the SDA line if an ACK gets sent! */ 118821f6ecabSRudolf Cornelissen buffer[0] = 1; 118921f6ecabSRudolf Cornelissen i2c_readbuffer(si->ps.tv_encoder.bus, buffer, 1); 119021f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 119121f6ecabSRudolf Cornelissen /* log on errors */ 119221f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 119321f6ecabSRudolf Cornelissen if (stat) 119421f6ecabSRudolf Cornelissen { 119521f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while reading connection status (3)\n")); 119621f6ecabSRudolf Cornelissen return stat; 119721f6ecabSRudolf Cornelissen } 119821f6ecabSRudolf Cornelissen 119921f6ecabSRudolf Cornelissen *monstat = ((buffer[0] & 0xe0) >> 5); 120021f6ecabSRudolf Cornelissen LOG(4,("Brooktree: TV output monitor status = %d\n", *monstat)); 120121f6ecabSRudolf Cornelissen 120221f6ecabSRudolf Cornelissen /* instruct BT to go back to normal operation: */ 120321f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 120421f6ecabSRudolf Cornelissen /* select register with CHECK_STAT CMD */ 120521f6ecabSRudolf Cornelissen buffer[1] = 0xba; 120621f6ecabSRudolf Cornelissen /* issue actual command. */ 120721f6ecabSRudolf Cornelissen buffer[2] = 0x00; 120821f6ecabSRudolf Cornelissen 120921f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 121021f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 121121f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 121221f6ecabSRudolf Cornelissen /* log on errors */ 121321f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 121421f6ecabSRudolf Cornelissen if (stat) 121521f6ecabSRudolf Cornelissen { 121621f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while reading connection status (4)\n")); 121721f6ecabSRudolf Cornelissen return stat; 121821f6ecabSRudolf Cornelissen } 121921f6ecabSRudolf Cornelissen 122021f6ecabSRudolf Cornelissen return stat; 122121f6ecabSRudolf Cornelissen }//end BT_read_monstat. 122221f6ecabSRudolf Cornelissen 122321f6ecabSRudolf Cornelissen static uint8 BT_killclk_blackout(void) 122421f6ecabSRudolf Cornelissen { 122521f6ecabSRudolf Cornelissen uint8 stat; 122621f6ecabSRudolf Cornelissen 122721f6ecabSRudolf Cornelissen uint8 buffer[4]; 122821f6ecabSRudolf Cornelissen 12299a7218c5SRudolf Cornelissen LOG(4,("Brooktree: Killing clock and/or blacking out (blocking output signals)\n")); 12309a7218c5SRudolf Cornelissen 123121f6ecabSRudolf Cornelissen /* reset status */ 123221f6ecabSRudolf Cornelissen i2c_flag_error (-1); 123321f6ecabSRudolf Cornelissen 123421f6ecabSRudolf Cornelissen if (si->ps.tv_encoder.type <= BT869) //BT... 123521f6ecabSRudolf Cornelissen { 123621f6ecabSRudolf Cornelissen /* Only disable external pixelclock input on BT's. 123721f6ecabSRudolf Cornelissen * CX chips will lock the bus if you do this. 123821f6ecabSRudolf Cornelissen * (It looks like the external pixelclock is always OK as long as a valid 123921f6ecabSRudolf Cornelissen * mode is programmed for the TVout chip. This means that disabling the use 124021f6ecabSRudolf Cornelissen * of this clock is not needed anyway. 124121f6ecabSRudolf Cornelissen * If you do disable this input, this pixelclock will rise to about 60Mhz BTW..) */ 124221f6ecabSRudolf Cornelissen 124321f6ecabSRudolf Cornelissen /* disable use of external pixelclock source... */ 124421f6ecabSRudolf Cornelissen /* (should prevent BT for being 'overclocked' by RIVA in VGA-only mode...) */ 124521f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 124621f6ecabSRudolf Cornelissen /* select BT register for setting EN_XCLK */ 124721f6ecabSRudolf Cornelissen buffer[1] = 0xa0; 124821f6ecabSRudolf Cornelissen /* clear it */ 124921f6ecabSRudolf Cornelissen buffer[2] = 0x00; 125021f6ecabSRudolf Cornelissen 125121f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 125221f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3); 125321f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 125421f6ecabSRudolf Cornelissen /* log on errors */ 125521f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 125621f6ecabSRudolf Cornelissen if (stat) 125721f6ecabSRudolf Cornelissen { 125821f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-BT)\n")); 125921f6ecabSRudolf Cornelissen return stat; 126021f6ecabSRudolf Cornelissen } 126121f6ecabSRudolf Cornelissen } 126221f6ecabSRudolf Cornelissen else //CX... 126321f6ecabSRudolf Cornelissen { 126421f6ecabSRudolf Cornelissen /* Disable CX video out (or wild output will be seen on TV..) */ 126521f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 126621f6ecabSRudolf Cornelissen /* select register in CX */ 126721f6ecabSRudolf Cornelissen buffer[1] = 0x6c; 126821f6ecabSRudolf Cornelissen /* disable active video out. */ 126921f6ecabSRudolf Cornelissen buffer[2] = 0x02; 127021f6ecabSRudolf Cornelissen 127121f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 127221f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3); 127321f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 127421f6ecabSRudolf Cornelissen /* log on errors */ 127521f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 127621f6ecabSRudolf Cornelissen if (stat) 127721f6ecabSRudolf Cornelissen { 127821f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (1-CX)\n")); 127921f6ecabSRudolf Cornelissen return stat; 128021f6ecabSRudolf Cornelissen } 128121f6ecabSRudolf Cornelissen } 128221f6ecabSRudolf Cornelissen 128321f6ecabSRudolf Cornelissen /* black-out TVout while outputs are enabled... */ 128421f6ecabSRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 128521f6ecabSRudolf Cornelissen /* select first TV config register to write */ 128621f6ecabSRudolf Cornelissen buffer[1] = 0xc4; 128721f6ecabSRudolf Cornelissen /* disable testimage while outputs remain enabled */ 128821f6ecabSRudolf Cornelissen buffer[2] = 0x01; 128921f6ecabSRudolf Cornelissen /* input is 24bit mpx'd RGB, BLANK = in, sync = act. hi */ 129021f6ecabSRudolf Cornelissen buffer[3] = 0x18; 129121f6ecabSRudolf Cornelissen 129221f6ecabSRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 129321f6ecabSRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, sizeof(buffer)); 129421f6ecabSRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 129521f6ecabSRudolf Cornelissen /* log on errors */ 129621f6ecabSRudolf Cornelissen stat = i2c_flag_error(0); 129721f6ecabSRudolf Cornelissen if (stat) 129821f6ecabSRudolf Cornelissen { 129921f6ecabSRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while doing killclk_blackout (2)\n")); 130021f6ecabSRudolf Cornelissen return stat; 130121f6ecabSRudolf Cornelissen } 130221f6ecabSRudolf Cornelissen 130321f6ecabSRudolf Cornelissen return stat; 130421f6ecabSRudolf Cornelissen }//end BT_killclk_blackout. 130521f6ecabSRudolf Cornelissen 13063aa21459SRudolf Cornelissen uint8 BT_dpms(bool display) 13073aa21459SRudolf Cornelissen { 13083aa21459SRudolf Cornelissen uint8 stat; 13093aa21459SRudolf Cornelissen 13103aa21459SRudolf Cornelissen uint8 buffer[3]; 13113aa21459SRudolf Cornelissen 13123aa21459SRudolf Cornelissen LOG(4,("Brooktree: setting DPMS: ")); 13133aa21459SRudolf Cornelissen 13143aa21459SRudolf Cornelissen /* reset status */ 13153aa21459SRudolf Cornelissen i2c_flag_error (-1); 13163aa21459SRudolf Cornelissen 13173aa21459SRudolf Cornelissen /* shutdown all analog electronics... */ 13183aa21459SRudolf Cornelissen buffer[0] = si->ps.tv_encoder.adress + WR; 13193aa21459SRudolf Cornelissen /* select first TV config register to write */ 13203aa21459SRudolf Cornelissen buffer[1] = 0xba; 13213aa21459SRudolf Cornelissen if (display) 13223aa21459SRudolf Cornelissen { 13233aa21459SRudolf Cornelissen /* enable all DACs */ 13243aa21459SRudolf Cornelissen buffer[2] = 0x00; 13253aa21459SRudolf Cornelissen LOG(4,("display on\n")); 13263aa21459SRudolf Cornelissen } 13273aa21459SRudolf Cornelissen else 13283aa21459SRudolf Cornelissen { 13293aa21459SRudolf Cornelissen /* shutdown all DACs */ 13303aa21459SRudolf Cornelissen buffer[2] = 0x10; 13313aa21459SRudolf Cornelissen LOG(4,("display off\n")); 13323aa21459SRudolf Cornelissen } 13333aa21459SRudolf Cornelissen 13343aa21459SRudolf Cornelissen i2c_bstart(si->ps.tv_encoder.bus); 13353aa21459SRudolf Cornelissen i2c_writebuffer(si->ps.tv_encoder.bus, buffer, 3); 13363aa21459SRudolf Cornelissen i2c_bstop(si->ps.tv_encoder.bus); 13373aa21459SRudolf Cornelissen /* log on errors */ 13383aa21459SRudolf Cornelissen stat = i2c_flag_error(0); 13393aa21459SRudolf Cornelissen if (stat) 13403aa21459SRudolf Cornelissen { 13413aa21459SRudolf Cornelissen LOG(4,("Brooktree: I2C errors occurred while setting DPMS\n")); 13423aa21459SRudolf Cornelissen return stat; 13433aa21459SRudolf Cornelissen } 13443aa21459SRudolf Cornelissen 13453aa21459SRudolf Cornelissen return stat; 13463aa21459SRudolf Cornelissen }//end BT_dpms. 13473aa21459SRudolf Cornelissen 1348b2459715SRudolf Cornelissen uint8 BT_check_tvmode(display_mode target) 1349fb6cadf1Sshatty { 1350b2459715SRudolf Cornelissen uint8 status = NOT_SUPPORTED; 1351b2459715SRudolf Cornelissen uint32 mode = ((target.timing.h_display) | ((target.timing.v_display) << 16)); 1352b2459715SRudolf Cornelissen 1353b2459715SRudolf Cornelissen switch (mode) 1354b2459715SRudolf Cornelissen { 1355b2459715SRudolf Cornelissen case (640 | (480 << 16)): 1356c5fe5f2dSRudolf Cornelissen if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO))) 1357c5fe5f2dSRudolf Cornelissen status = PAL640; 1358b2459715SRudolf Cornelissen if ((target.flags & TV_BITS) == TV_NTSC) 1359b2459715SRudolf Cornelissen { 1360b2459715SRudolf Cornelissen if (!(target.flags & TV_VIDEO)) status = NTSC640; 1361b2459715SRudolf Cornelissen else status = NTSC640_OS; 1362b2459715SRudolf Cornelissen } 1363b2459715SRudolf Cornelissen break; 1364c5fe5f2dSRudolf Cornelissen case (768 | (576 << 16)): 1365c5fe5f2dSRudolf Cornelissen if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO)) 1366c5fe5f2dSRudolf Cornelissen status = PAL800_OS; 1367c5fe5f2dSRudolf Cornelissen break; 1368b2459715SRudolf Cornelissen case (800 | (600 << 16)): 1369c5fe5f2dSRudolf Cornelissen if (((target.flags & TV_BITS) == TV_PAL) && (!(target.flags & TV_VIDEO))) 1370c5fe5f2dSRudolf Cornelissen status = PAL800; 1371c5fe5f2dSRudolf Cornelissen if (((target.flags & TV_BITS) == TV_NTSC) && (!(target.flags & TV_VIDEO))) 1372c5fe5f2dSRudolf Cornelissen status = NTSC800; 1373b2459715SRudolf Cornelissen break; 1374b2459715SRudolf Cornelissen case (720 | (480 << 16)): 1375b2459715SRudolf Cornelissen if (((target.flags & TV_BITS) == TV_NTSC) && (target.flags & TV_VIDEO)) 1376b2459715SRudolf Cornelissen status = NTSC720; 1377b2459715SRudolf Cornelissen break; 1378b2459715SRudolf Cornelissen case (720 | (576 << 16)): 1379b2459715SRudolf Cornelissen if (((target.flags & TV_BITS) == TV_PAL) && (target.flags & TV_VIDEO)) 1380b2459715SRudolf Cornelissen status = PAL720; 1381b2459715SRudolf Cornelissen break; 1382b2459715SRudolf Cornelissen } 1383b2459715SRudolf Cornelissen 1384b2459715SRudolf Cornelissen return status; 1385b2459715SRudolf Cornelissen }//end BT_check_tvmode. 1386b2459715SRudolf Cornelissen 1387bd7693f2SRudolf Cornelissen 1388bd7693f2SRudolf Cornelissen /* 1389da3804eeSRudolf Cornelissen //BeTVOut's SwitchRIVAtoTV(vtot) timing formula: (note: vtot = (v_total - 2)) 1390bd7693f2SRudolf Cornelissen //----------------------------------------------------------------------------------- 1391bd7693f2SRudolf Cornelissen //HORIZONTAL: 1392bd7693f2SRudolf Cornelissen //----------- 1393bd7693f2SRudolf Cornelissen h_sync_start = h_display; 1394bd7693f2SRudolf Cornelissen 1395bd7693f2SRudolf Cornelissen //fixme, note, checkout: 1396bd7693f2SRudolf Cornelissen //feels like in fact TNT2-M64 nv_crtc.c registerprogramming should be adapted... 1397bd7693f2SRudolf Cornelissen if (TNT2-M64) 1398bd7693f2SRudolf Cornelissen { 1399bd7693f2SRudolf Cornelissen h_sync_end = h_display + 8; 1400bd7693f2SRudolf Cornelissen h_total = h_display + 56; 1401bd7693f2SRudolf Cornelissen } 1402bd7693f2SRudolf Cornelissen else //TNT1, TNT2, Geforce2... (so default) 1403bd7693f2SRudolf Cornelissen { 1404bd7693f2SRudolf Cornelissen h_sync_end = h_display + 16; 1405bd7693f2SRudolf Cornelissen h_total = h_display + 48; 1406bd7693f2SRudolf Cornelissen } 1407bd7693f2SRudolf Cornelissen 1408bd7693f2SRudolf Cornelissen //fixme, note, checkout: 1409bd7693f2SRudolf Cornelissen //BeTVOut uses two 'tweaks': 1410bd7693f2SRudolf Cornelissen // - on TNT2-M64 only: 1411bd7693f2SRudolf Cornelissen // register h_blank_e is increased with 1 (so should be done in nv_crtc.c here) 1412463f0fabSRudolf Cornelissen // - 'all cards': 1413463f0fabSRudolf Cornelissen // register h_blank_e b6 = 0 (only influences TNT2-M64 in modes NTSC800 and PAL800). 1414bd7693f2SRudolf Cornelissen //----------------------------------------------------------------------------------- 1415bd7693f2SRudolf Cornelissen //VERTICAL: 1416bd7693f2SRudolf Cornelissen //--------- 1417da3804eeSRudolf Cornelissen v_sync_start = v_display; 1418da3804eeSRudolf Cornelissen v_total = vtot + 2; 1419da3804eeSRudolf Cornelissen v_sync_end = v_total - 1; //(This takes care of the 'cursor trash' on TNT1's...) 1420bd7693f2SRudolf Cornelissen //----------------------------------------------------------------------------------- 1421bd7693f2SRudolf Cornelissen */ 142285406c4dSRudolf Cornelissen static status_t BT_update_mode_for_gpu(display_mode *target, uint8 tvmode) 142385406c4dSRudolf Cornelissen { 1424b0fce481SRudolf Cornelissen //fixme if needed: 1425b0fce481SRudolf Cornelissen //pixelclock is not actually pgm'd because PLL is pgm' earlier during setmode... 142685406c4dSRudolf Cornelissen switch (tvmode) 142785406c4dSRudolf Cornelissen { 142885406c4dSRudolf Cornelissen case NTSC640: 142985406c4dSRudolf Cornelissen case NTSC640_TST: 1430bd7693f2SRudolf Cornelissen target->timing.h_display = 640; 1431bd7693f2SRudolf Cornelissen target->timing.h_sync_start = 640; 1432bd7693f2SRudolf Cornelissen if (si->ps.card_type == NV05M64) 1433bd7693f2SRudolf Cornelissen { 1434bd7693f2SRudolf Cornelissen target->timing.h_sync_end = 648; 1435bd7693f2SRudolf Cornelissen target->timing.h_total = 696; 1436bd7693f2SRudolf Cornelissen } 1437bd7693f2SRudolf Cornelissen else 1438bd7693f2SRudolf Cornelissen { 14394e918a7cSRudolf Cornelissen //fixme if possible: 14404e918a7cSRudolf Cornelissen //see if tweaking h_sync_end can shift picture 8 pixels right to fix 14414e918a7cSRudolf Cornelissen //ws tv's tuning fault (always going for max. compatibility :) 1442bd7693f2SRudolf Cornelissen target->timing.h_sync_end = 656; 1443bd7693f2SRudolf Cornelissen target->timing.h_total = 688; 1444bd7693f2SRudolf Cornelissen } 1445bd7693f2SRudolf Cornelissen target->timing.v_display = 480; 1446da3804eeSRudolf Cornelissen target->timing.v_sync_start = 480; 1447da3804eeSRudolf Cornelissen target->timing.v_sync_end = 555; //This prevents 'cursor trash' on TNT1's 1448da3804eeSRudolf Cornelissen target->timing.v_total = 556; //Above 525 because mode scales down 1449da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1450da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((696 * 556 * 60) / 1000); 1451da3804eeSRudolf Cornelissen else 1452da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((688 * 556 * 60) / 1000); 145385406c4dSRudolf Cornelissen break; 145485406c4dSRudolf Cornelissen case NTSC800: 1455da3804eeSRudolf Cornelissen target->timing.h_display = 800; 1456da3804eeSRudolf Cornelissen target->timing.h_sync_start = 800; 1457da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1458da3804eeSRudolf Cornelissen { 1459da3804eeSRudolf Cornelissen target->timing.h_sync_end = 808; 1460da3804eeSRudolf Cornelissen target->timing.h_total = 856; 1461da3804eeSRudolf Cornelissen } 1462da3804eeSRudolf Cornelissen else 1463da3804eeSRudolf Cornelissen { 1464da3804eeSRudolf Cornelissen target->timing.h_sync_end = 816; 1465da3804eeSRudolf Cornelissen target->timing.h_total = 848; 1466da3804eeSRudolf Cornelissen } 1467da3804eeSRudolf Cornelissen target->timing.v_display = 600; 1468da3804eeSRudolf Cornelissen target->timing.v_sync_start = 600; 1469da3804eeSRudolf Cornelissen target->timing.v_sync_end = 685; //This prevents 'cursor trash' on TNT1's 1470da3804eeSRudolf Cornelissen target->timing.v_total = 686; //Above 525 because mode scales down 1471da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1472da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((856 * 686 * 60) / 1000); 1473da3804eeSRudolf Cornelissen else 1474da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((848 * 686 * 60) / 1000); 147585406c4dSRudolf Cornelissen break; 147685406c4dSRudolf Cornelissen case PAL640: 1477bd7693f2SRudolf Cornelissen target->timing.h_display = 640; 1478da3804eeSRudolf Cornelissen target->timing.h_sync_start = 640; 1479da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1480da3804eeSRudolf Cornelissen { 1481da3804eeSRudolf Cornelissen target->timing.h_sync_end = 648; 1482da3804eeSRudolf Cornelissen target->timing.h_total = 696; 1483da3804eeSRudolf Cornelissen } 1484da3804eeSRudolf Cornelissen else 1485da3804eeSRudolf Cornelissen { 1486da3804eeSRudolf Cornelissen target->timing.h_sync_end = 656; 1487da3804eeSRudolf Cornelissen target->timing.h_total = 688; 1488da3804eeSRudolf Cornelissen } 1489bd7693f2SRudolf Cornelissen target->timing.v_display = 480; 1490da3804eeSRudolf Cornelissen target->timing.v_sync_start = 480; 1491da3804eeSRudolf Cornelissen target->timing.v_sync_end = 570; //This prevents 'cursor trash' on TNT1's 1492da3804eeSRudolf Cornelissen target->timing.v_total = 571; //Below 625 because mode scales up 1493da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1494da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((696 * 571 * 50) / 1000); 1495da3804eeSRudolf Cornelissen else 1496da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((688 * 571 * 50) / 1000); 149785406c4dSRudolf Cornelissen break; 149885406c4dSRudolf Cornelissen case PAL800: 149985406c4dSRudolf Cornelissen case PAL800_TST: 1500da3804eeSRudolf Cornelissen target->timing.h_display = 800; 1501da3804eeSRudolf Cornelissen target->timing.h_sync_start = 800; 1502da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1503da3804eeSRudolf Cornelissen { 1504da3804eeSRudolf Cornelissen target->timing.h_sync_end = 808; 1505da3804eeSRudolf Cornelissen target->timing.h_total = 856; 1506da3804eeSRudolf Cornelissen } 1507da3804eeSRudolf Cornelissen else 1508da3804eeSRudolf Cornelissen { 1509da3804eeSRudolf Cornelissen target->timing.h_sync_end = 816; 1510da3804eeSRudolf Cornelissen target->timing.h_total = 848; 1511da3804eeSRudolf Cornelissen } 1512da3804eeSRudolf Cornelissen target->timing.v_display = 600; 1513da3804eeSRudolf Cornelissen target->timing.v_sync_start = 600; 1514da3804eeSRudolf Cornelissen target->timing.v_sync_end = 695; //This prevents 'cursor trash' on TNT1's 1515da3804eeSRudolf Cornelissen target->timing.v_total = 696; //Above 625 because mode scales down 1516da3804eeSRudolf Cornelissen if (si->ps.card_type == NV05M64) 1517da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((856 * 696 * 50) / 1000); 1518da3804eeSRudolf Cornelissen else 1519da3804eeSRudolf Cornelissen target->timing.pixel_clock = ((848 * 696 * 50) / 1000); 152085406c4dSRudolf Cornelissen break; 152185406c4dSRudolf Cornelissen case NTSC640_OS: 152285406c4dSRudolf Cornelissen target->timing.h_display = 640; //BT H_ACTIVE 152385406c4dSRudolf Cornelissen target->timing.h_sync_start = 744; //set for CH/BT compatible TV output 152485406c4dSRudolf Cornelissen target->timing.h_sync_end = 744+20; //delta is BT H_BLANKI 152585406c4dSRudolf Cornelissen target->timing.h_total = 784; //BT H_CLKI 152685406c4dSRudolf Cornelissen target->timing.v_display = 480; //BT V_ACTIVEI 152785406c4dSRudolf Cornelissen target->timing.v_sync_start = 490; //set for centered sync pulse 152885406c4dSRudolf Cornelissen target->timing.v_sync_end = 490+25; //delta is BT V_BLANKI 1529da3804eeSRudolf Cornelissen target->timing.v_total = 525; //BT V_LINESI (== 525: 1:1 scaled mode) 153085406c4dSRudolf Cornelissen target->timing.pixel_clock = ((784 * 525 * 60) / 1000); //refresh 153185406c4dSRudolf Cornelissen break; 153285406c4dSRudolf Cornelissen case PAL800_OS: 153385406c4dSRudolf Cornelissen target->timing.h_display = 768; //H_ACTIVE 15346245f19cSRudolf Cornelissen if (si->ps.tv_encoder.type <= BT869) 15356245f19cSRudolf Cornelissen { 15364e918a7cSRudolf Cornelissen /* confirmed on TNT1 using 4:3 TV and 16:9 TV */ 15376245f19cSRudolf Cornelissen target->timing.h_sync_start = 856; //set for centered TV output 15386245f19cSRudolf Cornelissen target->timing.h_sync_end = 856+20; //delta is BT H_BLANKI 15396245f19cSRudolf Cornelissen } 15406245f19cSRudolf Cornelissen else 15416245f19cSRudolf Cornelissen { 1542195828c4SRudolf Cornelissen /* confirmed on NV11 using 4:3 TV and 16:9 TV */ 154385406c4dSRudolf Cornelissen target->timing.h_sync_start = 848; //set for centered TV output 154485406c4dSRudolf Cornelissen target->timing.h_sync_end = 848+20; //delta is BT H_BLANKI 15456245f19cSRudolf Cornelissen } 154685406c4dSRudolf Cornelissen target->timing.h_total = 944; //BT H_CLKI 154785406c4dSRudolf Cornelissen target->timing.v_display = 576; //V_ACTIVEI 154885406c4dSRudolf Cornelissen target->timing.v_sync_start = 579; //set for centered sync pulse 154985406c4dSRudolf Cornelissen target->timing.v_sync_end = 579+42; //delta is BT V_BLANKI 1550da3804eeSRudolf Cornelissen target->timing.v_total = 625; //BT V_LINESI (== 625: 1:1 scaled mode) 155185406c4dSRudolf Cornelissen target->timing.pixel_clock = ((944 * 625 * 50) / 1000); //refresh 155285406c4dSRudolf Cornelissen break; 155385406c4dSRudolf Cornelissen case NTSC720: 155485406c4dSRudolf Cornelissen /* (tested on TNT2 with BT869) */ 155585406c4dSRudolf Cornelissen target->timing.h_display = 720; //H_ACTIVE 15565cadaa5fSRudolf Cornelissen if (si->ps.tv_encoder.type <= BT869) 15575cadaa5fSRudolf Cornelissen { 15585cadaa5fSRudolf Cornelissen /* confirmed on TNT1 using 4:3 TV and 16:9 TV */ 155985406c4dSRudolf Cornelissen target->timing.h_sync_start = 744; //do not change! 156085406c4dSRudolf Cornelissen target->timing.h_sync_end = 744+144; //delta is H_sync_pulse 15615cadaa5fSRudolf Cornelissen } 15625cadaa5fSRudolf Cornelissen else 15635cadaa5fSRudolf Cornelissen { 1564195828c4SRudolf Cornelissen /* confirmed on NV11 using 4:3 TV and 16:9 TV */ 15655cadaa5fSRudolf Cornelissen target->timing.h_sync_start = 728; //do not change! 15665cadaa5fSRudolf Cornelissen target->timing.h_sync_end = 728+160; //delta is H_sync_pulse 15675cadaa5fSRudolf Cornelissen } 156885406c4dSRudolf Cornelissen target->timing.h_total = 888; //BT H_TOTAL 156985406c4dSRudolf Cornelissen target->timing.v_display = 480; //V_ACTIVEI 157085406c4dSRudolf Cornelissen target->timing.v_sync_start = 490; //set for centered sync pulse 157185406c4dSRudolf Cornelissen target->timing.v_sync_end = 490+26; //delta is V_sync_pulse 1572da3804eeSRudolf Cornelissen target->timing.v_total = 525; //CH V_TOTAL (== 525: 1:1 scaled mode) 157385406c4dSRudolf Cornelissen target->timing.pixel_clock = ((888 * 525 * 60) / 1000); //refresh 157485406c4dSRudolf Cornelissen break; 157585406c4dSRudolf Cornelissen case PAL720: 157685406c4dSRudolf Cornelissen target->timing.h_display = 720; //BT H_ACTIVE 157785406c4dSRudolf Cornelissen target->timing.h_sync_start = 744; //set for centered sync pulse 157885406c4dSRudolf Cornelissen target->timing.h_sync_end = 744+140; //delta is BT H_BLANKI 157985406c4dSRudolf Cornelissen target->timing.h_total = 888; //BT H_CLKI 158085406c4dSRudolf Cornelissen target->timing.v_display = 576; //BT V_ACTIVEI 158185406c4dSRudolf Cornelissen target->timing.v_sync_start = 579; //set for centered sync pulse 158285406c4dSRudolf Cornelissen target->timing.v_sync_end = 579+42; //delta is BT V_BLANKI 1583da3804eeSRudolf Cornelissen target->timing.v_total = 625; //BT V_LINESI (== 625: 1:1 scaled mode) 158485406c4dSRudolf Cornelissen target->timing.pixel_clock = ((888 * 625 * 50) / 1000); //refresh 158585406c4dSRudolf Cornelissen break; 158685406c4dSRudolf Cornelissen default: 158785406c4dSRudolf Cornelissen return B_ERROR; 158885406c4dSRudolf Cornelissen } 158985406c4dSRudolf Cornelissen 159085406c4dSRudolf Cornelissen return B_OK; 159185406c4dSRudolf Cornelissen }//end BT_update_mode_for_gpu. 159285406c4dSRudolf Cornelissen 159322a0d15bSRudolf Cornelissen /* note: 159422a0d15bSRudolf Cornelissen * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869), 159522a0d15bSRudolf Cornelissen * Diamond Viper V550 16Mb PCI (TNT1/BT869), 159622a0d15bSRudolf Cornelissen * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */ 159722a0d15bSRudolf Cornelissen static status_t BT_start_tvout(void) 159822a0d15bSRudolf Cornelissen { 159922a0d15bSRudolf Cornelissen /* enable access to primary head */ 160022a0d15bSRudolf Cornelissen set_crtc_owner(0); 160122a0d15bSRudolf Cornelissen 16029b394aa2SRudolf Cornelissen /* CAUTION: 16035cadaa5fSRudolf Cornelissen * On old cards, PLLSEL (and TV_SETUP?) cannot be read (sometimes?), but 16045cadaa5fSRudolf Cornelissen * write actions do succeed ... 16055cadaa5fSRudolf Cornelissen * This is confirmed for both ISA and PCI access, on NV04 and NV11. */ 160622a0d15bSRudolf Cornelissen 160722a0d15bSRudolf Cornelissen /* setup TVencoder connection */ 160822a0d15bSRudolf Cornelissen /* b1-0 = %01: encoder type is MASTER; 160922a0d15bSRudolf Cornelissen * b24 = 1: VIP datapos is b0-7 */ 1610b0fce481SRudolf Cornelissen //fixme if needed: setup completely instead of relying on pre-init by BIOS.. 16115cadaa5fSRudolf Cornelissen //(it seems to work OK on NV04 and NV11 although read reg. doesn't seem to work) 1612b0fce481SRudolf Cornelissen DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000002) | 0x01000001)); 161322a0d15bSRudolf Cornelissen 161422a0d15bSRudolf Cornelissen /* tell GPU to use pixelclock from TVencoder instead of using internal source */ 161522a0d15bSRudolf Cornelissen /* (nessecary or display will 'shiver' on both TV and VGA.) */ 16169b394aa2SRudolf Cornelissen if (si->ps.secondary_head) 16175cadaa5fSRudolf Cornelissen //fixme: assuming TVout is on primary head!! 16185cadaa5fSRudolf Cornelissen DACW(PLLSEL, 0x20030f00); 16199b394aa2SRudolf Cornelissen else 16209b394aa2SRudolf Cornelissen DACW(PLLSEL, 0x00030700); 162122a0d15bSRudolf Cornelissen 162222a0d15bSRudolf Cornelissen /* Set overscan color to 'black' */ 162322a0d15bSRudolf Cornelissen /* note: 162422a0d15bSRudolf Cornelissen * Change this instruction for a visible overscan color if you're trying to 162522a0d15bSRudolf Cornelissen * center the output on TV. Use it as a guide-'line' then ;-) */ 162622a0d15bSRudolf Cornelissen ATBW(OSCANCOLOR, 0x00); 162722a0d15bSRudolf Cornelissen 162822a0d15bSRudolf Cornelissen /* set CRTC to slaved mode (b7 = 1) and clear TVadjust (b3-5 = %000) */ 162922a0d15bSRudolf Cornelissen CRTCW(PIXEL, ((CRTCR(PIXEL) & 0xc7) | 0x80)); 1630bd419083SRudolf Cornelissen /* select TV encoder, not panel encoder (b0 = 0). 1631bd419083SRudolf Cornelissen * Note: 1632b0fce481SRudolf Cornelissen * Both are devices (often) using the CRTC in slaved mode. */ 1633bd419083SRudolf Cornelissen CRTCW(LCD, (CRTCR(LCD) & 0xfe)); 163422a0d15bSRudolf Cornelissen 1635bd419083SRudolf Cornelissen /* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of 1636bd419083SRudolf Cornelissen * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */ 1637bd419083SRudolf Cornelissen CRTCW(TREG, 0x80); 163822a0d15bSRudolf Cornelissen 163922a0d15bSRudolf Cornelissen return B_OK; 164022a0d15bSRudolf Cornelissen }//end BT_start_tvout. 164122a0d15bSRudolf Cornelissen 1642bd419083SRudolf Cornelissen /* note: 1643bd419083SRudolf Cornelissen * tested on ELSA Erazor III 32Mb AGP (TNT2/BT869), 1644bd419083SRudolf Cornelissen * Diamond Viper V550 16Mb PCI (TNT1/BT869), 1645bd419083SRudolf Cornelissen * and ASUS V7100 GeForce2 MX200 AGP/32Mb (CH7007). */ 164622a0d15bSRudolf Cornelissen status_t BT_stop_tvout(void) 164722a0d15bSRudolf Cornelissen { 164822a0d15bSRudolf Cornelissen /* prevent BT from being overclocked by VGA-only modes & black-out TV-out */ 164922a0d15bSRudolf Cornelissen BT_killclk_blackout(); 165022a0d15bSRudolf Cornelissen 1651bd419083SRudolf Cornelissen /* enable access to primary head */ 1652bd419083SRudolf Cornelissen set_crtc_owner(0); 1653bd419083SRudolf Cornelissen 1654bd419083SRudolf Cornelissen /* switch on VGA monitor HSYNC and VSYNC */ 1655bd419083SRudolf Cornelissen //fixme: see if better DPMS state fetching can be setup for crtc.c (!) 1656bd419083SRudolf Cornelissen CRTCW(REPAINT1, (CRTCR(REPAINT1) & 0x3f)); 1657bd419083SRudolf Cornelissen 1658bd419083SRudolf Cornelissen 16590b36eea4SRudolf Cornelissen /* wait for one image to be generated to make sure VGA has kicked in and is 16600b36eea4SRudolf Cornelissen * running OK before continuing... 16610b36eea4SRudolf Cornelissen * (Kicking in will fail often if we do not wait here) */ 1662bd419083SRudolf Cornelissen 16630b36eea4SRudolf Cornelissen /* make sure we are 'in' active VGA picture */ 16640b36eea4SRudolf Cornelissen while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1); 16650b36eea4SRudolf Cornelissen /* wait for next vertical retrace start on VGA */ 16660b36eea4SRudolf Cornelissen while (!(NV_REG8(NV8_INSTAT1) & 0x08)) snooze(1); 16670b36eea4SRudolf Cornelissen /* now wait until we are 'in' active VGA picture again */ 16680b36eea4SRudolf Cornelissen while (NV_REG8(NV8_INSTAT1) & 0x08) snooze(1); 1669bd419083SRudolf Cornelissen 16700b36eea4SRudolf Cornelissen 1671b0fce481SRudolf Cornelissen /* set CRTC to master mode (b7 = 0) if it wasn't slaved for a panel before */ 1672b0fce481SRudolf Cornelissen if (!(si->ps.slaved_tmds1)) CRTCW(PIXEL, (CRTCR(PIXEL) & 0x03)); 16730b36eea4SRudolf Cornelissen 16745cadaa5fSRudolf Cornelissen /* CAUTION: 16755cadaa5fSRudolf Cornelissen * On old cards, PLLSEL (and TV_SETUP?) cannot be read (sometimes?), but 16765cadaa5fSRudolf Cornelissen * write actions do succeed ... 16775cadaa5fSRudolf Cornelissen * This is confirmed for both ISA and PCI access, on NV04 and NV11. */ 1678bd419083SRudolf Cornelissen 16790b36eea4SRudolf Cornelissen /* setup TVencoder connection */ 16800b36eea4SRudolf Cornelissen /* b1-0 = %00: encoder type is SLAVE; 16810b36eea4SRudolf Cornelissen * b24 = 1: VIP datapos is b0-7 */ 1682b0fce481SRudolf Cornelissen //fixme if needed: setup completely instead of relying on pre-init by BIOS.. 16835cadaa5fSRudolf Cornelissen //(it seems to work OK on NV04 and NV11 although read reg. doesn't seem to work) 1684b0fce481SRudolf Cornelissen DACW(TV_SETUP, ((DACR(TV_SETUP) & ~0x00000003) | 0x01000000)); 1685bd419083SRudolf Cornelissen 16860b36eea4SRudolf Cornelissen /* tell GPU to use pixelclock from internal source instead of using TVencoder */ 16875cadaa5fSRudolf Cornelissen if (si->ps.secondary_head) 16885cadaa5fSRudolf Cornelissen DACW(PLLSEL, 0x30000f00); 16895cadaa5fSRudolf Cornelissen else 16900b36eea4SRudolf Cornelissen DACW(PLLSEL, 0x10000700); 1691bd419083SRudolf Cornelissen 16920b36eea4SRudolf Cornelissen /* HTOTAL, VTOTAL and OVERFLOW return their default CRTC use, instead of 16930b36eea4SRudolf Cornelissen * H, V-low and V-high 'shadow' counters(?)(b0, 4 and 6 = 0) (b7 use = unknown) */ 16940b36eea4SRudolf Cornelissen CRTCW(TREG, 0x00); 1695bd419083SRudolf Cornelissen 1696b0fce481SRudolf Cornelissen /* select panel encoder, not TV encoder if needed (b0 = 1). 16970b36eea4SRudolf Cornelissen * Note: 1698b0fce481SRudolf Cornelissen * Both are devices (often) using the CRTC in slaved mode. */ 1699b0fce481SRudolf Cornelissen if (si->ps.slaved_tmds1) CRTCW(LCD, (CRTCR(LCD) | 0x01)); 170022a0d15bSRudolf Cornelissen 170122a0d15bSRudolf Cornelissen /* fixme if needed: 170222a0d15bSRudolf Cornelissen * a full encoder chip reset could be done here (so after decoupling crtc)... */ 1703b0fce481SRudolf Cornelissen /* (but: beware of the 'locked SDA' syndrome then!) */ 170422a0d15bSRudolf Cornelissen 170522a0d15bSRudolf Cornelissen return B_OK; 1706bd419083SRudolf Cornelissen }//end BT_stop_tvout. 170722a0d15bSRudolf Cornelissen 1708b2459715SRudolf Cornelissen status_t BT_setmode(display_mode target) 1709b2459715SRudolf Cornelissen { 1710efe9c7a6SRudolf Cornelissen uint8 tvmode, monstat; 1711efe9c7a6SRudolf Cornelissen /* enable flickerfilter in desktop modes, disable it in video modes. */ 1712efe9c7a6SRudolf Cornelissen uint8 ffilter = 0; 1713b2459715SRudolf Cornelissen 1714fb6cadf1Sshatty /* use a display_mode copy because we might tune it for TVout compatibility */ 1715fb6cadf1Sshatty display_mode tv_target = target; 1716fb6cadf1Sshatty 1717fb6cadf1Sshatty /* preset new TVout mode */ 1718b2459715SRudolf Cornelissen tvmode = BT_check_tvmode(tv_target); 1719b2459715SRudolf Cornelissen if (!tvmode) return B_ERROR; 1720b2459715SRudolf Cornelissen 1721efe9c7a6SRudolf Cornelissen /* read current output devices connection status */ 1722efe9c7a6SRudolf Cornelissen BT_read_monstat(&monstat); 1723efe9c7a6SRudolf Cornelissen 1724efe9c7a6SRudolf Cornelissen /* (pre)set TV mode */ 1725efe9c7a6SRudolf Cornelissen /* note: 1726efe9c7a6SRudolf Cornelissen * Manual config is non-dependent of the state of the PAL hardware input pin; 1727efe9c7a6SRudolf Cornelissen * Also SDA lockups occur when setting EN_XCLK after autoconfig! 1728efe9c7a6SRudolf Cornelissen * Make sure PAL_MD=0 for NTSC and PAL_MD = 1 for PAL... */ 1729b2459715SRudolf Cornelissen switch (tvmode) 1730fb6cadf1Sshatty { 1731b2459715SRudolf Cornelissen case NTSC640: 1732b2459715SRudolf Cornelissen case NTSC640_TST: 1733efe9c7a6SRudolf Cornelissen ffilter = 1; 1734efe9c7a6SRudolf Cornelissen BT_init_NTSC640(); 1735b2459715SRudolf Cornelissen break; 1736b2459715SRudolf Cornelissen case NTSC800: 1737efe9c7a6SRudolf Cornelissen ffilter = 1; 1738efe9c7a6SRudolf Cornelissen BT_init_NTSC800(); 1739b2459715SRudolf Cornelissen break; 1740b2459715SRudolf Cornelissen case PAL640: 1741efe9c7a6SRudolf Cornelissen ffilter = 1; 1742efe9c7a6SRudolf Cornelissen BT_init_PAL640(); 1743b2459715SRudolf Cornelissen break; 1744b2459715SRudolf Cornelissen case PAL800: 1745b2459715SRudolf Cornelissen case PAL800_TST: 1746efe9c7a6SRudolf Cornelissen ffilter = 1; 1747efe9c7a6SRudolf Cornelissen BT_init_PAL800(); 1748b2459715SRudolf Cornelissen break; 1749b2459715SRudolf Cornelissen case NTSC640_OS: 1750efe9c7a6SRudolf Cornelissen BT_init_NTSC640_OS(); 1751b2459715SRudolf Cornelissen break; 1752b2459715SRudolf Cornelissen case PAL800_OS: 1753efe9c7a6SRudolf Cornelissen BT_init_PAL800_OS(); 1754b2459715SRudolf Cornelissen break; 1755b2459715SRudolf Cornelissen case NTSC720: 1756efe9c7a6SRudolf Cornelissen BT_init_NTSC720(); 1757b2459715SRudolf Cornelissen break; 1758b2459715SRudolf Cornelissen case PAL720: 1759efe9c7a6SRudolf Cornelissen BT_init_PAL720(); 1760b2459715SRudolf Cornelissen break; 1761fb6cadf1Sshatty } 1762fb6cadf1Sshatty 1763efe9c7a6SRudolf Cornelissen /* modify BT Hphase signal to center TV image... */ 1764efe9c7a6SRudolf Cornelissen BT_setup_hphase(tvmode); 1765fb6cadf1Sshatty 1766efe9c7a6SRudolf Cornelissen /* disable Macro mode */ 1767efe9c7a6SRudolf Cornelissen switch (tvmode) 1768efe9c7a6SRudolf Cornelissen { 1769efe9c7a6SRudolf Cornelissen case NTSC640: 1770efe9c7a6SRudolf Cornelissen case NTSC640_TST: 1771efe9c7a6SRudolf Cornelissen case NTSC800: 1772efe9c7a6SRudolf Cornelissen case NTSC640_OS: 1773efe9c7a6SRudolf Cornelissen case NTSC720: 1774efe9c7a6SRudolf Cornelissen /* NTSC */ 1775efe9c7a6SRudolf Cornelissen BT_set_macro (0, 0); 1776efe9c7a6SRudolf Cornelissen break; 1777efe9c7a6SRudolf Cornelissen default: 1778efe9c7a6SRudolf Cornelissen /* PAL */ 1779efe9c7a6SRudolf Cornelissen BT_set_macro (1, 0); 1780efe9c7a6SRudolf Cornelissen break; 1781efe9c7a6SRudolf Cornelissen } 1782fb6cadf1Sshatty 1783efe9c7a6SRudolf Cornelissen /* setup output signal routing and flickerfilter */ 1784*0c73ffe8SRudolf Cornelissen BT_setup_output(monstat, (uint8)(si->settings.tv_output), ffilter); 1785fb6cadf1Sshatty 178685406c4dSRudolf Cornelissen /* update the GPU CRTC timing for the requested mode */ 178785406c4dSRudolf Cornelissen BT_update_mode_for_gpu(&tv_target, tvmode); 1788fb6cadf1Sshatty 1789efe9c7a6SRudolf Cornelissen /* setup GPU CRTC timing */ 1790b2459715SRudolf Cornelissen head1_set_timing(tv_target); 1791fb6cadf1Sshatty 17925cadaa5fSRudolf Cornelissen //fixme: only testing older cards for now... 17935cadaa5fSRudolf Cornelissen if (si->ps.secondary_head && (si->ps.card_type > NV15)) 1794b0fce481SRudolf Cornelissen { 1795b0fce481SRudolf Cornelissen BT_testsignal(); 1796b0fce481SRudolf Cornelissen return B_OK; 1797b0fce481SRudolf Cornelissen } 1798b0fce481SRudolf Cornelissen 179922a0d15bSRudolf Cornelissen /* now set GPU CRTC to slave mode */ 1800b0fce481SRudolf Cornelissen BT_start_tvout(); 1801efe9c7a6SRudolf Cornelissen 1802efe9c7a6SRudolf Cornelissen //fixme: add code to disable VGA screen when TVout enabled 1803efe9c7a6SRudolf Cornelissen //(use via nv.setting preset) 1804fb6cadf1Sshatty 1805b2459715SRudolf Cornelissen return B_OK; 1806fb6cadf1Sshatty } 1807