summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyu.z.wang@intel.com>2008-10-12 08:07:44 +0800
committerZhenyu Wang <zhenyu.z.wang@intel.com>2008-10-12 08:07:44 +0800
commit6cb4150160bb1e1365773561fb53294ad9248a0e (patch)
tree0eb2e452034226ae7924d6917af14634173cc1da
parent140451abb41fbd68d5aac4736c1cf1ec2805dd9e (diff)
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.
-rw-r--r--src/i830_crt.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 2e70eb8d..479fbe5b 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");
}