xf86-video-intel: Branch 'display-port' - 2 commits - src/i830_dp.c
Keith Packard
keithp at kemper.freedesktop.org
Tue Dec 9 21:52:16 PST 2008
src/i830_dp.c | 502 ++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 389 insertions(+), 113 deletions(-)
New commits:
commit f00d3c35076cd6574fe1d2923d4f2f1a0b7586dc
Author: Keith Packard <keithp at keithp.com>
Date: Mon Dec 8 01:54:50 2008 -0800
Add (broken) DDC support to i830_dp.c
diff --git a/src/i830_dp.c b/src/i830_dp.c
index dd4c493..6a136d1 100644
--- a/src/i830_dp.c
+++ b/src/i830_dp.c
@@ -41,6 +41,9 @@ struct i830_dp_priv {
uint32_t save_DP;
uint8_t save_link_configuration[0x10];
Bool has_audio;
+ uint16_t i2c_address;
+ uint8_t i2c_put_byte;
+ Bool i2c_has_byte;
};
static void
@@ -92,35 +95,38 @@ unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes)
}
static int
-i830_dp_aux_write(ScrnInfoPtr pScrn, uint32_t output_reg,
- uint32_t address, uint8_t *send, int send_bytes)
+i830_dp_aux_ch(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint8_t *send, int send_bytes,
+ uint8_t *recv, int recv_size)
{
I830Ptr pI830 = I830PTR(pScrn);
uint32_t ch_ctl = output_reg + 0x10;
- uint32_t ch_cmd = ch_ctl + 4;
- uint32_t ch_data = ch_ctl + 8;
+ uint32_t ch_data = ch_ctl + 4;
int i;
+ int recv_bytes;
uint32_t ctl;
- uint32_t cmd;
uint32_t status;
- cmd = ((0x8 << 28) |
- (address << 8) |
- (send_bytes));
- OUTREG(ch_cmd, cmd);
- for (i = 0; i < send_bytes; i += 4)
- OUTREG(ch_data + i, pack_aux(send + i, send_bytes - i));
+ for (i = 0; i < send_bytes; i += 4) {
+ uint32_t d = pack_aux(send + i, send_bytes - i);;
+
+// xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+// "aux_ch send[%d] = %08x\n", i/4, d);
+ OUTREG(ch_data + i, d);
+ }
ctl = (DP_AUX_CH_CTL_SEND_BUSY |
DP_AUX_CH_CTL_TIME_OUT_400us |
- ((send_bytes + 4) << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+ (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
(5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
(133 << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
+
OUTREG(ch_ctl, ctl);
for (;;) {
status = INREG(ch_ctl);
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
break;
+ usleep(100);
}
/* Clear done status and any errors */
@@ -136,105 +142,208 @@ i830_dp_aux_write(ScrnInfoPtr pScrn, uint32_t output_reg,
status);
return -1;
}
- return send_bytes;
+ recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
+ DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+
+ if (recv_bytes > recv_size)
+ recv_bytes = recv_size;
+ for (i = 0; i < recv_bytes; i += 4) {
+ uint32_t d = INREG(ch_data + i);
+
+// xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+// "aux_ch recv[%d] = %08x\n", i/4, d);
+ unpack_aux(d, recv + i, recv_bytes - i);
+ }
+
+ return recv_bytes;
}
static int
-i830_dp_aux_write_1(ScrnInfoPtr pScrn, uint32_t output_reg,
- uint32_t address, uint8_t byte)
+i830_dp_aux_native_write(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint16_t address, uint8_t *send, int send_bytes)
{
- return i830_dp_aux_write(pScrn, output_reg, address, &byte, 1);
+ int ret;
+ uint8_t msg[20];
+ int msg_bytes;
+ uint8_t ack;
+
+ assert(send_bytes <= 16);
+ msg[0] = AUX_NATIVE_WRITE << 4;
+ msg[1] = address >> 8;
+ msg[2] = address;
+ msg[3] = send_bytes - 1;
+ memcpy(&msg[4], send, send_bytes);
+ msg_bytes = send_bytes + 4;
+ for (;;) {
+ ret = i830_dp_aux_ch(pScrn, output_reg, msg, msg_bytes, &ack, 1);
+ if (ret < 0)
+ return ret;
+ if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
+ break;
+ else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+ usleep(100);
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "aux ch native write returns %08x\n", ack);
+ return -1;
+ }
+ }
+ return send_bytes;
}
static int
-i830_dp_aux_read(ScrnInfoPtr pScrn, uint32_t output_reg,
- uint32_t address, uint8_t *recv, int recv_bytes)
+i830_dp_aux_native_write_1(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint16_t address, uint8_t byte)
{
- I830Ptr pI830 = I830PTR(pScrn);
- uint32_t ch_ctl = output_reg + 0x10;
- uint32_t ch_cmd = ch_ctl + 4;
- int i;
- uint8_t header[4];
- uint8_t header_bytes;
- uint32_t ctl;
- uint32_t cmd;
- uint32_t status;
- int got_bytes;
- int tries = 0;
+ return i830_dp_aux_native_write(pScrn, output_reg, address, &byte, 1);
+}
- cmd = ((0x9 << 28) |
- (address << 8) |
- (recv_bytes-1));
- ctl = (DP_AUX_CH_CTL_SEND_BUSY |
- DP_AUX_CH_CTL_TIME_OUT_400us |
- (4 << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
- (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
- (133 << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
+static int
+i830_dp_aux_i2c_address(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint16_t address)
+{
+ int ret;
+ uint8_t ack;
+ uint8_t msg[3];
+ int msg_bytes;
+
+ msg[0] = (AUX_I2C_WRITE|AUX_I2C_MOT) << 4;
+ msg[1] = address >> 8;
+ msg[2] = address;
+ msg_bytes = 3;
for (;;) {
- OUTREG(ch_cmd, cmd);
+ ret = i830_dp_aux_ch(pScrn, output_reg, msg, msg_bytes, &ack, 1);
+ if (ret < 0)
+ return ret;
+ if ((ack & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_ACK)
+ break;
+ else if ((ack & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_DEFER)
+ usleep(100);
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "aux ch i2c address returns %02x\n", ack);
+ return -1;
+ }
+ }
+ return 0;
+}
- OUTREG(ch_ctl, ctl);
- for (;;) {
- status = INREG(ch_ctl);
- if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
- break;
+static int
+i830_dp_aux_i2c_write_1(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint16_t address, uint8_t byte, Bool last)
+{
+ int ret;
+ uint8_t ack;
+ uint8_t msg[5];
+ int msg_bytes;
+
+ msg[0] = (AUX_I2C_WRITE) << 4;
+ if (!last)
+ msg[0] |= (AUX_I2C_MOT) << 4;
+ msg[1] = address >> 8;
+ msg[2] = address;
+ msg[3] = 0;
+ msg[4] = byte;
+ msg_bytes = 5;
+ for (;;) {
+ ret = i830_dp_aux_ch(pScrn, output_reg, msg, msg_bytes, &ack, 1);
+ if (ret < 0)
+ return ret;
+ if ((ack & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_ACK)
+ break;
+ else if ((ack & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_DEFER)
+ usleep(100);
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "aux ch i2c write returns %02x\n", ack);
+ return -1;
}
+ }
+ return 1;
+}
- /* Clear done status and any errors */
- OUTREG(ch_ctl, (ctl |
- DP_AUX_CH_CTL_DONE |
- DP_AUX_CH_CTL_TIME_OUT_ERROR |
- DP_AUX_CH_CTL_RECEIVE_ERROR));
+static int
+i830_dp_aux_native_read(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint16_t address, uint8_t *recv, int recv_bytes)
+{
+ uint8_t msg[4];
+ int msg_bytes;
+ uint8_t reply[20];
+ int reply_bytes;
+ uint8_t ack;
+ int ret;
- if ((status & DP_AUX_CH_CTL_DONE) == 0)
- {
+ msg[0] = AUX_NATIVE_READ << 4;
+ msg[1] = address >> 8;
+ msg[2] = address & 0xff;
+ msg[3] = recv_bytes - 1;
+
+ msg_bytes = 4;
+ reply_bytes = recv_bytes + 1;
+
+ for (;;) {
+ ret = i830_dp_aux_ch(pScrn, output_reg, msg, msg_bytes,
+ reply, reply_bytes);
+ if (ret <= 0)
+ return ret;
+ ack = reply[0];
+ if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) {
+ memcpy(recv, reply + 1, ret - 1);
+ return ret - 1;
+ }
+ else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
+ usleep(100);
+ else {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "DisplayPort AUX CH failed to complete: 0x%08x\n",
- status);
+ "aux ch native write returns %08x\n", ack);
return -1;
}
+ }
+}
- got_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
- DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
- if (got_bytes > 20)
- got_bytes = 20;
- if (got_bytes - 1 < recv_bytes)
- recv_bytes = got_bytes - 1;
- if (got_bytes - 1 > recv_bytes)
- {
+static int
+i830_dp_aux_i2c_read_1(ScrnInfoPtr pScrn, uint32_t output_reg,
+ uint16_t address, uint8_t *recv, Bool last)
+{
+ uint8_t msg[4];
+ int msg_bytes;
+ uint8_t reply[2];
+ uint8_t ack;
+ int reply_bytes;
+ int ret;
+
+ msg[0] = AUX_I2C_READ << 4;
+ if (!last)
+ msg[0] |= AUX_I2C_MOT << 4;
+ msg[1] = address >> 8;
+ msg[2] = address;
+ msg[3] = 0;
+ msg_bytes = 4;
+ reply_bytes = 2;
+
+ for (;;) {
+ ret = i830_dp_aux_ch(pScrn, output_reg, msg, msg_bytes,
+ reply, reply_bytes);
+ if (ret <= 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "DisplayPort AUX CH read returns too much: %d > %d\n",
- got_bytes, recv_bytes);
+ "i2c_read: aux_ch error %d\n", ret);
+ return -1;
}
- header_bytes = 4;
- if (recv_bytes + 1 < 4)
- header_bytes = recv_bytes + 1;
- unpack_aux(INREG(ch_cmd), header, header_bytes);
- switch (header[0] & 0x3) {
- case 0:
- break;
- case 1:
- case 3:
+ ack = reply[0];
+ if ((ack & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_ACK) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "DisplayPort AUX CH %d read fails\n", address);
+ "i2c_read: %02x\n", reply[1]);
+ recv[0] = reply[1];
+ return 1;
+ }
+ else if ((ack & AUX_I2C_REPLY_MASK) == AUX_I2C_REPLY_DEFER)
+ usleep(100);
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "aux ch i2c write returns %02x\n", ack);
return -1;
- case 2:
- tries++;
- if (tries > 10) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "DisplayPort AUX CH read %d gave up after %d retries\n",
- address, tries);
- return -1;
- }
- usleep(1000);
- continue;
}
- break;
}
- memcpy(recv, header + 1, header_bytes-1);
- for (i = 4; i < recv_bytes + 1; i += 4)
- unpack_aux(INREG(ch_cmd + i), recv + (i-1), recv_bytes - (i-1));
- return recv_bytes;
}
static void
@@ -295,8 +404,9 @@ i830_dp_lane_status(xf86OutputPtr output, uint8_t lane_status[3])
struct i830_dp_priv *dev_priv = intel_output->dev_priv;
int ret;
- ret = i830_dp_aux_read(pScrn, dev_priv->output_reg, DP_LANE0_1_STATUS,
- lane_status, 3);
+ ret = i830_dp_aux_native_read(pScrn,
+ dev_priv->output_reg, DP_LANE0_1_STATUS,
+ lane_status, 3);
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"lane status(%d) %02x %02x %02x\n",
ret, lane_status[0], lane_status[1], lane_status[2]);
@@ -313,7 +423,7 @@ i830_dp_save(xf86OutputPtr output)
uint8_t lane_status[3];
dev_priv->save_DP = INREG(dev_priv->output_reg);
- i830_dp_aux_read(pScrn, dev_priv->output_reg, 0x100,
+ i830_dp_aux_native_read(pScrn, dev_priv->output_reg, 0x100,
dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"link configuration: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -352,24 +462,27 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
int tries;
int i;
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "i830_dp_link_train dp 0x%08x\n", DP);
if ((DP & DP_PORT_EN) == 0) {
OUTREG(dev_priv->output_reg, DP);
return;
}
DP &= ~DP_LINK_TRAIN_MASK;
- ret = i830_dp_aux_read(pScrn, dev_priv->output_reg,
+ ret = i830_dp_aux_native_read(pScrn, dev_priv->output_reg,
0x206, adjust_request, 2);
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"adjust_request(%d): %02x %02x\n",
ret, adjust_request[0], adjust_request[1]);
/* main link disabled */
- i830_dp_aux_write_1(pScrn, dev_priv->output_reg,
- DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_1);
OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_1);
POSTING_READ(dev_priv->output_reg);
usleep (15*1000);
- ret = i830_dp_aux_read(pScrn, dev_priv->output_reg,
+ i830_dp_aux_native_write_1(pScrn, dev_priv->output_reg,
+ DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_1);
+ usleep (15*1000);
+ ret = i830_dp_aux_native_read(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET,
training, 1);
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -383,7 +496,7 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
tries = 0;
for (i = 0; i < 4; i++) {
- ret = i830_dp_aux_write(pScrn, dev_priv->output_reg,
+ ret = i830_dp_aux_native_write(pScrn, dev_priv->output_reg,
DP_TRAINING_LANE0_SET, train_set, 4);
if (ret != 4) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -407,12 +520,13 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
}
}
/* channel eq pattern */
- i830_dp_aux_write_1(pScrn, dev_priv->output_reg,
- DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_2);
OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_2);
POSTING_READ(dev_priv->output_reg);
+ usleep (15*1000);
+ i830_dp_aux_native_write_1(pScrn, dev_priv->output_reg,
+ DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_2);
usleep(15*1000);
- ret = i830_dp_aux_read(pScrn, dev_priv->output_reg,
+ ret = i830_dp_aux_native_read(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET,
training, 1);
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -420,7 +534,7 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
for (i = 0; i < 4; i++) {
int ret;
- ret = i830_dp_aux_write(pScrn, dev_priv->output_reg,
+ ret = i830_dp_aux_native_write(pScrn, dev_priv->output_reg,
DP_TRAINING_LANE0_SET, train_set, 4);
if (ret != 4) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -445,11 +559,146 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
}
OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_OFF);
POSTING_READ(dev_priv->output_reg);
- i830_dp_aux_write_1(pScrn, dev_priv->output_reg,
+ usleep (15*1000);
+ i830_dp_aux_native_write_1(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE);
usleep (15*1000);
}
+/*
+ * I2C over AUX CH
+ */
+
+static Bool
+i830_dp_i2c_flush(I2CBusPtr bus, Bool last)
+{
+ xf86OutputPtr output = bus->DriverPrivate.ptr;
+ ScrnInfoPtr scrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_dp_priv *dev_priv = intel_output->dev_priv;
+
+ if (dev_priv->i2c_has_byte) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "i2c_flush %02x\n", dev_priv->i2c_put_byte);
+ dev_priv->i2c_has_byte = FALSE;
+ return i830_dp_aux_i2c_write_1(scrn, dev_priv->output_reg,
+ dev_priv->i2c_address,
+ dev_priv->i2c_put_byte, last);
+ }
+ return 0;
+}
+
+static Bool
+i830_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr)
+{
+ I2CBusPtr bus = dev->pI2CBus;
+ xf86OutputPtr output = bus->DriverPrivate.ptr;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_dp_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr scrn = output->scrn;
+
+ if (i830_dp_i2c_flush(bus, TRUE) < 0)
+ return FALSE;
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "i2c_address %04x\n", addr);
+ dev_priv->i2c_address = addr;
+ return i830_dp_aux_i2c_address(scrn, dev_priv->output_reg, addr) >= 0;
+}
+
+static Bool
+i830_dp_i2c_start(I2CBusPtr bus, int timeout)
+{
+ xf86OutputPtr output = bus->DriverPrivate.ptr;
+ ScrnInfoPtr scrn = output->scrn;
+
+ (void) i830_dp_i2c_flush(bus, TRUE);
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "i2c_start %d\n", timeout);
+ return TRUE;
+}
+
+static void
+i830_dp_i2c_stop(I2CDevPtr dev)
+{
+ I2CBusPtr bus = dev->pI2CBus;
+ xf86OutputPtr output = bus->DriverPrivate.ptr;
+ ScrnInfoPtr scrn = output->scrn;
+
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "i2c_stop\n");
+ (void) i830_dp_i2c_flush(bus, TRUE);
+}
+
+static Bool
+i830_dp_i2c_put_byte(I2CDevPtr dev, I2CByte byte)
+{
+ I2CBusPtr bus = dev->pI2CBus;
+ xf86OutputPtr output = bus->DriverPrivate.ptr;
+ ScrnInfoPtr scrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_dp_priv *dev_priv = intel_output->dev_priv;
+
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "i2c_put_byte 0x%x\n", byte);
+ if (i830_dp_i2c_flush(bus, FALSE) < 0)
+ return FALSE;
+ dev_priv->i2c_put_byte = byte;
+ dev_priv->i2c_has_byte = TRUE;
+ return TRUE;
+}
+
+static Bool
+i830_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last)
+{
+ I2CBusPtr bus = dev->pI2CBus;
+ xf86OutputPtr output = bus->DriverPrivate.ptr;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_dp_priv *dev_priv = intel_output->dev_priv;
+ ScrnInfoPtr scrn = output->scrn;
+
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "i2c_get_byte %d\n", last);
+ return i830_dp_aux_i2c_read_1(scrn, dev_priv->output_reg,
+ dev_priv->i2c_address,
+ byte_ret, last) == 1;
+}
+
+
+static Bool
+i830_dp_i2c_init(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr,
+ xf86OutputPtr output, char *name)
+{
+ I2CBusPtr pI2CBus;
+
+ pI2CBus = xf86CreateI2CBusRec();
+
+ if (!pI2CBus)
+ return FALSE;
+
+ pI2CBus->BusName = name;
+ pI2CBus->scrnIndex = pScrn->scrnIndex;
+ pI2CBus->I2CGetByte = i830_dp_i2c_get_byte;
+ pI2CBus->I2CPutByte = i830_dp_i2c_put_byte;
+ pI2CBus->I2CAddress = i830_dp_i2c_address;
+ pI2CBus->I2CStart = i830_dp_i2c_start;
+ pI2CBus->I2CStop = i830_dp_i2c_stop;
+ pI2CBus->DriverPrivate.ptr = output;
+
+ /* Assume all busses are used for DDCish stuff */
+
+ /*
+ * These were set incorrectly in the server pre-1.3, Having
+ * duplicate settings is sub-optimal, but this lets the driver
+ * work with older servers
+ */
+ pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+ pI2CBus->StartTimeout = 550;
+ pI2CBus->BitTimeout = 40;
+ pI2CBus->AcknTimeout = 40;
+ pI2CBus->RiseFallTime = 20;
+
+ if (!xf86I2CBusInit(pI2CBus))
+ return FALSE;
+
+ *bus_ptr = pI2CBus;
+ return TRUE;
+}
+
static void
i830_dp_restore(xf86OutputPtr output)
{
@@ -457,7 +706,7 @@ i830_dp_restore(xf86OutputPtr output)
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_dp_priv *dev_priv = intel_output->dev_priv;
- i830_dp_aux_write(pScrn, dev_priv->output_reg, 0x100,
+ i830_dp_aux_native_write(pScrn, dev_priv->output_reg, 0x100,
dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
i830_dp_link_train(output, dev_priv->save_DP);
}
@@ -574,6 +823,11 @@ i830_dp_init(ScrnInfoPtr pScrn, int output_reg)
struct i830_dp_priv *dev_priv;
uint32_t dp;
uint8_t dpcd[4];
+#if 0
+ uint8_t edid[0x100];
+ int i;
+ int ret;
+#endif
dp = INREG(output_reg);
if ((dp & DP_DETECTED) == 0)
@@ -582,12 +836,23 @@ i830_dp_init(ScrnInfoPtr pScrn, int output_reg)
/* The DP_DETECTED bits are not reliable; see if there's anyone
* home
*/
- if (i830_dp_aux_read(pScrn, output_reg,
+ if (i830_dp_aux_native_read(pScrn, output_reg,
0, dpcd, sizeof (dpcd)) != sizeof (dpcd) ||
(dpcd[0] == 0))
{
return TRUE;
}
+#if 0
+ ret = i830_dp_aux_i2c_address(pScrn, output_reg, 0xa1);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "send EDID address %d\n", ret);
+ for (i = 0; i < 16; i++) {
+ ret = i830_dp_aux_i2c_read_1(pScrn, output_reg,
+ 0xa1, &edid[i], i == 15 ? TRUE : FALSE);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "get(%d) EDID[%d]=%02x\n", ret, i, edid[i]);
+ }
+ return TRUE;
+#endif
+
output = xf86OutputCreate(pScrn, &i830_dp_output_funcs,
(output_reg == DP_B) ? "DP-1" :
(output_reg == DP_C) ? "DP-2" : "DP-3");
@@ -613,17 +878,10 @@ i830_dp_init(ScrnInfoPtr pScrn, int output_reg)
intel_output->clone_mask = (1 << I830_OUTPUT_DISPLAYPORT);
/* Set up the DDC bus. */
- switch (output_reg) {
- case DP_B:
- I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOE, "DPDDC_B");
- break;
- case DP_C:
- I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOF, "DPDDC_C");
- break;
- case DP_D:
- I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOG, "DPDDC_D");
- break;
- }
+ i830_dp_i2c_init(pScrn, &intel_output->pDDCBus, output,
+ (output_reg == DP_B) ? "DPDDC-B" :
+ (output_reg == DP_C) ? "DPDDC-C" : "DPDDC_D");
+
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"DP output %d detected\n",
commit d4824637a80c06a8be36942145388f960041ac56
Author: Keith Packard <keithp at keithp.com>
Date: Sun Dec 7 22:34:15 2008 -0800
Re-train link on dp_restore
Run the link training code when restoring the startup mode. This actually
appears to work too.
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/src/i830_dp.c b/src/i830_dp.c
index 8b6066d..dd4c493 100644
--- a/src/i830_dp.c
+++ b/src/i830_dp.c
@@ -315,6 +315,25 @@ i830_dp_save(xf86OutputPtr output)
dev_priv->save_DP = INREG(dev_priv->output_reg);
i830_dp_aux_read(pScrn, dev_priv->output_reg, 0x100,
dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "link configuration: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ dev_priv->save_link_configuration[0],
+ dev_priv->save_link_configuration[1],
+ dev_priv->save_link_configuration[2],
+ dev_priv->save_link_configuration[3],
+ dev_priv->save_link_configuration[4],
+ dev_priv->save_link_configuration[5],
+ dev_priv->save_link_configuration[6],
+ dev_priv->save_link_configuration[7],
+ dev_priv->save_link_configuration[8],
+ dev_priv->save_link_configuration[9],
+ dev_priv->save_link_configuration[10],
+ dev_priv->save_link_configuration[11],
+ dev_priv->save_link_configuration[12],
+ dev_priv->save_link_configuration[13],
+ dev_priv->save_link_configuration[14],
+ dev_priv->save_link_configuration[15]);
+
i830_dp_lane_status(output, lane_status);
}
@@ -345,10 +364,10 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
"adjust_request(%d): %02x %02x\n",
ret, adjust_request[0], adjust_request[1]);
/* main link disabled */
- OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_1);
- POSTING_READ(dev_priv->output_reg);
i830_dp_aux_write_1(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_1);
+ OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_1);
+ POSTING_READ(dev_priv->output_reg);
usleep (15*1000);
ret = i830_dp_aux_read(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET,
@@ -388,10 +407,10 @@ i830_dp_link_train(xf86OutputPtr output, uint32_t DP)
}
}
/* channel eq pattern */
- OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_2);
- POSTING_READ(dev_priv->output_reg);
i830_dp_aux_write_1(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_2);
+ OUTREG(dev_priv->output_reg, DP | DP_LINK_TRAIN_PAT_2);
+ POSTING_READ(dev_priv->output_reg);
usleep(15*1000);
ret = i830_dp_aux_read(pScrn, dev_priv->output_reg,
DP_TRAINING_PATTERN_SET,
@@ -437,11 +456,10 @@ i830_dp_restore(xf86OutputPtr output)
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_dp_priv *dev_priv = intel_output->dev_priv;
- I830Ptr pI830 = I830PTR(pScrn);
- OUTREG(dev_priv->output_reg, dev_priv->save_DP);
i830_dp_aux_write(pScrn, dev_priv->output_reg, 0x100,
dev_priv->save_link_configuration, sizeof (dev_priv->save_link_configuration));
+ i830_dp_link_train(output, dev_priv->save_DP);
}
/*
More information about the xorg-commit
mailing list