diff mbox

[2/2] drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads

Message ID 03e17075b1252d819178316c8b2a12573e59ddca.1344852255.git.jani.nikula@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jani Nikula Aug. 13, 2012, 10:22 a.m. UTC
GMBUS was enabled over bit-banging as the default in commits:

commit c3dfefa0a6d235bd465309e12f4c56ea16e71111
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Tue Feb 14 22:37:25 2012 +0100

    drm/i915: reenable gmbus on gen3+ again

and

commit 0fb3f969c8683505fb7323c06bf8a999a5a45a15
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Fri Mar 2 19:38:30 2012 +0100

    drm/i915: enable gmbus on gen2

Unfortunately, GMBUS seems to fail on some CRT displays. Add a bit-banging
fallback to CRT EDID reads.

LKML-Reference: <201207251020.47637.maciej.rutecki@gmail.com>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/intel_crt.c |   36 +++++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

Comments

Daniel Vetter Aug. 16, 2012, 2:35 p.m. UTC | #1
On Mon, Aug 13, 2012 at 01:22:35PM +0300, Jani Nikula wrote:
> GMBUS was enabled over bit-banging as the default in commits:
> 
> commit c3dfefa0a6d235bd465309e12f4c56ea16e71111
> Author: Daniel Vetter <daniel.vetter@ffwll.ch>
> Date:   Tue Feb 14 22:37:25 2012 +0100
> 
>     drm/i915: reenable gmbus on gen3+ again
> 
> and
> 
> commit 0fb3f969c8683505fb7323c06bf8a999a5a45a15
> Author: Daniel Vetter <daniel.vetter@ffwll.ch>
> Date:   Fri Mar 2 19:38:30 2012 +0100
> 
>     drm/i915: enable gmbus on gen2
> 
> Unfortunately, GMBUS seems to fail on some CRT displays. Add a bit-banging
> fallback to CRT EDID reads.
> 
> LKML-Reference: <201207251020.47637.maciej.rutecki@gmail.com>
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=45881
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Patches applied to -fixes with the tested-by result from the bug report.
I've also put a cc: stable on both of them, since the regression is
already in 3.4.

Thanks, Daniel
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index bc5e2c9..80bf311 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -328,6 +328,36 @@  static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 	return ret;
 }
 
+static struct edid *intel_crt_get_edid(struct drm_connector *connector,
+				struct i2c_adapter *i2c)
+{
+	struct edid *edid;
+
+	edid = drm_get_edid(connector, i2c);
+
+	if (!edid && !intel_gmbus_is_forced_bit(i2c)) {
+		DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
+		intel_gmbus_force_bit(i2c, true);
+		edid = drm_get_edid(connector, i2c);
+		intel_gmbus_force_bit(i2c, false);
+	}
+
+	return edid;
+}
+
+/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
+static int intel_crt_ddc_get_modes(struct drm_connector *connector,
+				struct i2c_adapter *adapter)
+{
+	struct edid *edid;
+
+	edid = intel_crt_get_edid(connector, adapter);
+	if (!edid)
+		return 0;
+
+	return intel_connector_update_modes(connector, edid);
+}
+
 static bool intel_crt_detect_ddc(struct drm_connector *connector)
 {
 	struct intel_crt *crt = intel_attached_crt(connector);
@@ -338,7 +368,7 @@  static bool intel_crt_detect_ddc(struct drm_connector *connector)
 	BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
 
 	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
-	edid = drm_get_edid(connector, i2c);
+	edid = intel_crt_get_edid(connector, i2c);
 
 	if (edid) {
 		bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
@@ -546,13 +576,13 @@  static int intel_crt_get_modes(struct drm_connector *connector)
 	struct i2c_adapter *i2c;
 
 	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin);
-	ret = intel_ddc_get_modes(connector, i2c);
+	ret = intel_crt_ddc_get_modes(connector, i2c);
 	if (ret || !IS_G4X(dev))
 		return ret;
 
 	/* Try to probe digital port for output in DVI-I -> VGA mode. */
 	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
-	return intel_ddc_get_modes(connector, i2c);
+	return intel_crt_ddc_get_modes(connector, i2c);
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,