summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-04-25 18:09:10 -0400
committerKristian Høgsberg <krh@redhat.com>2007-04-25 18:09:10 -0400
commit0cd524e5411e35c8483c02ecc5062625809e6fc6 (patch)
treec8374d9424ed2a408f7e5c0303d9787cdf40b030
parent880314aabe6326ed56517034940f0e10fb16e866 (diff)
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.
-rw-r--r--src/i830_dvo.c6
-rw-r--r--src/ivch/ivch.c75
2 files changed, 61 insertions, 20 deletions
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 0bb25bd5..4b37228d 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -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",
diff --git a/src/ivch/ivch.c b/src/ivch/ivch.c
index 71f41f58..efc74f83 100644
--- a/src/ivch/ivch.c
+++ b/src/ivch/ivch.c
@@ -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;
- }
+ 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)) {