Implement the custom I2C protocol used by the ivch DVO.

The ihch DVO uses a modified I2C addressing scheme as described
in section 5.2 of the data sheet.  Implement this by over-riding
the I2C read and write word routines.
This commit is contained in:
Kristian Høgsberg 2007-04-25 18:09:10 -04:00
parent 880314aabe
commit 0cd524e541
2 changed files with 62 additions and 21 deletions

View File

@ -45,13 +45,11 @@ static const char *CH7xxxSymbols[] = {
"CH7xxxVidOutput",
NULL
};
#if 0
static const char *ivch_symbols[] = {
"ivch_methods",
NULL
};
#endif
#if 0
static const char *ch7017_symbols[] = {
"ch7017_methods",
@ -66,9 +64,9 @@ struct _I830DVODriver i830_dvo_drivers[] =
(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
{I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
/*
{I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
0x04, ivch_symbols, NULL, NULL, NULL},
/*
{I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
0x44, ivch_symbols, NULL, NULL, NULL},
{I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",

View File

@ -60,26 +60,69 @@ ivch_dump_regs(I2CDevPtr d);
static Bool
ivch_read(struct ivch_priv *priv, int addr, CARD16 *data)
{
if (!xf86I2CReadWord(&priv->d, addr, data)) {
xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
"Unable to read register 0x%02x from %s:%d.\n",
addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
return FALSE;
}
return TRUE;
}
I2CBusPtr b = priv->d.pI2CBus;
I2CByte *p = (I2CByte *) data;
if (!b->I2CStart(b, priv->d.StartTimeout))
goto fail;
if (!b->I2CPutByte(&priv->d, priv->d.SlaveAddr | 1))
goto fail;
if (!b->I2CPutByte(&priv->d, addr))
goto fail;
if (!b->I2CGetByte(&priv->d, p++, FALSE))
goto fail;
if (!b->I2CGetByte(&priv->d, p++, TRUE))
goto fail;
b->I2CStop(&priv->d);
return TRUE;
fail:
xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
"ivch: Unable to read register 0x%02x from %s:%02x.\n",
addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
b->I2CStop(&priv->d);
return FALSE;
}
/** Writes a 16-bit register on the ivch */
static Bool
ivch_write(struct ivch_priv *priv, int addr, CARD16 data)
{
if (!xf86I2CWriteWord(&priv->d, addr, data)) {
xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
"Unable to write register 0x%02x to %s:%d.\n",
addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
return FALSE;
}
I2CBusPtr b = priv->d.pI2CBus;
if (!b->I2CStart(b, priv->d.StartTimeout))
goto fail;
if (!b->I2CPutByte(&priv->d, priv->d.SlaveAddr))
goto fail;
if (!b->I2CPutByte(&priv->d, addr))
goto fail;
if (!b->I2CPutByte(&priv->d, data & 0xff))
goto fail;
if (!b->I2CPutByte(&priv->d, data >> 8))
goto fail;
b->I2CStop(&priv->d);
return TRUE;
fail:
b->I2CStop(&priv->d);
xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
"Unable to write register 0x%02x to %s:%d.\n",
addr, priv->d.pI2CBus->BusName, priv->d.SlaveAddr);
return FALSE;
}
/** Probes the given bus and slave address for an ivch */
@ -104,18 +147,18 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
priv->d.ByteTimeout = b->ByteTimeout;
priv->d.DriverPrivate.ptr = priv;
if (!xf86I2CReadWord(&priv->d, VR00, &temp))
if (!ivch_read(priv, VR00, &temp))
goto out;
/* Since the identification bits are probably zeroes, which doesn't seem
* very unique, check that the value in the base address field matches
* the address it's responding on.
*/
if ((temp & VR00_BASE_ADDRESS_MASK) != priv->d.SlaveAddr) {
if ((temp & VR00_BASE_ADDRESS_MASK) != (priv->d.SlaveAddr >> 1)) {
xf86DrvMsg(priv->d.pI2CBus->scrnIndex, X_ERROR,
"ivch detect failed due to address mismatch "
"(%d vs %d)\n",
(temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr);
(temp & VR00_BASE_ADDRESS_MASK), priv->d.SlaveAddr >> 1);
}
if (!xf86I2CDevInit(&priv->d)) {