drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup.
authorEric Anholt <eric@anholt.net>
Tue, 1 Dec 2009 19:56:30 +0000 (11:56 -0800)
committerEric Anholt <eric@anholt.net>
Tue, 1 Dec 2009 19:56:30 +0000 (11:56 -0800)
This is a sync of a fix I made in the old UMS code.  If the BIOS uses
the GMBUS and doesn't clear that setup, then our bit-banging I2C can
fail, leading to monitors not being detected.

Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_i2c.c

index 6b596020d36258093616464f6aa14caa87d78ab4..c4a273513b2fba0a8038e1c6f93b438739b09528 100644 (file)
 # define GPIO_DATA_VAL_IN              (1 << 12)
 # define GPIO_DATA_PULLUP_DISABLE      (1 << 13)
 
+#define GMBUS0                 0x5100
+#define GMBUS1                 0x5104
+#define GMBUS2                 0x5108
+#define GMBUS3                 0x510c
+#define GMBUS4                 0x5110
+#define GMBUS5                 0x5120
+
 /*
  * Clock control & power management
  */
 #define PCH_GPIOE               0xc5020
 #define PCH_GPIOF               0xc5024
 
+#define PCH_GMBUS0             0xc5100
+#define PCH_GMBUS1             0xc5104
+#define PCH_GMBUS2             0xc5108
+#define PCH_GMBUS3             0xc510c
+#define PCH_GMBUS4             0xc5110
+#define PCH_GMBUS5             0xc5120
+
 #define PCH_DPLL_A              0xc6014
 #define PCH_DPLL_B              0xc6018
 
index cd10d9b8181fb2bd692ca05ab4f6c58dbff3b2c8..c5a6df93e1b61a546f6bf5d3873922f7ee7d4d56 100644 (file)
@@ -27,7 +27,7 @@
 #include "drmP.h"
 #include "drm.h"
 #include "i915_drm.h"
-#include "i915_drv.h"
+#include "intel_drv.h"
 
 static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 {
@@ -816,6 +816,9 @@ int i915_restore_state(struct drm_device *dev)
        for (i = 0; i < 3; i++)
                I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
 
+       /* I2C state */
+       intel_i2c_reset_gmbus(dev);
+
        return 0;
 }
 
index 8a22f25088997eba97899d107e635ecef005f366..9ffa31e13eb36e29a58e6c55beb36ab1aab09302 100644 (file)
@@ -162,6 +162,8 @@ void intel_i2c_destroy(struct i2c_adapter *adapter);
 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);
+void intel_i2c_reset_gmbus(struct drm_device *dev);
+
 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 c7eab724c418ed5a406ca711bdcadda8874881fc..b94acc4cc05ff3987932c5d03830504e7347afe0 100644 (file)
@@ -118,6 +118,23 @@ static void set_data(void *data, int state_high)
        udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
 }
 
+/* Clears the GMBUS setup.  Our driver doesn't make use of the GMBUS I2C
+ * engine, but if the BIOS leaves it enabled, then that can break our use
+ * of the bit-banging I2C interfaces.  This is notably the case with the
+ * Mac Mini in EFI mode.
+ */
+void
+intel_i2c_reset_gmbus(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (IS_IGDNG(dev)) {
+               I915_WRITE(PCH_GMBUS0, 0);
+       } else {
+               I915_WRITE(GMBUS0, 0);
+       }
+}
+
 /**
  * intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
  * @dev: DRM device
@@ -168,6 +185,8 @@ struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg,
        if(i2c_bit_add_bus(&chan->adapter))
                goto out_free;
 
+       intel_i2c_reset_gmbus(dev);
+
        /* JJJ:  raise SCL and SDA? */
        intel_i2c_quirk_set(dev, true);
        set_data(chan, 1);