added via accelerant, a copy of skeleton driver yet.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13604 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,348 @@
|
|||||||
|
/*
|
||||||
|
* i2c interface for the G400 MAVEN under BeOS
|
||||||
|
*
|
||||||
|
* Provides I2CR,I2CW - functions to parallel DACW,DACR
|
||||||
|
* 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-12/2003
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MODULE_BIT 0x00004000
|
||||||
|
|
||||||
|
#include "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);
|
||||||
|
unsigned char i2c_readbyte(int ack_required);
|
||||||
|
|
||||||
|
/*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 result = B_ERROR;
|
||||||
|
|
||||||
|
/* The secondary DDC channel only exist on dualhead cards */
|
||||||
|
if (!si->ps.secondary_head) return result;
|
||||||
|
|
||||||
|
/* make sure the output lines will be active-low when enabled
|
||||||
|
* (they will be pulled 'passive-high' when disabled) */
|
||||||
|
// DXIW(GENIODATA,0x00);
|
||||||
|
/* send out B_STOP condition on secondary head DDC channel and use it to
|
||||||
|
* check for 'shortcut', indicating the Matrox VGA->TV adapter is connected */
|
||||||
|
|
||||||
|
/* make sure SDA is low */
|
||||||
|
// DXIW(GENIOCTRL, (DXIR(GENIOCTRL) | DDC2_DATA));
|
||||||
|
snooze(2);
|
||||||
|
/* make sure SCL should be high */
|
||||||
|
// DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_CLK));
|
||||||
|
snooze(2);
|
||||||
|
/* if SCL is low then the bus is blocked by a TV adapter */
|
||||||
|
// if (!(DXIR(GENIODATA) & DDC2_CLK)) result = B_OK;
|
||||||
|
snooze(5);
|
||||||
|
/* set SDA while SCL should be set (generates actual bus-stop condition) */
|
||||||
|
// DXIW(GENIOCTRL, (DXIR(GENIOCTRL) & ~DDC2_DATA));
|
||||||
|
snooze(5);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char i2c_readbyte(int ack_required)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char data=0;
|
||||||
|
|
||||||
|
/*read data*/
|
||||||
|
i2c_set_lines(0,1);
|
||||||
|
for (i=7; i>=0; i--)
|
||||||
|
{
|
||||||
|
i2c_set_lines(1,1);
|
||||||
|
if (i2c_get_data()==1)
|
||||||
|
data |= (1<<i);
|
||||||
|
i2c_set_lines(0,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*send acknowledge*/
|
||||||
|
if (ack_required) i2c_send_ack();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------
|
||||||
|
*PUBLIC functions
|
||||||
|
*/
|
||||||
|
int i2c_maven_read(unsigned char address)
|
||||||
|
{
|
||||||
|
int error=0;
|
||||||
|
int data;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/*init g400 i2c*/
|
||||||
|
// DXIW(GENIODATA,0x00); /*to zero*/
|
||||||
|
// DXIW(GENIOCTRL,0x30); /*drive clock and data*/
|
||||||
|
// DXIW(GENIOCTRL,0x00); /*stop driving*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user