[Intel-gfx] [PATCH 2/2]IGD: workaround i2c bus issue in gfx driver side

Shaohua Li shaohua.li at intel.com
Tue Apr 7 05:02:30 CEST 2009


In IGD, DPCUNIT_CLOCK_GATE_DISABLE bit should be set, otherwise i2c
access will be wrong.

Signed-off-by: Shaohua Li <shaohua.li at intel.com>
---
 src/i830.h       |    2 ++
 src/i830_crt.c   |    4 ++--
 src/i830_hdmi.c  |    2 +-
 src/i830_lvds.c  |    2 +-
 src/i830_modes.c |   41 +++++++++++++++++++++++++++++++++++++++--
 src/i830_sdvo.c  |    4 ++--
 6 files changed, 47 insertions(+), 8 deletions(-)

Index: xf86_video_intel/src/i830_crt.c
===================================================================
--- xf86_video_intel.orig/src/i830_crt.c
+++ xf86_video_intel/src/i830_crt.c
@@ -375,7 +375,7 @@ i830_crt_detect_ddc(xf86OutputPtr output
 	return FALSE;
 
     I830I2CInit(pScrn, &i830_output->pDDCBus, GPIOA, "CRTDDC_A");
-    detect = xf86I2CProbeAddress(i830_output->pDDCBus, 0x00A0);
+    detect = i830_ddc_probe(output);
     xf86DestroyI2CBusRec(i830_output->pDDCBus, TRUE, TRUE);
 
     return detect;
@@ -464,7 +464,7 @@ i830_get_edid(xf86OutputPtr output, int 
     /* Set up the DDC bus. */
     I830I2CInit(output->scrn, &intel_output->pDDCBus, gpio_reg, gpio_str);
 
-    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    edid_mon = i830_output_get_edid(output);
 
     if (!edid_mon || DIGITAL(edid_mon->features.input_type)) {
 	xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
Index: xf86_video_intel/src/i830_hdmi.c
===================================================================
--- xf86_video_intel.orig/src/i830_hdmi.c
+++ xf86_video_intel/src/i830_hdmi.c
@@ -185,7 +185,7 @@ i830_hdmi_detect(xf86OutputPtr output)
     else
 	return XF86OutputStatusDisconnected;
 
-    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    edid_mon = i830_output_get_edid(output);
     if (!edid_mon || !DIGITAL(edid_mon->features.input_type))
 	status = XF86OutputStatusDisconnected;
 
Index: xf86_video_intel/src/i830_lvds.c
===================================================================
--- xf86_video_intel.orig/src/i830_lvds.c
+++ xf86_video_intel/src/i830_lvds.c
@@ -941,7 +941,7 @@ i830_lvds_get_modes(xf86OutputPtr output
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
-    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    edid_mon = i830_output_get_edid(output);
 
     /* Our LVDS scaler can hit any size, so mark the EDID data as
      * supporting continuous timings
Index: xf86_video_intel/src/i830_modes.c
===================================================================
--- xf86_video_intel.orig/src/i830_modes.c
+++ xf86_video_intel/src/i830_modes.c
@@ -54,14 +54,51 @@
 #include "xf86Modes.h"
 #include <randrstr.h>
 
+static void i830_i2c_quirk_set(I830Ptr pI830, Bool enable)
+{
+   if (!IS_IGD(pI830))
+	return;
+   if (enable)
+        /* Driver is using bit bashing for I2C, this bit should be set to 1 */
+        OUTREG(DSPCLK_GATE_D, INREG(DSPCLK_GATE_D) | DPCUNIT_CLOCK_GATE_DISABLE);
+   else
+        OUTREG(DSPCLK_GATE_D, INREG(DSPCLK_GATE_D) &(~DPCUNIT_CLOCK_GATE_DISABLE));
+}
+
+Bool i830_ddc_probe(xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    ScrnInfoPtr scrn = output->scrn;
+    I830Ptr pI830 = I830PTR(scrn);
+    Bool detect;
+
+    i830_i2c_quirk_set(pI830, TRUE);
+    detect = xf86I2CProbeAddress(intel_output->pDDCBus, 0x00A0);
+    i830_i2c_quirk_set(pI830, FALSE);
+
+    return detect;
+}
+
+xf86MonPtr i830_output_get_edid(xf86OutputPtr output)
+{
+    xf86MonPtr edid_mon;
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    ScrnInfoPtr scrn = output->scrn;
+    I830Ptr pI830 = I830PTR(scrn);
+
+    i830_i2c_quirk_set(pI830, TRUE);
+    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    i830_i2c_quirk_set(pI830, FALSE);
+    return edid_mon;
+}
+
 DisplayModePtr
 i830_ddc_get_modes (xf86OutputPtr output)
 {
-    I830OutputPrivatePtr    intel_output = output->driver_private;
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
-    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    edid_mon = i830_output_get_edid(output);
     xf86OutputSetEDID (output, edid_mon);
     
     modes = xf86OutputGetEDIDModes (output);
Index: xf86_video_intel/src/i830_sdvo.c
===================================================================
--- xf86_video_intel.orig/src/i830_sdvo.c
+++ xf86_video_intel/src/i830_sdvo.c
@@ -1711,7 +1711,7 @@ i830_sdvo_detect(xf86OutputPtr output)
 	xf86MonPtr edid_mon;
 	/* Check EDID in DVI-I case */
 	i830_sdvo_set_control_bus_switch(output, dev_priv->ddc_bus);
-	edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+	edid_mon = i830_output_get_edid(output);
 	if (edid_mon && !DIGITAL(edid_mon->features.input_type)) {
 	    xfree(edid_mon);
 	    return XF86OutputStatusDisconnected;
@@ -1746,7 +1746,7 @@ i830_sdvo_get_ddc_modes(xf86OutputPtr ou
     if (intel_output->type == I830_OUTPUT_ANALOG &&
 	crt->funcs->detect(crt) == XF86OutputStatusDisconnected) {
 	I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOA, "CRTDDC_A");
-	edid_mon = xf86OutputGetEDID(crt, intel_output->pDDCBus);
+	edid_mon = i830_output_get_edid(crt);
 	xf86DestroyI2CBusRec(intel_output->pDDCBus, TRUE, TRUE);
     }
     if (edid_mon) {
Index: xf86_video_intel/src/i830.h
===================================================================
--- xf86_video_intel.orig/src/i830.h
+++ xf86_video_intel/src/i830.h
@@ -903,6 +903,8 @@ i830_allocate_framebuffer(ScrnInfoPtr pS
 
 /* i830_modes.c */
 DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
+xf86MonPtr i830_output_get_edid(xf86OutputPtr output);
+Bool i830_ddc_probe(xf86OutputPtr output);
 
 /* i830_tv.c */
 void i830_tv_init(ScrnInfoPtr pScrn);





More information about the Intel-gfx mailing list