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