xf86-video-intel: Branch 'modesetting' - 3 commits - src/i810_reg.h src/i830_i2c.c

Eric Anholt anholt at kemper.freedesktop.org
Fri Dec 1 03:58:18 EET 2006


 src/i810_reg.h |    2 +
 src/i830_i2c.c |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 67 insertions(+), 9 deletions(-)

New commits:
diff-tree de50ca9ed9e78c17be1badec62e35ed5e4d62b05 (from 8c44556408601db2be799b5ac5c4da1d92886d31)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 17:56:47 2006 -0800

    Tristate the clock/data pins during GPIO when released while getting values.
    
    While the register is laid out suggesting that you can read a low value while
    driving the output high, and the I2C spec seems to indicate that you should be
    able to as well, and on some hardware this works successfully, on the i865 and
    perhaps some other chips it doesn't.  So, if we're not holding the clock or
    data pin low during GetBits, tristate the pin so that we can successfully read.
    
    This fixes i865 analog (VGA) DDC so it successfully sees slave acks.
    
    Also, improve the I2C bit-banging debugging.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 973ca61..d246c16 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -261,24 +261,46 @@ I830I2CAddress(I2CDevPtr d, I2CSlaveAddr
 
 #else
 
+#define I2C_DEBUG 0
+
+#if I2C_DEBUG
+static Bool first = TRUE;
+#endif
+
 static void
 i830I2CGetBits(I2CBusPtr b, int *clock, int *data)
 {
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
-    CARD32 val;
+    CARD32 val, tristate = 0;
 
     val = INREG(b->DriverPrivate.uval);
+
+    /* If we've released either of the lines from holding low, tristate them
+     * so that we can successfully read.  Some hardware fails to read low
+     * values driven by slaves when our master is not tri-stated, while other
+     * chips succeed.
+     */
+    if ((val & GPIO_DATA_DIR_OUT) && (val & GPIO_DATA_VAL_OUT))
+	tristate |= GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
+    if ((val & GPIO_CLOCK_DIR_OUT) && (val & GPIO_CLOCK_VAL_OUT))
+	tristate |= GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
+
+    if (tristate) {
+	OUTREG(b->DriverPrivate.uval, tristate);
+
+	val = INREG(b->DriverPrivate.uval);
+    }
+
     *data = (val & GPIO_DATA_VAL_IN) != 0;
     *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
-}
-
-#define I2C_DEBUG 0
 
 #if I2C_DEBUG
-static int last_clock = 0, last_data = 0;
-static Bool first = TRUE;
+    ErrorF("Getting I2C:                   %c %c\n",
+	   *clock ? '^' : 'v',
+	   *data ? '^' : 'v');
 #endif
+}
 
 static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
@@ -287,23 +309,12 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 
 #if I2C_DEBUG
     int cur_clock, cur_data;
-    char *debug = "";
 #endif
 
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
 
 #if I2C_DEBUG
-    if (!first && cur_clock != last_clock && cur_data != last_data) {
-	/* If we change the clock and data simultaneously, that would be bad.
-	 * I thought we did sometimes, but maybe not.
-	 */
-	debug = " <--";
-    }
-
-    last_clock = cur_clock;
-    last_data = cur_data;
-
     i830I2CGetBits(b, &cur_clock, &cur_data);
 
     if (first) {
@@ -311,13 +322,10 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	first = FALSE;
     }
 
-    ErrorF("Setting I2C 0x%08x to: %c %c (at: %c %c)%s\n",
+    ErrorF("Setting I2C 0x%08x to: %c %c\n",
 	   (int)b->DriverPrivate.uval,
 	   clock ? '^' : 'v',
-	   data ? '^' : 'v',
-	   cur_clock ? '^' : 'v',
-	   cur_data ? '^' : 'v',
-	   debug);
+	   data ? '^' : 'v');
 #endif
 
     if (!IS_I830(pI830) && !IS_845G(pI830)) {
diff-tree 8c44556408601db2be799b5ac5c4da1d92886d31 (from 28401b25cc5c1afb272e506cef196ba3a1258bd3)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 15:56:52 2006 -0800

    Preserve some GPIO bits that the docs tell us to.

diff --git a/src/i810_reg.h b/src/i810_reg.h
index e931934..7312f8a 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -281,12 +281,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # define GPIO_CLOCK_VAL_MASK		(1 << 2)
 # define GPIO_CLOCK_VAL_OUT		(1 << 3)
 # define GPIO_CLOCK_VAL_IN		(1 << 4)
+# define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5)
 # define GPIO_DATA_DIR_MASK		(1 << 8)
 # define GPIO_DATA_DIR_IN		(0 << 9)
 # define GPIO_DATA_DIR_OUT		(1 << 9)
 # define GPIO_DATA_VAL_MASK		(1 << 10)
 # define GPIO_DATA_VAL_OUT		(1 << 11)
 # define GPIO_DATA_VAL_IN		(1 << 12)
+# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
 
 /* p317, 319
  */
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index ea828ff..973ca61 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -283,6 +283,8 @@ static Bool first = TRUE;
 static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
 {
+    CARD32 reserved = 0;
+
 #if I2C_DEBUG
     int cur_clock, cur_data;
     char *debug = "";
@@ -310,7 +312,7 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
     }
 
     ErrorF("Setting I2C 0x%08x to: %c %c (at: %c %c)%s\n",
-	   b->DriverPrivate.uval,
+	   (int)b->DriverPrivate.uval,
 	   clock ? '^' : 'v',
 	   data ? '^' : 'v',
 	   cur_clock ? '^' : 'v',
@@ -318,15 +320,22 @@ i830I2CPutBits(I2CBusPtr b, int clock, i
 	   debug);
 #endif
 
+    if (!IS_I830(pI830) && !IS_845G(pI830)) {
+	/* On most chips, these bits must be preserved in software. */
+	reserved = INREG(b->DriverPrivate.uval) &
+	    (GPIO_DATA_PULLUP_DISABLE | GPIO_CLOCK_PULLUP_DISABLE);
+    }
+
     OUTREG(b->DriverPrivate.uval,
-	(data ? GPIO_DATA_VAL_OUT : 0) |
-	(clock ? GPIO_CLOCK_VAL_OUT : 0) |
-	GPIO_CLOCK_DIR_OUT |
-	GPIO_DATA_DIR_OUT |
-	GPIO_CLOCK_DIR_MASK |
-	GPIO_CLOCK_VAL_MASK |
-	GPIO_DATA_DIR_MASK |
-	GPIO_DATA_VAL_MASK);
+	   reserved |
+	   (data ? GPIO_DATA_VAL_OUT : 0) |
+	   (clock ? GPIO_CLOCK_VAL_OUT : 0) |
+	   GPIO_CLOCK_DIR_OUT |
+	   GPIO_DATA_DIR_OUT |
+	   GPIO_CLOCK_DIR_MASK |
+	   GPIO_CLOCK_VAL_MASK |
+	   GPIO_DATA_DIR_MASK |
+	   GPIO_DATA_VAL_MASK);
 }
 #endif
 
diff-tree 28401b25cc5c1afb272e506cef196ba3a1258bd3 (from ff64bc7397cafbec94e388e1625b3a1999f1aca7)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Nov 30 15:45:13 2006 -0800

    Add debug code for the bit-banging I2C implementation.

diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 8b93c8e..ea828ff 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -273,12 +273,51 @@ i830I2CGetBits(I2CBusPtr b, int *clock, 
     *clock = (val & GPIO_CLOCK_VAL_IN) != 0;
 }
 
+#define I2C_DEBUG 0
+
+#if I2C_DEBUG
+static int last_clock = 0, last_data = 0;
+static Bool first = TRUE;
+#endif
+
 static void
 i830I2CPutBits(I2CBusPtr b, int clock, int data)
 {
+#if I2C_DEBUG
+    int cur_clock, cur_data;
+    char *debug = "";
+#endif
+
     ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
     I830Ptr pI830 = I830PTR(pScrn);
 
+#if I2C_DEBUG
+    if (!first && cur_clock != last_clock && cur_data != last_data) {
+	/* If we change the clock and data simultaneously, that would be bad.
+	 * I thought we did sometimes, but maybe not.
+	 */
+	debug = " <--";
+    }
+
+    last_clock = cur_clock;
+    last_data = cur_data;
+
+    i830I2CGetBits(b, &cur_clock, &cur_data);
+
+    if (first) {
+	ErrorF("I2C Debug:        C D      C D\n");
+	first = FALSE;
+    }
+
+    ErrorF("Setting I2C 0x%08x to: %c %c (at: %c %c)%s\n",
+	   b->DriverPrivate.uval,
+	   clock ? '^' : 'v',
+	   data ? '^' : 'v',
+	   cur_clock ? '^' : 'v',
+	   cur_data ? '^' : 'v',
+	   debug);
+#endif
+
     OUTREG(b->DriverPrivate.uval,
 	(data ? GPIO_DATA_VAL_OUT : 0) |
 	(clock ? GPIO_CLOCK_VAL_OUT : 0) |



More information about the xorg-commit mailing list