[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