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:
parent
880314aabe
commit
0cd524e541
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue