xf86-video-intel: src/i830_crt.c

Zhenyu Wang zhen at kemper.freedesktop.org
Sat Oct 11 08:59:14 PDT 2008


 src/i830_crt.c |   22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

New commits:
commit 6cb4150160bb1e1365773561fb53294ad9248a0e
Author: Zhenyu Wang <zhenyu.z.wang at intel.com>
Date:   Sun Oct 12 08:07:44 2008 +0800

    Bug #17892: Fix possible crash in CRT probe
    
    Introduced in patch for DVI-I CRT probe, if no EDID
    CRT monitor is connected, origin code destroys default
    DDC bus which causes crash in later get_modes call.
    Change it to setup and destroy DDC bus as needed in
    get_modes, so we always reprobe and get current state.

diff --git a/src/i830_crt.c b/src/i830_crt.c
index 2e70eb8..479fbe5 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -338,13 +338,19 @@ i830_crt_detect_load (xf86CrtcPtr	    crtc,
 static Bool
 i830_crt_detect_ddc(xf86OutputPtr output)
 {
+    ScrnInfoPtr		    pScrn = output->scrn;
     I830OutputPrivatePtr    i830_output = output->driver_private;
+    Bool detect;
 
     /* CRT should always be at 0, but check anyway */
     if (i830_output->type != I830_OUTPUT_ANALOG)
 	return FALSE;
 
-    return xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0);
+    I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
+    detect = xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0);
+    xf86DestroyI2CBusRec(i830_output->pDDCBus, TRUE, TRUE);
+
+    return detect;
 }
 
 /**
@@ -428,18 +434,19 @@ i830_get_edid(xf86OutputPtr output, int gpio_reg, char *gpio_str)
     xf86MonPtr		    edid_mon = NULL;
 
     /* Set up the DDC bus. */
-    if (gpio_reg != GPIOA)
-	I830I2CInit(output->scrn, &intel_output->pDDCBus, gpio_reg, gpio_str);
+    I830I2CInit(output->scrn, &intel_output->pDDCBus, gpio_reg, gpio_str);
 
     edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
 
     if (!edid_mon || DIGITAL(edid_mon->features.input_type)) {
 	xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+	intel_output->pDDCBus = NULL;
 	if (edid_mon) {
 	    xfree(edid_mon);
 	    edid_mon = NULL;
 	}
     }
+
     return edid_mon;
 }
 
@@ -448,6 +455,7 @@ i830_crt_get_modes (xf86OutputPtr output)
 {
     DisplayModePtr	    modes;
     xf86MonPtr		    edid_mon = NULL;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
 
     /* Try to probe normal CRT port, and also digital port for output
        in DVI-I mode. */
@@ -458,6 +466,11 @@ i830_crt_get_modes (xf86OutputPtr output)
     if ((edid_mon = i830_get_edid(output, GPIOE, "CRTDDC_E")))
 	goto found;
 found:
+    /* Destroy DDC bus after probe, so every other new probe will
+       scan all ports again */
+    if (intel_output->pDDCBus)
+	xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
+
     xf86OutputSetEDID (output, edid_mon);
 
     modes = xf86OutputGetEDIDModes (output);
@@ -509,7 +522,4 @@ i830_crt_init(ScrnInfoPtr pScrn)
     output->driver_private = i830_output;
     output->interlaceAllowed = FALSE;
     output->doubleScanAllowed = FALSE;
-
-    /* Set up the DDC bus. */
-    I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
 }


More information about the xorg-commit mailing list