From 12566cbd0db6d1d6e7dd9623c6642a29c0ed7c36 Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Tue, 27 Sep 2005 14:18:46 +0000 Subject: [PATCH] added brooktree (BT) and conexant (CX) TV encoder recognition, as far as was supported in BeTVOut (BT868/869, CX25870/25871). Tested OK on TNT1 with BT869 on secondary adres, primary bus. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14252 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../nvidia/engine/nv_brooktreetv.c | 162 +++++++++++++++++- .../accelerants/nvidia/engine/nv_general.c | 3 +- .../accelerants/nvidia/engine/nv_i2c.c | 81 +++------ .../accelerants/nvidia/engine/nv_info.c | 18 +- .../accelerants/nvidia/engine/nv_proto.h | 15 +- 5 files changed, 198 insertions(+), 81 deletions(-) diff --git a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c index 2b148c5971..fd98aab3f2 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_brooktreetv.c @@ -1,14 +1,166 @@ -/* Authors: - Mark Watson 2000, - Rudolf Cornelissen 1/2003-12/2003 - - Thanx to Petr Vandrovec for writing matroxfb. +/* + Author: + Rudolf Cornelissen 4/2002-9/2005 */ #define MODULE_BIT 0x00100000 #include "nv_std.h" +#define PRADR 0x88 +#define SCADR 0x8a +#define WR 0x00 +#define RD 0x01 + +/* + see if a (possible) BT/CX chip resides at the given adress. + Return zero if no errors occurred. +*/ +static uint8 BT_check (uint8 bus, uint8 adress) +{ + /* reset status */ + i2c_flag_error (-1); + + /* do check */ + i2c_bstart(bus); + i2c_writebyte(bus, adress + WR); + /* set ESTATUS at b'00'; and enable bt chip-outputs + * WARNING: + * If bit0 = 0 is issued below (EN_OUT = disabled), the BT will lock SDA + * after writing adress $A0 (setting EN_XCLK)!!! + * Until a reboot the corresponding IIC bus will be inacessable then!!! */ + i2c_writebyte(bus, 0xc4); + /* fixme: if testimage 'was' active txbuffer[3] should become 0x05... + * (currently this cannot be detected in a 'foolproof' way so don't touch...) */ + /* (ESTATUS b'0x' means: RX ID and VERSION info later..) */ + i2c_writebyte(bus, 0x01); + i2c_bstop(bus); + return i2c_flag_error(0); +} + +/* identify chiptype */ +static uint8 BT_read_type (void) +{ + uint8 id, stat; + + /* reset status */ + i2c_flag_error (-1); + +//fixme: setup higher level static I2C routines in this file. + /* Make sure a CX (Conexant) chip (if this turns out to be there) is set to + * BT-compatibility mode! (This command will do nothing on a BT chip...) */ + i2c_bstart(si->ps.tv_encoder.bus); + i2c_writebyte(si->ps.tv_encoder.bus, si->ps.tv_encoder.adress + WR); + /* select CX reg. for BT-compatible readback, video still off */ + i2c_writebyte(si->ps.tv_encoder.bus, 0x6c); + /* set it up */ + i2c_writebyte(si->ps.tv_encoder.bus, 0x02); + i2c_bstop(si->ps.tv_encoder.bus); + /* abort on errors */ + stat = i2c_flag_error(0); + if (stat) return stat; + + /* Do actual readtype command */ + i2c_bstart(si->ps.tv_encoder.bus); + /* issue IIC read command */ + i2c_writebyte(si->ps.tv_encoder.bus, si->ps.tv_encoder.adress + RD); + /* receive 1 byte; + * ACK level to TX after last byte to RX should be 1 (= NACK) (see IIC spec). */ + /* note: + * While the BT's don't care, CX chips will block the SDA line if + * an ACK gets sent! */ + id = i2c_readbyte(si->ps.tv_encoder.bus, true); + i2c_bstop(si->ps.tv_encoder.bus); + /* abort on errors */ + stat = i2c_flag_error(0); + if (stat) return stat; + + /* inform driver about TV encoder found */ + si->ps.tvout = true; + si->ps.tv_encoder.type = BT868 + ((id & 0xe0) >> 5); + si->ps.tv_encoder.version = id & 0x1f; + + return stat; +} + +bool BT_probe() +{ + bool btfound = false; + + LOG(4,("Brooktree: Checking IIC bus(ses) for first possible TV encoder...\n")); + if (si->ps.i2c_bus0) + { + /* try primary adress on bus 0 */ + if (!BT_check(0, PRADR)) + { + btfound = true; + si->ps.tv_encoder.adress = PRADR; + si->ps.tv_encoder.bus = 0; + } + else + { + /* try secondary adress on bus 0 */ + if (!BT_check(0, SCADR)) + { + btfound = true; + si->ps.tv_encoder.adress = SCADR; + si->ps.tv_encoder.bus = 0; + } + } + } + + if (si->ps.i2c_bus1 && !btfound) + { + /* try primary adress on bus 1 */ + if (!BT_check(1, PRADR)) + { + btfound = true; + si->ps.tv_encoder.adress = PRADR; + si->ps.tv_encoder.bus = 1; + } + else + { + /* try secondary adress on bus 1 */ + if (!BT_check(1, SCADR)) + { + btfound = true; + si->ps.tv_encoder.adress = SCADR; + si->ps.tv_encoder.bus = 1; + } + } + } + + /* identify exact TV encoder type */ + if (btfound) + { + /* if errors are found, retry */ + /* note: + * NACK: occurs on some ASUS V7700 GeForce cards! + * (apparantly the video-in chip or another chip resides at 'BT' adresses + * there..) */ + uint8 stat; + uint8 cnt = 0; + while ((stat = BT_read_type()) && (cnt < 3)) + { + cnt++; + } + if (stat) + { + LOG(4,("Brooktree: too much errors occurred, aborting.\n")); + btfound = 0; + } + } + + if (btfound) + LOG(4,("Brooktree: Found TV encoder on bus %d, adress $%02x\n", + si->ps.tv_encoder.bus, si->ps.tv_encoder.adress)); + else + LOG(4,("Brooktree: No TV encoder Found\n")); + + return btfound; +} + +//matrox old stuff.. typedef struct { uint32 h_total; uint32 h_display; diff --git a/src/add-ons/accelerants/nvidia/engine/nv_general.c b/src/add-ons/accelerants/nvidia/engine/nv_general.c index e9df2a68b3..827a963093 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_general.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_general.c @@ -1107,7 +1107,8 @@ static status_t nvxx_general_powerup() unlock_card(); - /* get RAM size and fake panel startup (panel init code is still missing) */ + /* get RAM size, detect TV encoder and do fake panel startup (panel init code + * is still missing). */ fake_panel_start(); /* log the final card specifications */ diff --git a/src/add-ons/accelerants/nvidia/engine/nv_i2c.c b/src/add-ons/accelerants/nvidia/engine/nv_i2c.c index c6e8cbf23a..3594629d6b 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_i2c.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_i2c.c @@ -38,8 +38,9 @@ status_t i2c_sec_tv_adapter() return result; } -static char FlagIICError (char ErrNo) +char i2c_flag_error (char ErrNo) //error code list: +//0 - OK status //1 - SCL locked low by device (bus is still busy) //2 - SDA locked low by device (bus is still busy) //3 - No Acknowledge from device (no handshake) @@ -131,7 +132,7 @@ static void TXBit (uint8 BusNR, bool Bit) { OutSDA(BusNR, true); snooze(3); - if (!InSDA(BusNR)) FlagIICError (2); + if (!InSDA(BusNR)) i2c_flag_error (2); } else { @@ -141,7 +142,7 @@ static void TXBit (uint8 BusNR, bool Bit) snooze(6); OutSCL(BusNR, true); snooze(3); - if (!InSCL(BusNR)) FlagIICError (1); + if (!InSCL(BusNR)) i2c_flag_error (1); snooze(6); OutSCL(BusNR, false); snooze(6); @@ -157,7 +158,7 @@ static uint8 RXBit (uint8 BusNR) snooze(6); OutSCL(BusNR, true); snooze(3); - if (!InSCL(BusNR)) FlagIICError (1); + if (!InSCL(BusNR)) i2c_flag_error (1); snooze(3); /* read databit */ if (InSDA(BusNR)) Bit = 1; @@ -168,14 +169,14 @@ static uint8 RXBit (uint8 BusNR) return Bit; } -static void bstart (uint8 BusNR) +void i2c_bstart (uint8 BusNR) { /* make sure SDA is high */ OutSDA(BusNR, true); snooze(3); OutSCL(BusNR, true); snooze(3); - if (!InSCL(BusNR)) FlagIICError (1); + if (!InSCL(BusNR)) i2c_flag_error (1); snooze(6); /* clear SDA while SCL set (bus-start condition) */ OutSDA(BusNR, false); @@ -184,29 +185,29 @@ static void bstart (uint8 BusNR) snooze(6); LOG(4,("I2C: START condition generated on bus %d; status is %d\n", - BusNR, FlagIICError (0))); + BusNR, i2c_flag_error (0))); } -static void bstop (uint8 BusNR) +void i2c_bstop (uint8 BusNR) { /* make sure SDA is low */ OutSDA(BusNR, false); snooze(3); OutSCL(BusNR, true); snooze(3); - if (!InSCL(BusNR)) FlagIICError (1); + if (!InSCL(BusNR)) i2c_flag_error (1); snooze(6); /* set SDA while SCL set (bus-stop condition) */ OutSDA(BusNR, true); snooze(3); - if (!InSDA(BusNR)) FlagIICError (4); + if (!InSDA(BusNR)) i2c_flag_error (4); snooze(3); LOG(4,("I2C: STOP condition generated on bus %d; status is %d\n", - BusNR, FlagIICError (0))); + BusNR, i2c_flag_error (0))); } -static uint8 i2c_readbyte(uint8 BusNR, bool Ack) +uint8 i2c_readbyte(uint8 BusNR, bool Ack) { uint8 cnt, bit, byte = 0; @@ -224,15 +225,16 @@ static uint8 i2c_readbyte(uint8 BusNR, bool Ack) TXBit (BusNR, Ack); LOG(4,("I2C: read byte ($%02x) from bus #%d; status is %d\n", - byte, BusNR, FlagIICError(0))); + byte, BusNR, i2c_flag_error(0))); return byte; } -static bool i2c_writebyte (uint8 BusNR, uint8 byte) +bool i2c_writebyte (uint8 BusNR, uint8 byte) { uint8 cnt; bool bit; + uint8 tmp = byte; /* enable access to primary head */ set_crtc_owner(0); @@ -240,55 +242,19 @@ static bool i2c_writebyte (uint8 BusNR, uint8 byte) /* write data */ for (cnt = 8; cnt > 0; cnt--) { - bit = (byte & 0x80); + bit = (tmp & 0x80); TXBit (BusNR, bit); - byte <<= 1; + tmp <<= 1; } /* read acknowledge */ bit = RXBit (BusNR); - if (bit) FlagIICError (3); + if (bit) i2c_flag_error (3); LOG(4,("I2C: written byte ($%02x) to bus #%d; status is %d\n", - byte, BusNR, FlagIICError(0))); + byte, BusNR, i2c_flag_error(0))); return bit; } -//end rud. - -/*------------------------------------------- - *PUBLIC functions - */ -int i2c_maven_read(unsigned char address) -{ - int error=0; - int data=0; -/* - i2c_start(); - { - error+=i2c_sendbyte(MAVEN_READ); - error+=i2c_sendbyte(address); -// data = i2c_readbyte(0); - } - i2c_stop(); -*/ - if (error>0) LOG(8,("I2C: MAVR ERROR - %x\n",error)); - return data; -} - -void i2c_maven_write(unsigned char address, unsigned char data) -{ - int error=0; -/* - i2c_start(); - { - error+=i2c_sendbyte(MAVEN_WRITE); - error+=i2c_sendbyte(address); - error+=i2c_sendbyte(data); - } - i2c_stop(); -*/ - if (error>0) LOG(8,("I2C: MAVW ERROR - %x\n",error)); -} status_t i2c_init(void) { @@ -305,10 +271,10 @@ status_t i2c_init(void) for (bus = 0; bus < 2; bus++) { /* reset status */ - FlagIICError (-1); + i2c_flag_error (-1); snooze(6); /* init and/or stop I2C bus */ - bstop(bus); + i2c_bstop(bus); /* check for hardware coupling of SCL and SDA -out and -in lines */ snooze(6); OutSCL(bus, false); @@ -323,7 +289,7 @@ status_t i2c_init(void) i2c_bus[bus] = true; snooze(3); /* re-init bus */ - bstop(bus); + i2c_bstop(bus); } for (bus = 0; bus < 2; bus++) @@ -334,5 +300,6 @@ status_t i2c_init(void) LOG(4,("I2C: bus #%d wiring check: failed\n", bus)); } + if (!si->ps.i2c_bus0 && !si->ps.i2c_bus1) return B_ERROR; return B_OK; } diff --git a/src/add-ons/accelerants/nvidia/engine/nv_info.c b/src/add-ons/accelerants/nvidia/engine/nv_info.c index 2c1b3b5823..4202b117e6 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_info.c +++ b/src/add-ons/accelerants/nvidia/engine/nv_info.c @@ -2129,16 +2129,11 @@ void fake_panel_start(void) /* find out if the card has a tvout chip */ si->ps.tvout = false; - si->ps.tvout_chip_type = NONE; -//fixme ;-) + si->ps.tv_encoder.type = NONE; + si->ps.tv_encoder.version = 0; i2c_init(); -/* if (i2c_maven_probe() == B_OK) - { - si->ps.tvout = true; - si->ps.tvout_chip_bus = ???; - si->ps.tvout_chip_type = ???; - } -*/ + //fixme: add support for more encoders... + BT_probe(); LOG(8,("INFO: faking panel startup\n")); @@ -3149,7 +3144,7 @@ void dump_pins(void) LOG(2,("tvout: ")); if (si->ps.tvout) LOG(2,("present\n")); else LOG(2,("absent\n")); /* setup TVout logmessage text */ - switch (si->ps.tvout_chip_type) + switch (si->ps.tv_encoder.type) { case NONE: msg = "No"; @@ -3203,7 +3198,8 @@ void dump_pins(void) msg = "Unknown"; break; } - LOG(2, ("%s TVout chip detected\n", msg)); + LOG(2, ("%s TV encoder detected; silicon revision is $%02x\n", + msg, si->ps.tv_encoder.version)); // LOG(2,("primary_dvi: ")); // if (si->ps.primary_dvi) LOG(2,("present\n")); else LOG(2,("absent\n")); // LOG(2,("secondary_dvi: ")); diff --git a/src/add-ons/accelerants/nvidia/engine/nv_proto.h b/src/add-ons/accelerants/nvidia/engine/nv_proto.h index afe6bf25fc..bff39ab765 100644 --- a/src/add-ons/accelerants/nvidia/engine/nv_proto.h +++ b/src/add-ons/accelerants/nvidia/engine/nv_proto.h @@ -26,10 +26,13 @@ void delay(bigtime_t i); void nv_log(char *format, ...); /* i2c functions */ -int i2c_maven_read(unsigned char address); -void i2c_maven_write(unsigned char address, unsigned char data); +status_t i2c_sec_tv_adapter(void); +char i2c_flag_error (char ErrNo); +void i2c_bstart (uint8 BusNR); +void i2c_bstop (uint8 BusNR); +uint8 i2c_readbyte(uint8 BusNR, bool Ack); +bool i2c_writebyte (uint8 BusNR, uint8 byte); status_t i2c_init(void); -status_t i2c_maven_probe(void); /* card info functions */ status_t parse_pins(void); @@ -53,7 +56,8 @@ status_t nv_dac2_palette(uint8*,uint8*,uint8*); status_t nv_dac2_pix_pll_find(display_mode target,float * result,uint8 *,uint8 *,uint8 *, uint8); status_t nv_dac2_set_pix_pll(display_mode target); -/*MAVENTV functions*/ +/* Brooktree TV functions */ +bool BT_probe(void); status_t g100_g400max_maventv_vid_pll_find( display_mode target, unsigned int * ht_new, unsigned int * ht_last_line, uint8 * m_result, uint8 * n_result, uint8 * p_result); @@ -134,9 +138,6 @@ status_t nv_configure_bes (const overlay_buffer *ob, const overlay_window *ow,const overlay_view *ov, int offset); status_t nv_release_bes(void); -/* I2C functions */ -status_t i2c_sec_tv_adapter(void); - /* driver structures and enums */ enum{BPP8 = 0, BPP15 = 1, BPP16 = 2, BPP24 = 3, BPP32 = 4}; enum{DS_CRTC1DAC_CRTC2MAVEN, DS_CRTC1MAVEN_CRTC2DAC, DS_CRTC1CON1_CRTC2CON2, DS_CRTC1CON2_CRTC2CON1};