xserver: Branch 'master' - 3 commits

Adam Jackson ajax at kemper.freedesktop.org
Fri Mar 28 14:53:17 PDT 2008


 hw/xfree86/ddc/xf86DDC.c |  241 ++++++++++++++++++++++++++++-------------------
 hw/xfree86/ddc/xf86DDC.h |    2 
 2 files changed, 147 insertions(+), 96 deletions(-)

New commits:
commit 9e8451d869a4032ddb7de6a62920a3a7b0b1acc1
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Dec 3 17:38:53 2007 -0500

    Add E-EDID segment selection.

diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c
index 3e51c4e..7e26722 100644
--- a/hw/xfree86/ddc/xf86DDC.c
+++ b/hw/xfree86/ddc/xf86DDC.c
@@ -104,19 +104,14 @@ xf86DoEDID_DDC1(
 }
 
 static I2CDevPtr
-DDC2Init(int scrnIndex, I2CBusPtr pBus)
+DDC2MakeDevice(I2CBusPtr pBus, int address, char *name)
 {
     I2CDevPtr dev = NULL;
-    /*
-     * Slow down the bus so that older monitors don't 
-     * miss things.
-     */
-    pBus->RiseFallTime = 20;
-    
-    if (!(dev = xf86I2CFindDev(pBus, 0x00A0))) {
+
+    if (!(dev = xf86I2CFindDev(pBus, address))) {
 	dev = xf86CreateI2CDevRec();
-	dev->DevName = "ddc2";
-	dev->SlaveAddr = 0xA0;
+	dev->DevName = name;
+	dev->SlaveAddr = address;
 	dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
 	dev->StartTimeout = 550;
 	dev->BitTimeout = 40;
@@ -132,33 +127,70 @@ DDC2Init(int scrnIndex, I2CBusPtr pBus)
     return dev;
 }
 
-static unsigned char *
-DDC2Read(I2CDevPtr dev, int start, int len)
+static I2CDevPtr
+DDC2Init(int scrnIndex, I2CBusPtr pBus)
 {
-    unsigned char W_Buffer[2];
-    int w_bytes;
-    unsigned char *R_Buffer;
-    int i;
-    
-    if (start < 0x100) {
-	w_bytes = 1;
-	W_Buffer[0] = start;
-    } else {
-	w_bytes = 2;
-	W_Buffer[0] = start & 0xFF;
-	W_Buffer[1] = (start & 0xFF00) >> 8;
-    }
+    I2CDevPtr dev = NULL;
+
+    /*
+     * Slow down the bus so that older monitors don't 
+     * miss things.
+     */
+    pBus->RiseFallTime = 20;
+ 
+    DDC2MakeDevice(pBus, 0x0060, "E-EDID segment register");
+    dev = DDC2MakeDevice(pBus, 0x00A0, "ddc2");
+
+    return dev;
+}
+
+/* Mmmm, smell the hacks */
+static void
+EEDIDStop(I2CDevPtr d)
+{
+}
+
+/* block is the EDID block number.  a segment is two blocks. */
+static Bool
+DDC2Read(I2CDevPtr dev, int block, unsigned char *R_Buffer)
+{
+    unsigned char W_Buffer[1];
+    int i, segment;
+    I2CDevPtr seg;
+    void (*stop)(I2CDevPtr);
 
-    R_Buffer = xcalloc(sizeof(unsigned char), len);
     for (i = 0; i < RETRIES; i++) {
-	if (xf86I2CWriteRead(dev, W_Buffer, w_bytes, R_Buffer, len)) {
-	    if (!DDC_checksum(R_Buffer, len))
-		return R_Buffer;
+	/* Stop bits reset the segment pointer to 0, so be careful here. */
+	segment = block >> 1;
+	if (segment) {
+	    Bool b;
+	    
+	    if (!(seg = xf86I2CFindDev(dev->pI2CBus, 0x0060)))
+		return FALSE;
+
+	    W_Buffer[0] = segment;
+
+	    stop = dev->pI2CBus->I2CStop;
+	    dev->pI2CBus->I2CStop = EEDIDStop;
+
+	    b = xf86I2CWriteRead(seg, W_Buffer, 1, NULL, 0);
+
+	    dev->pI2CBus->I2CStop = stop;
+	    if (!b) {
+		dev->pI2CBus->I2CStop(dev);
+		continue;
+	    }
+	}
+
+	W_Buffer[0] = (block & 0x01) * EDID1_LEN;
+
+	if (xf86I2CWriteRead(dev, W_Buffer, 1, R_Buffer, EDID1_LEN)) {
+	    if (!DDC_checksum(R_Buffer, EDID1_LEN))
+		return TRUE;
 	}
     }
  
-    xfree(R_Buffer);
-    return NULL;
+    return FALSE;
 }
 
 /**
@@ -189,7 +221,9 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, int *nblocks)
     Bool noddc = FALSE, noddc2 = FALSE;
     OptionInfoPtr options;
 
-    options = xnfalloc(sizeof(DDCOptions));
+    options = xalloc(sizeof(DDCOptions));
+    if (!options)
+	return NULL;
     memcpy(options, DDCOptions, sizeof(DDCOptions));
     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
 
@@ -203,10 +237,13 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, int *nblocks)
     if (!(dev = DDC2Init(scrnIndex, pBus)))
 	return NULL;
 
-    EDID_block = DDC2Read(dev, 0, EDID1_LEN);
+    EDID_block = xcalloc(1, EDID1_LEN);
+    if (!EDID_block)
+	return NULL;
 
-    if (EDID_block)
+    if (DDC2Read(dev, 0, EDID_block)) {
 	tmp = xf86InterpretEDID(scrnIndex, EDID_block);
+    }
 
     if (nblocks) {
 	if (tmp)
commit 0b4aef4d6df7a5525d381de035fbbf78c5fffeef
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Dec 3 16:00:00 2007 -0500

    Refactor DDC2 code to allow for proper segmented addressing.

diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c
index 98f6006..3e51c4e 100644
--- a/hw/xfree86/ddc/xf86DDC.c
+++ b/hw/xfree86/ddc/xf86DDC.c
@@ -39,13 +39,6 @@ static unsigned int *FetchEDID_DDC1(
     register unsigned int (*)(ScrnInfoPtr)
 );
 
-static unsigned char * DDCRead_DDC2(
-    int scrnIndex,
-    I2CBusPtr pBus, 
-    int start, 
-    int len
-);
-
 typedef enum {
     DDCOPT_NODDC1,
     DDCOPT_NODDC2,
@@ -110,6 +103,64 @@ xf86DoEDID_DDC1(
 	return tmp;
 }
 
+static I2CDevPtr
+DDC2Init(int scrnIndex, I2CBusPtr pBus)
+{
+    I2CDevPtr dev = NULL;
+    /*
+     * Slow down the bus so that older monitors don't 
+     * miss things.
+     */
+    pBus->RiseFallTime = 20;
+    
+    if (!(dev = xf86I2CFindDev(pBus, 0x00A0))) {
+	dev = xf86CreateI2CDevRec();
+	dev->DevName = "ddc2";
+	dev->SlaveAddr = 0xA0;
+	dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
+	dev->StartTimeout = 550;
+	dev->BitTimeout = 40;
+	dev->AcknTimeout = 40;
+
+	dev->pI2CBus = pBus;
+	if (!xf86I2CDevInit(dev)) {
+	    xf86DrvMsg(scrnIndex, X_PROBED, "No DDC2 device\n");
+	    return NULL;
+	}
+    }
+
+    return dev;
+}
+
+static unsigned char *
+DDC2Read(I2CDevPtr dev, int start, int len)
+{
+    unsigned char W_Buffer[2];
+    int w_bytes;
+    unsigned char *R_Buffer;
+    int i;
+    
+    if (start < 0x100) {
+	w_bytes = 1;
+	W_Buffer[0] = start;
+    } else {
+	w_bytes = 2;
+	W_Buffer[0] = start & 0xFF;
+	W_Buffer[1] = (start & 0xFF00) >> 8;
+    }
+
+    R_Buffer = xcalloc(sizeof(unsigned char), len);
+    for (i = 0; i < RETRIES; i++) {
+	if (xf86I2CWriteRead(dev, W_Buffer, w_bytes, R_Buffer, len)) {
+	    if (!DDC_checksum(R_Buffer, len))
+		return R_Buffer;
+	}
+    }
+ 
+    xfree(R_Buffer);
+    return NULL;
+}
+
 /**
  * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
  * unset.  EDID information blocks are interpreted and the results returned in
@@ -133,6 +184,7 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, int *nblocks)
     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
     unsigned char *EDID_block = NULL;
     xf86MonPtr tmp = NULL;
+    I2CDevPtr dev = NULL;
     /* Default DDC and DDC2 to enabled. */
     Bool noddc = FALSE, noddc2 = FALSE;
     OptionInfoPtr options;
@@ -144,11 +196,14 @@ xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, int *nblocks)
     xf86GetOptValBool(options, DDCOPT_NODDC, &noddc);
     xf86GetOptValBool(options, DDCOPT_NODDC2, &noddc2);
     xfree(options);
-    
+
     if (noddc || noddc2)
 	return NULL;
 
-    EDID_block = DDCRead_DDC2(scrnIndex, pBus, 0, EDID1_LEN);
+    if (!(dev = DDC2Init(scrnIndex, pBus)))
+	return NULL;
+
+    EDID_block = DDC2Read(dev, 0, EDID1_LEN);
 
     if (EDID_block)
 	tmp = xf86InterpretEDID(scrnIndex, EDID_block);
@@ -247,62 +302,3 @@ FetchEDID_DDC1(register ScrnInfoPtr pScrn,
     } while(--count);
     return (ptr);
 }
-
-static unsigned char *
-DDCRead_DDC2(int scrnIndex, I2CBusPtr pBus, int start, int len)
-{
-    I2CDevPtr dev;
-    unsigned char W_Buffer[2];
-    int w_bytes;
-    unsigned char *R_Buffer;
-    int i;
-    
-    /*
-     * Slow down the bus so that older monitors don't 
-     * miss things.
-     */
-    pBus->RiseFallTime = 20;
-    
-    if (!(dev = xf86I2CFindDev(pBus, 0x00A0))) {
-	dev = xf86CreateI2CDevRec();
-	dev->DevName = "ddc2";
-	dev->SlaveAddr = 0xA0;
-	dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
-	dev->StartTimeout = 550;
-	dev->BitTimeout = 40;
-	dev->AcknTimeout = 40;
-
-	dev->pI2CBus = pBus;
-	if (!xf86I2CDevInit(dev)) {
-	    xf86DrvMsg(scrnIndex, X_PROBED, "No DDC2 device\n");
-	    return NULL;
-	}
-    }
-    if (start < 0x100) {
-	w_bytes = 1;
-	W_Buffer[0] = start;
-    } else {
-	w_bytes = 2;
-	W_Buffer[0] = start & 0xFF;
-	W_Buffer[1] = (start & 0xFF00) >> 8;
-    }
-    R_Buffer = xcalloc(1,sizeof(unsigned char) 
-					* (len));
-    for (i=0; i<RETRIES; i++) {
-	if (xf86I2CWriteRead(dev, W_Buffer,w_bytes, R_Buffer,len)) {
-	    if (!DDC_checksum(R_Buffer,len))
-		return R_Buffer;
-
-#ifdef DEBUG
-	    else ErrorF("Checksum error in EDID block\n");
-#endif
-	}
-#ifdef DEBUG
-	else ErrorF("Error reading EDID block\n");
-#endif
-    }
-    
-    xf86DestroyI2CDevRec(dev,TRUE);
-    xfree(R_Buffer);
-    return NULL;
-}
commit 88ece11d6c45c6f4b94f7fb2da64a46e879d7c27
Author: Adam Jackson <ajax at redhat.com>
Date:   Mon Dec 3 15:47:39 2007 -0500

    Start E-EDID support in the DDC module.
    
    Since there's no way to safely know how many blocks xf86DoEDID_DDC2 would
    return, add a new xf86DoEEDID entrypoint to do that, and implement the
    one in terms of the other.

diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c
index 28e2ead..98f6006 100644
--- a/hw/xfree86/ddc/xf86DDC.c
+++ b/hw/xfree86/ddc/xf86DDC.c
@@ -2,6 +2,14 @@
  * 
  * Copyright 1998,1999 by Egbert Eich <Egbert.Eich at Physik.TU-Darmstadt.DE>
  */
+
+/*
+ * Note that DDC1 does not define any method for returning blocks beyond
+ * the first.  DDC2 does, but the original implementation would only ever
+ * read the first block.  If you want to read and parse all blocks, use
+ * xf86DoEEDID().
+ */
+
 #ifdef HAVE_XORG_CONFIG_H
 #include <xorg-config.h>
 #endif
@@ -31,11 +39,6 @@ static unsigned int *FetchEDID_DDC1(
     register unsigned int (*)(ScrnInfoPtr)
 );
 
-static unsigned char* EDID1Read_DDC2(
-    int scrnIndex, 
-    I2CBusPtr pBus
-);
-
 static unsigned char * DDCRead_DDC2(
     int scrnIndex,
     I2CBusPtr pBus, 
@@ -110,16 +113,22 @@ xf86DoEDID_DDC1(
 /**
  * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
  * unset.  EDID information blocks are interpreted and the results returned in
- * an xf86MonPtr.
+ * an xf86MonPtr.  Unlike xf86DoEDID_DDC[12](), this function will return
+ * the complete EDID data, including all extension blocks.
  *
  * This function does not affect the list of modes used by drivers -- it is up
  * to the driver to decide policy on what to do with EDID information.
  *
  * @return pointer to a new xf86MonPtr containing the EDID information.
  * @return NULL if no monitor attached or failure to interpret the EDID.
+ *
+ * nblocks is an in/out parameter.  If non-zero, it defines the number of
+ * blocks to read from the monitor; zero (or NULL pointer) means read all.
+ * If non-NULL, on return it will be filled in with the number of blocks
+ * read.
  */
 xf86MonPtr
-xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
+xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, int *nblocks)
 {
     ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
     unsigned char *EDID_block = NULL;
@@ -129,7 +138,7 @@ xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
     OptionInfoPtr options;
 
     options = xnfalloc(sizeof(DDCOptions));
-    (void)memcpy(options, DDCOptions, sizeof(DDCOptions));
+    memcpy(options, DDCOptions, sizeof(DDCOptions));
     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, options);
 
     xf86GetOptValBool(options, DDCOPT_NODDC, &noddc);
@@ -139,26 +148,39 @@ xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
     if (noddc || noddc2)
 	return NULL;
 
-    EDID_block = EDID1Read_DDC2(scrnIndex,pBus);
+    EDID_block = DDCRead_DDC2(scrnIndex, pBus, 0, EDID1_LEN);
 
-    if (EDID_block){
-	tmp = xf86InterpretEDID(scrnIndex,EDID_block);
-    } else {
-#ifdef DEBUG
-	ErrorF("No EDID block returned\n");
-#endif
-	return NULL;
+    if (EDID_block)
+	tmp = xf86InterpretEDID(scrnIndex, EDID_block);
+
+    if (nblocks) {
+	if (tmp)
+	    *nblocks = tmp->no_sections;
+	else
+	    *nblocks = 0;
     }
-#ifdef DEBUG
-    if (!tmp)
-	ErrorF("Cannot interpret EDID block\n");
-    else
-        ErrorF("Sections to follow: %i\n",tmp->no_sections);
-#endif
-    
+
     return tmp;
 }
 
+/**
+ * Attempts to probe the monitor for EDID information, if NoDDC and NoDDC2 are
+ * unset.  EDID information blocks are interpreted and the results returned in
+ * an xf86MonPtr.
+ *
+ * This function does not affect the list of modes used by drivers -- it is up
+ * to the driver to decide policy on what to do with EDID information.
+ *
+ * @return pointer to a new xf86MonPtr containing the EDID information.
+ * @return NULL if no monitor attached or failure to interpret the EDID.
+ */
+xf86MonPtr
+xf86DoEDID_DDC2(int scrnIndex, I2CBusPtr pBus)
+{
+    int nblocks = 1;
+    return xf86DoEEDID(scrnIndex, pBus, &nblocks);
+}
+
 /* 
  * read EDID record , pass it to callback function to interpret.
  * callback function will store it for further use by calling
@@ -226,12 +248,6 @@ FetchEDID_DDC1(register ScrnInfoPtr pScrn,
     return (ptr);
 }
 
-static unsigned char*
-EDID1Read_DDC2(int scrnIndex, I2CBusPtr pBus)
-{
-    return  DDCRead_DDC2(scrnIndex, pBus, 0, EDID1_LEN);
-}
-
 static unsigned char *
 DDCRead_DDC2(int scrnIndex, I2CBusPtr pBus, int start, int len)
 {
diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h
index 3b072dd..6e5bf6f 100644
--- a/hw/xfree86/ddc/xf86DDC.h
+++ b/hw/xfree86/ddc/xf86DDC.h
@@ -35,6 +35,8 @@ extern xf86MonPtr xf86DoEDID_DDC2(
    I2CBusPtr pBus
 );
 
+extern xf86MonPtr xf86DoEEDID(int scrnIndex, I2CBusPtr pBus, int *nblocks);
+
 extern xf86MonPtr xf86PrintEDID(
     xf86MonPtr monPtr
 );


More information about the xorg-commit mailing list