xf86-video-intel: 3 commits - src/bios_reader/bios_reader.c src/i830_bios.c src/i830_bios.h src/i830.h src/i830_sdvo.c

Zhenyu Wang zhen at kemper.freedesktop.org
Sun Jun 14 23:59:52 PDT 2009


 src/bios_reader/bios_reader.c |    4 +-
 src/i830.h                    |    8 +++-
 src/i830_bios.c               |   81 ++++++++++++++++++++++++++++++++++++++++++
 src/i830_bios.h               |    2 -
 src/i830_sdvo.c               |   72 +++++++++++++++++++++++++++++++++++--
 5 files changed, 160 insertions(+), 7 deletions(-)

New commits:
commit 3da549f5b350dd42516e5cb3576f7fefe012d95e
Author: Zhao Yakui <yakui.zhao at intel.com>
Date:   Wed Jun 10 11:37:03 2009 +0800

    GFX: Initialize the SDVO device based on the valid slave address
    
    When the slave address is found for the SDVO port, the SDVO device will
    be initialzied.
    When the slave address is not found for the SDVO port, it will return
    the slave address by using the following flowchart:
    a. If the SDVO device info is found for another SDVO port, it will return
    the slave address that is not used. For example: if 0x70 is used, then 0x72
    is returned.
    b. If no SDVO device info is found for another SDVO port, it will return
    0x70 for SDVOB and 0x72 for SDVOC.
    
    http://bugs.freedesktop.org/show_bug.cgi?id=20429
    
    Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cfba482..acfe599 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1038,7 +1038,6 @@ i830_sdvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
 	/* Set the input timing to the screen. Assume always input 0. */
 	i830_sdvo_set_target_input(output, TRUE, FALSE);
 
-
 	success = i830_sdvo_create_preferred_input_timing(output,
 							  mode->Clock / 10,
 							  mode->HDisplay,
@@ -2135,7 +2134,70 @@ i830_sdvo_select_ddc_bus(struct i830_sdvo_priv *dev_priv)
     /* Corresponds to SDVO_CONTROL_BUS_DDCx */
     dev_priv->ddc_bus = 1 << num_bits;
 }
+/**
+ * find the slave address for the given SDVO port based on the info
+ * parsed in general definition blocks
+ * If the slave address is found in the SDVO device info parsed from
+ * VBT,it will be returned. Otherwise it will return the slave address
+ * by the following steps.
+ * and 0x72 for SDVOC port.
+ * a. If one SDVO device info is found in another DVO port, it will return
+ * the slave address that is not used. For example: if 0x70 is used,
+ * then 0x72 is returned.
+ * b. If no SDVO device info is found in another DVO port, it will return
+ * 0x70 for SDVOB and 0x72 for SDVOC port.
+ */
+static
+void i830_find_sdvo_slave(ScrnInfoPtr pScrn, int output_device,
+			  uint8_t *slave_addr)
+{
+    uint8_t temp_slave_addr;
+    I830Ptr pI830 = I830PTR(pScrn);
+    uint8_t dvo_port, dvo2_port;
+    struct sdvo_device_mapping *p_mapping;
+
+    if (output_device == SDVOB) {
+	/* DEVICE_PORT_DVOB */
+	dvo_port = 0;
+	dvo2_port = 1;
+    } else {
+	/* DEVICE_POTR_DVOC */
+	dvo_port = 1;
+	dvo2_port = 0;
+    }
 
+    p_mapping = &(pI830->sdvo_mappings[dvo_port]);
+    temp_slave_addr = p_mapping->slave_addr;
+    if (temp_slave_addr) {
+	/* slave address is found . return it */
+	*slave_addr = temp_slave_addr;
+	return ;
+    }
+    /* Check whether the SDVO device info is found in another dvo port */
+    p_mapping = &(pI830->sdvo_mappings[dvo2_port]);
+    temp_slave_addr = p_mapping->slave_addr;
+    if (!temp_slave_addr) {
+	/* no SDVO device is found in another DVO port */
+	/* it will return 0x70 for SDVOB and 0x72 for SDVOC */
+	if (output_device == SDVOB)
+		temp_slave_addr = 0x70;
+	else
+		temp_slave_addr = 0x72;
+	*slave_addr = temp_slave_addr;
+	return ;
+    }
+    /* return the slave address that is not used.
+     * If the 0x70 is used, then 0x72 is returned.
+     * If the 0x72 is used, then 0x70 is returned.
+     */
+    if (temp_slave_addr == 0x70)
+	temp_slave_addr = 0x72;
+    else
+	temp_slave_addr = 0x70;
+
+    *slave_addr = temp_slave_addr;
+    return ;
+}
 Bool
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 {
@@ -2145,6 +2207,10 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     int			    i;
     unsigned char	    ch[0x40];
     I2CBusPtr		    i2cbus = NULL, ddcbus;
+    uint8_t slave_addr;
+
+    slave_addr = 0;
+    i830_find_sdvo_slave(pScrn, output_device, &slave_addr);
 
     output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL);
     if (!output)
@@ -2180,14 +2246,12 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 	xf86OutputDestroy (output);
 	return FALSE;
     }
-
     if (output_device == SDVOB) {
 	dev_priv->d.DevName = "SDVO Controller B";
-	dev_priv->d.SlaveAddr = 0x70;
     } else {
 	dev_priv->d.DevName = "SDVO Controller C";
-	dev_priv->d.SlaveAddr = 0x72;
     }
+    dev_priv->d.SlaveAddr = slave_addr;
     dev_priv->d.pI2CBus = i2cbus;
     dev_priv->d.DriverPrivate.ptr = output;
     dev_priv->output_device = output_device;
commit 51b87b9913ba164d4d5de79e558233915b37a0a5
Author: Zhao Yakui <yakui.zhao at intel.com>
Date:   Wed Jun 10 11:37:02 2009 +0800

    parse general definition block to get the SDVO device info
    
    The general definition block contains the child device tables, which include
    the child device info. For example: device slave address, device dvo port,
    device type.
    We will get the info of SDVO device by parsing the general definition blocks.
    Only when a valid slave address is found, it is regarded as the SDVO device.
    And the info of DVO port and slave address is recorded.
    
    http://bugs.freedesktop.org/show_bug.cgi?id=20429
    
    Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>

diff --git a/src/i830.h b/src/i830.h
index a69f47c..19b189c 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -328,7 +328,12 @@ enum dri_type {
     DRI_NONE,
     DRI_DRI2
 };
-
+struct sdvo_device_mapping {
+   uint8_t dvo_port;
+   uint8_t slave_addr;
+   uint8_t dvo_wiring;
+   uint8_t initialized;
+};
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
    unsigned char *GTTBase;
@@ -608,6 +613,7 @@ typedef struct _I830Rec {
 
     /** User option to print acceleration fallback info to the server log. */
    Bool fallback_debug;
+   struct sdvo_device_mapping sdvo_mappings[2];
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_bios.c b/src/i830_bios.c
index 9c1f101..2f129e9 100644
--- a/src/i830_bios.c
+++ b/src/i830_bios.c
@@ -47,6 +47,8 @@
 				 (bios[_addr + 2] << 16) |	\
 				 (bios[_addr + 3] << 24))
 
+#define		SLAVE_ADDR1	0x70
+#define		SLAVE_ADDR2	0x72
 static void *
 find_section(struct bdb_header *bdb, int section_id)
 {
@@ -236,6 +238,84 @@ parse_driver_feature(I830Ptr pI830, struct bdb_header *bdb)
 	pI830->integrated_lvds = FALSE;
 }
 
+static
+void parse_sdvo_mapping(ScrnInfoPtr pScrn, struct bdb_header *bdb)
+{
+    unsigned int block_size;
+    uint16_t *block_ptr;
+    struct bdb_general_definitions *defs;
+    struct child_device_config *child;
+    int i, child_device_num, count;
+    struct sdvo_device_mapping *p_mapping;
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+    if (!defs) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			"can't find the general definition blocks\n");
+	return;
+    }
+    /* Get the block size of general defintion block */
+    block_ptr = (uint16_t *)((char *)defs - 2);
+    block_size = *block_ptr;
+    child_device_num = (block_size - sizeof(*defs)) / sizeof(*child);
+    count = 0;
+
+    for (i = 0; i < child_device_num; i++) {
+	child = &defs->devices[i];
+	if (!child->device_type) {
+		/* skip invalid child device type*/
+		 continue;
+	}
+	if (child->slave_addr == SLAVE_ADDR1 ||
+			child->slave_addr == SLAVE_ADDR2) {
+	    if (child->dvo_port != DEVICE_PORT_DVOB &&
+			child->dvo_port != DEVICE_PORT_DVOC) {
+		/* skip the incorrect sdvo port */
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+				"Incorrect SDVO port\n");
+		continue;
+	    }
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			"the SDVO device with slave addr %x "
+			"is found on DVO %x port\n",
+			child->slave_addr, child->dvo_port);
+	    /* fill the primary dvo port */
+	    p_mapping = &(pI830->sdvo_mappings[child->dvo_port - 1]);
+	    if (!p_mapping->initialized) {
+		p_mapping->dvo_port = child->dvo_port;
+		p_mapping->dvo_wiring = child->dvo_wiring;
+		p_mapping->initialized = 1;
+		p_mapping->slave_addr = child->slave_addr;
+	    } else {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+				"One DVO port is shared by two slave "
+				"address. Maybe it can't be handled\n");
+	    }
+	    /* If there exists the slave2_addr, maybe it is a sdvo
+	     * device that contain multiple inputs. And it can't
+	     * handled by SDVO driver.
+	     * Ignore the dvo mapping of slave2_addr
+	     * of course its mapping info won't be added.
+	     */
+	    if (child->slave2_addr) {
+		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+				"Two DVO ports uses the same slave address."
+				"Maybe it can't be handled by SDVO driver\n");
+	    }
+	    count++;
+	} else {
+	    /* if the slave address is neither 0x70 nor 0x72, skip it. */
+	    continue;
+	}
+    }
+    /* If the count is zero, it indicates that no sdvo device is found */
+    if (!count)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			"No SDVO device is found in VBT\n");
+
+    return;
+}
 #define INTEL_VBIOS_SIZE (64 * 1024)	/* XXX */
 
 /**
@@ -302,6 +382,7 @@ i830_bios_init(ScrnInfoPtr pScrn)
     parse_general_features(pI830, bdb);
     parse_panel_data(pI830, bdb);
     parse_driver_feature(pI830, bdb);
+    parse_sdvo_mapping(pScrn, bdb);
 
     xfree(bios);
 
commit 6ba148bbd78783f59eed3d898638c39b950dcd89
Author: Zhao Yakui <yakui.zhao at intel.com>
Date:   Wed Jun 10 11:37:01 2009 +0800

    Dynamically get the number of child device in general definition block
    
    The size of general definition block varies on different platform/machines.
    In such case the number of child device is also different.
    And it will be better to get the number of child device in general definition
    block dynamically.
    
    The number of child device can be calculated by the following formula:
    	(block_size - block_header_size) /
    		sizeof( struct child_device_config)
    
    http://bugs.freedesktop.org/show_bug.cgi?id=20429
    
    Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>

diff --git a/src/bios_reader/bios_reader.c b/src/bios_reader/bios_reader.c
index 328cacf..27ec769 100644
--- a/src/bios_reader/bios_reader.c
+++ b/src/bios_reader/bios_reader.c
@@ -170,6 +170,7 @@ static void dump_general_definitions(void)
     struct child_device_config *child;
     int i;
     char child_id[11];
+    int child_device_num;
 
     block = find_section(BDB_GENERAL_DEFINITIONS);
 
@@ -188,7 +189,8 @@ static void dump_general_definitions(void)
     printf("\tBoot display type: 0x%02x%02x\n", defs->boot_display[1],
 	   defs->boot_display[0]);
     printf("\tTV data block present: %s\n", YESNO(tv_present));
-    for (i = 0; i < 4; i++) {
+    child_device_num = (block->size - sizeof(*defs)) / sizeof(*child);
+    for (i = 0; i < child_device_num; i++) {
 	child = &defs->devices[i];
 	if (!child->device_type) {
 	    printf("\tChild device %d not present\n", i);
diff --git a/src/i830_bios.h b/src/i830_bios.h
index 1f1f1aa..8a3025e 100644
--- a/src/i830_bios.h
+++ b/src/i830_bios.h
@@ -228,7 +228,7 @@ struct bdb_general_definitions {
 	 * TV and LVDS are missing, so be careful when interpreting
 	 * [4] and [5].
 	 */
-	struct child_device_config devices[6];
+	struct child_device_config devices[0];
 	/* may be another device block here on some platforms */
 } __attribute__((packed));
 


More information about the xorg-commit mailing list