#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "ct_driver.h"
static Bool chips_TestI2C(int scrnIndex);
static Bool chips_setI2CBits(I2CBusPtr I2CPtr, ScrnInfoPtr pScrn);
static unsigned int
chips_ddc1Read(ScrnInfoPtr pScrn)
{
unsigned char ddc_mask = ((CHIPSPtr)pScrn->driverPrivate)->ddc_mask;
CHIPSPtr cPtr = CHIPSPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
register unsigned int tmp;
while ((hwp->readST01(hwp)) & 0x08){};
while (!(hwp->readST01(hwp)) & 0x08){};
tmp = cPtr->readXR(cPtr, 0x63);
return (tmp & ddc_mask);
}
void
chips_ddc1(ScrnInfoPtr pScrn)
{
unsigned char FR0B, FR0C, XR62;
unsigned char mask_c = 0x00;
unsigned char val, tmp_val = 0;
int i;
CHIPSPtr cPtr = CHIPSPTR(pScrn);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Probing for DDC1\n");
FR0C = cPtr->readFR(cPtr, 0x0C);
XR62 = cPtr->readXR(cPtr, 0x62);
switch (cPtr->Chipset) {
case CHIPS_CT65550:
cPtr->ddc_mask = 0x1F;
FR0B = cPtr->readFR(cPtr, 0x0B);
if (!(FR0B & 0x10))
cPtr->ddc_mask &= 0xFB;
if (cPtr->Bus == ChipsVLB)
cPtr->ddc_mask &= 0x07;
break;
case CHIPS_CT65554:
case CHIPS_CT65555:
case CHIPS_CT68554:
cPtr->ddc_mask = 0x0F;
break;
case CHIPS_CT69000:
case CHIPS_CT69030:
cPtr->ddc_mask = 0x9F;
break;
default:
cPtr->ddc_mask = 0x0C;
break;
}
if (!(FR0C & 0x80)) {
mask_c |= 0xC0;
cPtr->ddc_mask &= 0xFE;
}
if (!(FR0C & 0x10)) {
mask_c |= 0x18;
cPtr->ddc_mask &= 0xFD;
}
cPtr->writeFR(cPtr, 0x0C, (FR0C & mask_c) | (~mask_c & 0x90));
cPtr->writeXR(cPtr, 0x62, 0x00);
val = chips_ddc1Read(pScrn);
for (i = 0; i < 70; i++) {
tmp_val = chips_ddc1Read(pScrn);
if (tmp_val != val)
break;
}
cPtr->ddc_mask = val ^ tmp_val;
if (cPtr->ddc_mask)
xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DDC1 found\n");
else return;
xf86PrintEDID(xf86DoEDID_DDC1(pScrn->scrnIndex,vgaHWddc1SetSpeed,
chips_ddc1Read));
cPtr->writeFR(cPtr, 0x0C, FR0C);
cPtr->writeXR(cPtr, 0x62, XR62);
}
static void
chips_I2CGetBits(I2CBusPtr b, int *clock, int *data)
{
CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr);
unsigned char FR0C, XR62, val;
FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C);
if (pI2C_c->i2cDataBit & 0x01 || pI2C_c->i2cClockBit & 0x01)
FR0C = (FR0C & 0xE7) | 0x10;
if (pI2C_c->i2cDataBit & 0x02 || pI2C_c->i2cClockBit & 0x02)
FR0C = (FR0C & 0x3F) | 0x80;
XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62);
XR62 &= (~pI2C_c->i2cDataBit) & (~pI2C_c->i2cClockBit);
pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C);
pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62);
val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63);
*clock = (val & pI2C_c->i2cClockBit) != 0;
*data = (val & pI2C_c->i2cDataBit) != 0;
}
static void
chips_I2CPutBits(I2CBusPtr b, int clock, int data)
{
CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr);
unsigned char FR0C, XR62, val;
FR0C = pI2C_c->cPtr->readFR(pI2C_c->cPtr, 0x0C);
if (((pI2C_c->i2cDataBit & 0x01) && data)
|| ((pI2C_c->i2cClockBit & 0x01) && clock))
FR0C |= 0x18;
else if ((pI2C_c->i2cDataBit & 0x01)
|| (pI2C_c->i2cClockBit & 0x01))
FR0C |= 0x10;
if (((pI2C_c->i2cDataBit & 0x02) && data)
|| ((pI2C_c->i2cClockBit & 0x02) && clock))
FR0C |= 0xC0;
else if ((pI2C_c->i2cDataBit & 0x02)
|| (pI2C_c->i2cClockBit & 0x02))
FR0C |= 0x80;
XR62 = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x62);
XR62 = (XR62 & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0);
XR62 = (XR62 & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0);
pI2C_c->cPtr->writeFR(pI2C_c->cPtr, 0x0C, FR0C);
pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x62, XR62);
val = pI2C_c->cPtr->readXR(pI2C_c->cPtr, 0x63);
val = (val & ~pI2C_c->i2cClockBit) | (clock ? pI2C_c->i2cClockBit : 0);
val = (val & ~pI2C_c->i2cDataBit) | (data ? pI2C_c->i2cDataBit : 0);
pI2C_c->cPtr->writeXR(pI2C_c->cPtr, 0x63, val);
}
Bool
chips_i2cInit(ScrnInfoPtr pScrn)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
I2CBusPtr I2CPtr;
I2CPtr = xf86CreateI2CBusRec();
if(!I2CPtr) return FALSE;
cPtr->I2C = I2CPtr;
I2CPtr->BusName = "DDC";
I2CPtr->scrnIndex = pScrn->scrnIndex;
I2CPtr->I2CPutBits = chips_I2CPutBits;
I2CPtr->I2CGetBits = chips_I2CGetBits;
I2CPtr->DriverPrivate.ptr = xalloc(sizeof(CHIPSI2CRec));
((CHIPSI2CPtr)(I2CPtr->DriverPrivate.ptr))->cPtr = cPtr;
if (!xf86I2CBusInit(I2CPtr))
return FALSE;
if (!chips_setI2CBits(I2CPtr, pScrn))
return FALSE;
return TRUE;
}
static Bool
chips_setI2CBits(I2CBusPtr b, ScrnInfoPtr pScrn)
{
CHIPSPtr cPtr = CHIPSPTR(pScrn);
CHIPSI2CPtr pI2C_c = (CHIPSI2CPtr) (b->DriverPrivate.ptr);
unsigned char FR0B, FR0C;
unsigned char bits, data_bits, clock_bits;
int i,j;
FR0C = cPtr->readFR(cPtr, 0x0C);
switch (cPtr->Chipset) {
case CHIPS_CT65550:
bits = 0x1F;
FR0B = cPtr->readFR(cPtr, 0x0B);
if (!(FR0B & 0x10))
bits &= 0xFB;
pI2C_c->i2cDataBit = 0x01;
pI2C_c->i2cClockBit = 0x02;
if (cPtr->Bus == ChipsVLB)
bits &= 0x07;
break;
case CHIPS_CT65554:
case CHIPS_CT65555:
case CHIPS_CT68554:
bits = 0x0F;
pI2C_c->i2cDataBit = 0x04;
pI2C_c->i2cClockBit = 0x08;
break;
case CHIPS_CT69000:
case CHIPS_CT69030:
bits = 0x9F;
pI2C_c->i2cDataBit = 0x04;
pI2C_c->i2cClockBit = 0x08;
break;
default:
bits = 0x0C;
pI2C_c->i2cDataBit = 0x04;
pI2C_c->i2cClockBit = 0x08;
break;
}
if (!(FR0C & 0x80)) {
bits &= 0xFE;
}
if (!(FR0C & 0x10)) {
bits &= 0xFD;
}
pI2C_c->i2cClockBit &= bits;
pI2C_c->i2cDataBit &= bits;
if (chips_TestI2C(pScrn->scrnIndex)) return TRUE;
data_bits = bits;
pI2C_c->i2cDataBit = 0x01;
for (i = 0; i<8; i++) {
if (data_bits & 0x01) {
clock_bits = bits;
pI2C_c->i2cClockBit = 0x01;
for (j = 0; j<8; j++) {
if (clock_bits & 0x01)
if (chips_TestI2C(pScrn->scrnIndex)) return TRUE;
clock_bits >>= 1;
pI2C_c->i2cClockBit <<= 1;
}
}
data_bits >>= 1;
pI2C_c->i2cDataBit <<= 1;
}
return FALSE;
}
static Bool
chips_TestI2C(int scrnIndex)
{
int i;
I2CBusPtr b;
b = xf86I2CFindBus(scrnIndex, "DDC");
if (b == NULL) return FALSE;
else {
for(i = 0xA0; i < 0xA8; i += 2)
if(xf86I2CProbeAddress(b, i))
return TRUE;
}
return FALSE;
}