diff options
author | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2008-10-12 08:07:44 +0800 |
---|---|---|
committer | Zhenyu Wang <zhenyu.z.wang@intel.com> | 2008-10-12 08:07:44 +0800 |
commit | 6cb4150160bb1e1365773561fb53294ad9248a0e (patch) | |
tree | 0eb2e452034226ae7924d6917af14634173cc1da | |
parent | 140451abb41fbd68d5aac4736c1cf1ec2805dd9e (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.c | 22 |
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"); } |