added I2C bus wiring checks, and bumped version to 0.54. Note: the driver is tested on TNT1, the new code has not been tested for newer cards yet. Note also: the driver is now nolonger binary compatible with the 3D add-on alpha2, 2.5 and 3 (modified driverinterface).

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14249 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rudolf Cornelissen
2005-09-27 10:25:49 +00:00
parent a5c04ff3a5
commit 15b4879f71
3 changed files with 70 additions and 265 deletions
@@ -1,7 +1,7 @@
/* Authors: /* Authors:
Mark Watson 12/1999, Mark Watson 12/1999,
Apsed, Apsed,
Rudolf Cornelissen 10/2002-6/2005 Rudolf Cornelissen 10/2002-9/2005
*/ */
#define MODULE_BIT 0x00008000 #define MODULE_BIT 0x00008000
@@ -10,6 +10,7 @@
static status_t test_ram(void); static status_t test_ram(void);
static status_t nvxx_general_powerup (void); static status_t nvxx_general_powerup (void);
static void unlock_card(void);
static status_t nv_general_bios_to_powergraphics(void); static status_t nv_general_bios_to_powergraphics(void);
static void nv_dump_configuration_space (void) static void nv_dump_configuration_space (void)
@@ -90,7 +91,7 @@ status_t nv_general_powerup()
{ {
status_t status; status_t status;
LOG(1,("POWERUP: Haiku nVidia Accelerant 0.53 running.\n")); LOG(1,("POWERUP: Haiku nVidia Accelerant 0.54 running.\n"));
/* preset no laptop */ /* preset no laptop */
si->ps.laptop = false; si->ps.laptop = false;
@@ -1104,6 +1105,8 @@ static status_t nvxx_general_powerup()
LOG(2, ("INIT: Skipping card coldstart!\n")); LOG(2, ("INIT: Skipping card coldstart!\n"));
} }
unlock_card();
/* get RAM size and fake panel startup (panel init code is still missing) */ /* get RAM size and fake panel startup (panel init code is still missing) */
fake_panel_start(); fake_panel_start();
@@ -1195,14 +1198,8 @@ status_t nv_general_head_select(bool cross)
} }
} }
/* basic change of card state from VGA to enhanced mode: static void unlock_card(void)
* Should work from VGA BIOS POST init state. */
static status_t nv_general_bios_to_powergraphics()
{ {
/* let acc engine make power off/power on cycle to start 'fresh' */
NV_REG32(NV32_PWRUPCTRL) = 0x13110011;
snooze(1000);
/* power-up all nvidia hardware function blocks */ /* power-up all nvidia hardware function blocks */
/* bit 28: OVERLAY ENGINE (BES), /* bit 28: OVERLAY ENGINE (BES),
* bit 25: CRTC2, (> NV04A) * bit 25: CRTC2, (> NV04A)
@@ -1231,6 +1228,18 @@ static status_t nv_general_bios_to_powergraphics()
CRTC2W(LOCK, 0x57); CRTC2W(LOCK, 0x57);
CRTC2W(VSYNCE ,(CRTCR(VSYNCE) & 0x7f)); CRTC2W(VSYNCE ,(CRTCR(VSYNCE) & 0x7f));
} }
}
/* basic change of card state from VGA to enhanced mode:
* Should work from VGA BIOS POST init state. */
static status_t nv_general_bios_to_powergraphics()
{
/* let acc engine make power off/power on cycle to start 'fresh' */
NV_REG32(NV32_PWRUPCTRL) = 0x13110011;
snooze(1000);
NV_REG32(NV32_PWRUPCTRL) = 0x13111111;
unlock_card();
/* turn off both displays and the hardcursors (also disables transfers) */ /* turn off both displays and the hardcursors (also disables transfers) */
head1_dpms(false, false, false); head1_dpms(false, false, false);
+50 -255
View File
@@ -1,14 +1,7 @@
/* /*
* i2c interface for the G400 MAVEN under BeOS * i2c interface.
*
* Provides I2CR,I2CW - functions to parallel DACW,DACR
* Bus should be run at max. 100kHz: see original Philips I2C specification * Bus should be run at max. 100kHz: see original Philips I2C specification
* *
* Much help was provided by observing the Linux i2c code,
* so thanks go to: Gerd Knorr
*
* Other authors:
* Mark Watson 6/2000,
* Rudolf Cornelissen 12/2002-9/2005 * Rudolf Cornelissen 12/2002-9/2005
*/ */
@@ -16,36 +9,6 @@
#include "nv_std.h" #include "nv_std.h"
int i2c_set_lines(int clock, int data);
int i2c_get_data(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_high(void);
void i2c_low(void);
int i2c_get_ack(void);
void i2c_send_ack(void);
int i2c_sendbyte(unsigned char data);
/*which device on the bus is the MAVEN?*/
#define MAVEN_WRITE (0x1B<<1)
#define MAVEN_READ ((0x1B<<1)|1)
#define I2C_CLOCK 0x20
#define I2C_DATA 0x10
/* NV-TVO I2C for G200, G400 */
#define I2C_CLOCK 0x20
#define I2C_DATA 0x10
/* primary head DDC for Mystique(?), G100, G200, G400 */
#define DDC1_CLK 0x08
#define DDC1_DATA 0x02
/* primary head DDC for Millennium, Millennium II */
#define DDC1B_CLK 0x10
#define DDC1B_DATA 0x04
/* secondary head DDC for G400, G450 and G550 */
#define DDC2_CLK 0x04
#define DDC2_DATA 0x01
status_t i2c_sec_tv_adapter() status_t i2c_sec_tv_adapter()
{ {
status_t result = B_ERROR; status_t result = B_ERROR;
@@ -75,194 +38,6 @@ status_t i2c_sec_tv_adapter()
return result; return result;
} }
/*-----------------------------
*low level hardware access
*/
#define I2C_DELAY 2
#define I2C_TIMEOUT 100
int i2c_set_lines(int clock,int data)
{
int count=0;
int program;
int required;
/*work out which bits to zero*/
program =
(clock ? 0 : I2C_CLOCK)|
(data ? 0 : I2C_DATA);
/*what value do I require on data lines*/
required =
(clock ? I2C_CLOCK : 0);
/*set the bits to zero*/
// DXIW(GENIOCTRL,program); /*drive these bits*/
// DXIW(GENIODATA,0x00); /*to zero*/
/*wait a bit*/
delay(I2C_DELAY);
/*loop until the clock is as required*/
// while ((DXIR(GENIODATA)&I2C_CLOCK)!=required)
{
delay(I2C_DELAY);
count++;
if (count>I2C_TIMEOUT)
{
// LOG(8,("I2C: Timeout on set lines - clock:%d data:%d actual:%x\n",clock,data,DXIR(GENIODATA)));
return -1;
}
}
return 0;
}
int i2c_get_data()
{
int data = 0;
int clock;
int count=0;
do
{
/*read the data and clock lines*/
// data = DXIR(GENIODATA);
clock = (data&I2C_CLOCK) ? 1 : 0;
data = (data&I2C_DATA) ? 1 : 0;
/*manage timeout*/
count++;
if (count>I2C_TIMEOUT)
{
return -1;
}
/*wait a bit, so not hammering bus*/
delay(I2C_DELAY);
}while (!clock); /*wait for high clock*/
return data;
}
/*-----------------------
*Standard I2C operations
*/
void i2c_start()
{
int error=0;
error+= i2c_set_lines(0,1);
error+= i2c_set_lines(1,1);
error+= i2c_set_lines(1,0);
error+= i2c_set_lines(0,0);
if (error)
{
LOG(8,("I2C: start - %d\n",error));
}
}
void i2c_stop()
{
int error=0;
error+= i2c_set_lines(0,0);
error+= i2c_set_lines(1,0);
error+= i2c_set_lines(1,1);
error+= i2c_set_lines(0,1);
if (error)
{
LOG(8,("I2C: stop - %d\n",error));
}
}
void i2c_high()
{
int error=0;
error+= i2c_set_lines(0,1);
error+= i2c_set_lines(1,1);
error+= i2c_set_lines(0,1);
if (error)
{
LOG(8,("I2C: high - %d\n",error));
}
}
void i2c_low()
{
int error=0;
error+= i2c_set_lines(0,0);
error+= i2c_set_lines(1,0);
error+= i2c_set_lines(0,0);
if (error)
{
LOG(8,("I2C: low - %d\n",error));
}
}
int i2c_get_ack()
{
int error=0;
int ack;
error+= i2c_set_lines(0,1);
error+= i2c_set_lines(1,1);
ack = i2c_get_data();
error+= i2c_set_lines(0,1);
if (error)
{
LOG(8,("I2C: get_ack - %d value:%x\n",error,ack));
}
return ack;
}
void i2c_send_ack()
{
int error=0;
error+= i2c_set_lines(0,0);
error+= i2c_set_lines(1,0);
error+= i2c_set_lines(0,0);
if (error)
{
LOG(8,("I2C: send_ack - %d\n",error));
}
}
/*------------------------------
*use above functions to send and receive bytes
*/
int i2c_sendbyte(unsigned char data)
{
int i;
for (i=7; i>=0; i--)
{
if (data&(1<<i))
{
i2c_high();
}
else
{
i2c_low();
}
}
return i2c_get_ack();
}
//rud's betvout:
static char FlagIICError (char ErrNo) static char FlagIICError (char ErrNo)
//error code list: //error code list:
//1 - SCL locked low by device (bus is still busy) //1 - SCL locked low by device (bus is still busy)
@@ -408,7 +183,8 @@ static void bstart (uint8 BusNR)
OutSCL(BusNR, false); OutSCL(BusNR, false);
snooze(6); snooze(6);
LOG(4,("I2C: START condition generated on bus %d.\n", BusNR)); LOG(4,("I2C: START condition generated on bus %d; status is %d\n",
BusNR, FlagIICError (0)));
} }
static void bstop (uint8 BusNR) static void bstop (uint8 BusNR)
@@ -426,7 +202,8 @@ static void bstop (uint8 BusNR)
if (!InSDA(BusNR)) FlagIICError (4); if (!InSDA(BusNR)) FlagIICError (4);
snooze(3); snooze(3);
LOG(4,("I2C: STOP condition generated on bus %d.\n", BusNR)); LOG(4,("I2C: STOP condition generated on bus %d; status is %d\n",
BusNR, FlagIICError (0)));
} }
static uint8 i2c_readbyte(uint8 BusNR, bool Ack) static uint8 i2c_readbyte(uint8 BusNR, bool Ack)
@@ -476,7 +253,6 @@ static bool i2c_writebyte (uint8 BusNR, uint8 byte)
return bit; return bit;
} }
//end rud. //end rud.
/*------------------------------------------- /*-------------------------------------------
@@ -486,7 +262,7 @@ int i2c_maven_read(unsigned char address)
{ {
int error=0; int error=0;
int data=0; int data=0;
/*
i2c_start(); i2c_start();
{ {
error+=i2c_sendbyte(MAVEN_READ); error+=i2c_sendbyte(MAVEN_READ);
@@ -494,6 +270,7 @@ int i2c_maven_read(unsigned char address)
// data = i2c_readbyte(0); // data = i2c_readbyte(0);
} }
i2c_stop(); i2c_stop();
*/
if (error>0) LOG(8,("I2C: MAVR ERROR - %x\n",error)); if (error>0) LOG(8,("I2C: MAVR ERROR - %x\n",error));
return data; return data;
} }
@@ -501,7 +278,7 @@ int i2c_maven_read(unsigned char address)
void i2c_maven_write(unsigned char address, unsigned char data) void i2c_maven_write(unsigned char address, unsigned char data)
{ {
int error=0; int error=0;
/*
i2c_start(); i2c_start();
{ {
error+=i2c_sendbyte(MAVEN_WRITE); error+=i2c_sendbyte(MAVEN_WRITE);
@@ -509,35 +286,53 @@ void i2c_maven_write(unsigned char address, unsigned char data)
error+=i2c_sendbyte(data); error+=i2c_sendbyte(data);
} }
i2c_stop(); i2c_stop();
*/
if (error>0) LOG(8,("I2C: MAVW ERROR - %x\n",error)); if (error>0) LOG(8,("I2C: MAVW ERROR - %x\n",error));
} }
status_t i2c_init(void) status_t i2c_init(void)
{ {
/*init g400 i2c*/ uint8 bus;
// DXIW(GENIODATA,0x00); /*to zero*/ bool *i2c_bus = &(si->ps.i2c_bus0);
// DXIW(GENIOCTRL,0x30); /*drive clock and data*/
// DXIW(GENIOCTRL,0x00); /*stop driving*/ LOG(4,("I2C: searching for wired I2C buses...\n"));
/* preset no board wired buses */
si->ps.i2c_bus0 = false;
si->ps.i2c_bus1 = false;
/* find existing buses */
for (bus = 0; bus < 2; bus++)
{
/* reset status */
FlagIICError (-1);
snooze(6);
/* init and/or stop I2C bus */
bstop(bus);
/* check for hardware coupling of SCL and SDA -out and -in lines */
snooze(6);
OutSCL(bus, false);
OutSDA(bus, true);
snooze(3);
if (InSCL(bus) || !InSDA(bus)) continue;
snooze(3);
OutSCL(bus, true);
OutSDA(bus, false);
snooze(3);
if (!InSCL(bus) || InSDA(bus)) continue;
i2c_bus[bus] = true;
snooze(3);
/* re-init bus */
bstop(bus);
}
for (bus = 0; bus < 2; bus++)
{
if (i2c_bus[bus])
LOG(4,("I2C: bus #%d wiring check: passed\n", bus));
else
LOG(4,("I2C: bus #%d wiring check: failed\n", bus));
}
return B_OK; return B_OK;
} }
status_t i2c_maven_probe(void)
{
int ack;
/*scan the bus for the MAVEN*/
i2c_start();
{
ack = i2c_sendbyte(MAVEN_READ);
}
i2c_stop();
if (ack==0)
{
return B_OK;
}
else
{
return B_ERROR;
}
}
@@ -1,7 +1,7 @@
/* Read initialisation information from card */ /* Read initialisation information from card */
/* some bits are hacks, where PINS is not known */ /* some bits are hacks, where PINS is not known */
/* Author: /* Author:
Rudolf Cornelissen 7/2003-6/2005 Rudolf Cornelissen 7/2003-9/2005
*/ */
#define MODULE_BIT 0x00002000 #define MODULE_BIT 0x00002000
@@ -2131,6 +2131,7 @@ void fake_panel_start(void)
si->ps.tvout = false; si->ps.tvout = false;
si->ps.tvout_chip_type = NONE; si->ps.tvout_chip_type = NONE;
//fixme ;-) //fixme ;-)
i2c_init();
/* if (i2c_maven_probe() == B_OK) /* if (i2c_maven_probe() == B_OK)
{ {
si->ps.tvout = true; si->ps.tvout = true;