[Intel-gfx] [PATCH 1/2] IGD: workaround i2c bus issue in kernel side
Shaohua Li
shaohua.li at intel.com
Tue Apr 7 05:02:28 CEST 2009
This is the second version patch. This version will disable
CLOCK_GATE_DISABLE bit after bit bashing as suggested by Eric.
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>
---
drivers/gpu/drm/i915/i915_reg.h | 1 +
drivers/gpu/drm/i915/intel_drv.h | 2 +-
drivers/gpu/drm/i915/intel_i2c.c | 17 +++++++++++++++++
drivers/gpu/drm/i915/intel_modes.c | 6 ++++++
4 files changed, 25 insertions(+), 1 deletion(-)
Index: linux/drivers/gpu/drm/i915/i915_reg.h
===================================================================
--- linux.orig/drivers/gpu/drm/i915/i915_reg.h 2009-04-03 15:03:32.000000000 +0800
+++ linux/drivers/gpu/drm/i915/i915_reg.h 2009-04-03 15:05:24.000000000 +0800
@@ -526,6 +526,7 @@
#define DPLLA_INPUT_BUFFER_ENABLE (1 << 0)
#define D_STATE 0x6104
#define CG_2D_DIS 0x6200
+#define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24)
#define CG_3D_DIS 0x6204
/*
Index: linux/drivers/gpu/drm/i915/intel_modes.c
===================================================================
--- linux.orig/drivers/gpu/drm/i915/intel_modes.c 2009-04-03 15:03:32.000000000 +0800
+++ linux/drivers/gpu/drm/i915/intel_modes.c 2009-04-03 15:52:37.000000000 +0800
@@ -27,6 +27,7 @@
#include <linux/fb.h>
#include "drmP.h"
#include "intel_drv.h"
+#include "i915_drv.h"
/**
* intel_ddc_probe
@@ -52,7 +53,10 @@ bool intel_ddc_probe(struct intel_output
}
};
+ intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2);
+ intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
+
if (ret == 2)
return true;
@@ -70,8 +74,10 @@ int intel_ddc_get_modes(struct intel_out
struct edid *edid;
int ret = 0;
+ intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true);
edid = drm_get_edid(&intel_output->base,
&intel_output->ddc_bus->adapter);
+ intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false);
if (edid) {
drm_mode_connector_update_edid_property(&intel_output->base,
edid);
Index: linux/drivers/gpu/drm/i915/intel_drv.h
===================================================================
--- linux.orig/drivers/gpu/drm/i915/intel_drv.h 2009-04-03 15:53:04.000000000 +0800
+++ linux/drivers/gpu/drm/i915/intel_drv.h 2009-04-03 15:53:38.000000000 +0800
@@ -109,7 +109,7 @@ struct intel_i2c_chan *intel_i2c_create(
void intel_i2c_destroy(struct intel_i2c_chan *chan);
int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
-
+void intel_i2c_quirk_set(struct drm_device *dev, bool enable);
extern void intel_crt_init(struct drm_device *dev);
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
extern bool intel_sdvo_init(struct drm_device *dev, int output_device);
Index: linux/drivers/gpu/drm/i915/intel_i2c.c
===================================================================
--- linux.orig/drivers/gpu/drm/i915/intel_i2c.c 2009-04-03 15:44:46.000000000 +0800
+++ linux/drivers/gpu/drm/i915/intel_i2c.c 2009-04-03 15:47:37.000000000 +0800
@@ -34,6 +34,21 @@
#include "i915_drm.h"
#include "i915_drv.h"
+void intel_i2c_quirk_set(struct drm_device *dev, bool enable)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ /* When using bit bashing for I2C, this bit needs to be set to 1 */
+ if (!IS_IGD(dev))
+ return;
+ if (enable)
+ I915_WRITE(CG_2D_DIS,
+ I915_READ(CG_2D_DIS) | DPCUNIT_CLOCK_GATE_DISABLE);
+ else
+ I915_WRITE(CG_2D_DIS,
+ I915_READ(CG_2D_DIS) & (~DPCUNIT_CLOCK_GATE_DISABLE));
+}
+
/*
* Intel GPIO access functions
*/
@@ -153,8 +168,10 @@ struct intel_i2c_chan *intel_i2c_create(
goto out_free;
/* JJJ: raise SCL and SDA? */
+ intel_i2c_quirk_set(dev, true);
set_data(chan, 1);
set_clock(chan, 1);
+ intel_i2c_quirk_set(dev, false);
udelay(20);
return chan;
More information about the Intel-gfx
mailing list