#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86Pci.h"
#include "xf86PciInfo.h"
#include "vgaHW.h"
#include "via_driver.h"
#define DDC_SDA_READ_MASK (1 << 2)
#define DDC_SCL_READ_MASK (1 << 3)
#define DDC_SDA_WRITE_MASK (1 << 4)
#define DDC_SCL_WRITE_MASK (1 << 5)
static void
VIAI2C1PutBits(I2CBusPtr b, int clock, int data)
{
CARD8 reg;
outb(0x3c4, 0x26);
reg = inb(0x3c5);
reg &= 0xF0;
reg |= 0x01;
if (clock)
reg |= DDC_SCL_WRITE_MASK;
else
reg &= ~DDC_SCL_WRITE_MASK;
if (data)
reg |= DDC_SDA_WRITE_MASK;
else
reg &= ~DDC_SDA_WRITE_MASK;
outb(0x3c4, 0x26);
outb(0x3c5, reg);
}
static void
VIAI2C1GetBits(I2CBusPtr b, int *clock, int *data)
{
CARD8 reg;
outb(0x3c4, 0x26);
reg = inb(0x3c5);
*clock = (reg & DDC_SCL_READ_MASK) != 0;
*data = (reg & DDC_SDA_READ_MASK) != 0;
}
static void
VIAI2C2PutBits(I2CBusPtr b, int clock, int data)
{
CARD8 reg;
outb(0x3c4, 0x31);
reg = inb(0x3c5);
reg &= 0xF0;
reg |= 0x01;
if (clock)
reg |= DDC_SCL_WRITE_MASK;
else
reg &= ~DDC_SCL_WRITE_MASK;
if (data)
reg |= DDC_SDA_WRITE_MASK;
else
reg &= ~DDC_SDA_WRITE_MASK;
outb(0x3c4, 0x31);
outb(0x3c5, reg);
}
static void
VIAI2C2GetBits(I2CBusPtr b, int *clock, int *data)
{
CARD8 reg;
outb(0x3c4, 0x31);
reg = inb(0x3c5);
*clock = (reg & DDC_SCL_READ_MASK) != 0;
*data = (reg & DDC_SDA_READ_MASK) != 0;
}
Bool
VIAI2CInit(ScrnInfoPtr pScrn)
{
VIAPtr pVia = VIAPTR(pScrn);
I2CBusPtr I2CPtr1, I2CPtr2;
I2CPtr1 = xf86CreateI2CBusRec();
I2CPtr2 = xf86CreateI2CBusRec();
if (!I2CPtr1 || !I2CPtr2)
return FALSE;
I2CPtr1->BusName = "I2C bus 1";
I2CPtr1->scrnIndex = pScrn->scrnIndex;
I2CPtr1->I2CPutBits = VIAI2C1PutBits;
I2CPtr1->I2CGetBits = VIAI2C1GetBits;
I2CPtr2->BusName = "I2C bus 2";
I2CPtr2->scrnIndex = pScrn->scrnIndex;
I2CPtr2->I2CPutBits = VIAI2C2PutBits;
I2CPtr2->I2CGetBits = VIAI2C2GetBits;
if (!xf86I2CBusInit(I2CPtr1) || !xf86I2CBusInit(I2CPtr2))
return FALSE;
pVia->I2C_Port1 = I2CPtr1;
pVia->I2C_Port2 = I2CPtr2;
return TRUE;
}
#ifdef _MY_I2C_
static int pcI2CIndex = 0x3c4;
static int pcI2Cport = 0x3c5;
static int gSDA=0;
#if 0
static void I2CUDelay(int usec)
{
long b_secs, b_usecs;
long a_secs, a_usecs;
long d_secs, d_usecs;
long diff;
if (usec > 0) {
xf86getsecs(&b_secs, &b_usecs);
do {
xf86getsecs(&a_secs, &a_usecs);
d_secs = (a_secs - b_secs);
d_usecs = (a_usecs - b_usecs);
diff = d_secs*1000000 + d_usecs;
} while (diff>0 && diff< (usec + 1));
}
}
#endif
void I2C_Enable(int pcIndexReg)
{
int tempI2Cdata, Reg3C4H;
Reg3C4H = inb(pcI2CIndex);
outb(pcI2CIndex, pcIndexReg);
tempI2Cdata = inb(pcI2Cport);
tempI2Cdata |= 0x01;
outb(pcI2Cport, tempI2Cdata);
outb(pcI2CIndex, Reg3C4H);
}
long I2C_reverk(register unsigned data)
{
unsigned long rdata = 0;
int i;
for ( i = 0; i < 16 ; i++ ) {
rdata |= ( data & 1 );
data >>= 1;
rdata <<= 1;
}
return(rdata >> 1);
}
int I2C_ack_pc(int pcIndexReg)
{
int ack;
I2C_regwrit_pc(pcIndexReg, I2C_SDA, 1);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, HICLK);
ack = I2C_regread_pc(pcIndexReg, I2C_SDA);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, LOCLK);
return (ack);
}
void I2C_start_pc(int pcIndexReg)
{
I2C_regwrit_pc(pcIndexReg, I2C_SDA, 1);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, HICLK);
I2C_regwrit_pc(pcIndexReg, I2C_SDA, 0);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, LOCLK);
}
void I2C_stop_pc(int pcIndexReg)
{
I2C_regwrit_pc(pcIndexReg, I2C_SDA, 0);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, HICLK);
I2C_regwrit_pc(pcIndexReg, I2C_SDA, 1);
}
int I2C_wdata_pc(int pcIndexReg, unsigned type , unsigned data)
{
int i;
data = (unsigned int)(I2C_reverk(data) >> 8);
if ( type == I2C_ADR )
I2C_start_pc(pcIndexReg);
for ( i = 0; i < 8; data >>=1, i++ ) {
I2C_regwrit_pc(pcIndexReg, I2C_SDA, data);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, HICLK);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, LOCLK);
}
return I2C_ack_pc(pcIndexReg);
}
void I2C_regwrit_pc(int pcIndexReg, unsigned type, unsigned data )
{
int tempI2Cdata, Reg3C4H;
Reg3C4H = inb(pcI2CIndex);
outb(pcI2CIndex, pcIndexReg);
tempI2Cdata = inb(pcI2Cport);
switch (type) {
case I2C_SCL:
tempI2Cdata &= 0xcf;
tempI2Cdata |= gSDA | ( (data & 1)<< 5);
outb(pcI2Cport, tempI2Cdata);
break;
case I2C_SDA:
tempI2Cdata &= 0xef;
tempI2Cdata |= ( (data & 1) << 4);
outb(pcI2Cport, tempI2Cdata);
gSDA = 0;
gSDA = ( (data & 1) << 4);
break;
}
outb(pcI2CIndex, Reg3C4H);
}
int I2C_regread_pc(int pcIndexReg, unsigned type)
{
int temp=0,Reg3C4H;
Reg3C4H = inb(pcI2CIndex);
switch (type) {
case I2C_SCL :
break;
case I2C_SDA:
outb(pcI2CIndex, pcIndexReg);
temp = ( inb(pcI2Cport) >> 2) & 0x01;
break;
}
outb(pcI2CIndex, Reg3C4H);
return(temp);
}
void I2C_wdata(int pcIndexReg, int addr, int subAddr, int data)
{
int ack = 1;
ack = I2C_wdata_pc(pcIndexReg, I2C_ADR, addr);
ack = I2C_wdata_pc(pcIndexReg, I2C_DAT, subAddr);
ack = I2C_wdata_pc(pcIndexReg, I2C_DAT, data);
I2C_stop_pc(pcIndexReg);
}
int I2C_rdata(int pcIndexReg, int addr, unsigned subAddr)
{
int StatusData =0, data, i;
I2C_wdata_pc(pcIndexReg, I2C_ADR, addr);
I2C_wdata_pc(pcIndexReg, I2C_DAT, subAddr);
I2C_stop_pc(pcIndexReg);
I2C_wdata_pc(pcIndexReg, I2C_ADR, addr+1);
I2C_regwrit_pc(pcIndexReg, I2C_SDA, 1);
for ( i = 0; i <= 7 ; i++ ) {
I2C_regwrit_pc(pcIndexReg, I2C_SCL, HICLK);
data = I2C_regread_pc(pcIndexReg, I2C_SDA);
I2C_regwrit_pc(pcIndexReg, I2C_SCL, LOCLK);
data &= 0x01;
StatusData <<= 1;
StatusData |= data;
}
I2C_stop_pc(pcIndexReg);
return(StatusData);
}
Bool I2C_Write(int pcIndexReg, int addr, unsigned char *WriteBuffer, int nWrite)
{
int s = 0;
int ack = 1;
ack = I2C_wdata_pc(pcIndexReg, I2C_ADR, addr);
if (nWrite > 0) {
for (; nWrite > 0; WriteBuffer++, nWrite--)
ack = I2C_wdata_pc(pcIndexReg, I2C_DAT, *WriteBuffer);
s++;
}
else {
I2C_stop_pc(pcIndexReg);
return (s);
}
I2C_stop_pc(pcIndexReg);
return (s);
}
#endif