diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-04-25 18:09:10 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@redhat.com> | 2007-04-25 18:09:10 -0400 |
commit | 0cd524e5411e35c8483c02ecc5062625809e6fc6 (patch) | |
tree | c8374d9424ed2a408f7e5c0303d9787cdf40b030 | |
parent | 880314aabe6326ed56517034940f0e10fb16e866 (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.c | 6 | ||||
-rw-r--r-- | src/ivch/ivch.c | 75 |
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)) { |