summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2012-08-13 13:22:35 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-02 10:39:41 -0700
commitefb269742ee6b7a7f929054fde8bfaa4ccb3f0de (patch)
treee15930af28714f38fed1378478cea49a2b6e697b /drivers/gpu
parentd3e3373115a6472419fb84663e99ce52f8e77cfa (diff)
drm/i915: fall back to bit-banging if GMBUS fails in CRT EDID reads
commit f1a2f5b7c5f0941d23eef0a095c0b99bf8d051e6 upstream. 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> Tested-by: Alex Ferrando <alferpal@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 75a70c46ef1b..1f0741f026cc 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -284,6 +284,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);
@@ -299,7 +329,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
struct i2c_adapter *i2c;
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);
/*
* This may be a DVI-I connector with a shared DDC
* link between analog and digital outputs, so we
@@ -498,13 +528,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,