Commit f1a2f5b7 authored by Jani Nikula's avatar Jani Nikula Committed by Daniel Vetter

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

GMBUS was enabled over bit-banging as the default in commits:

commit c3dfefa0
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 0fb3f969
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=45881Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
Tested-by: default avatarAlex Ferrando <alferpal@gmail.com>
Cc: stable@vger.kernel.org (for 3.4+3.5)
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 4eab8136
...@@ -326,6 +326,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) ...@@ -326,6 +326,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
return ret; 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) static bool intel_crt_detect_ddc(struct drm_connector *connector)
{ {
struct intel_crt *crt = intel_attached_crt(connector); struct intel_crt *crt = intel_attached_crt(connector);
...@@ -336,7 +366,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) ...@@ -336,7 +366,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)
BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG); BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); 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) { if (edid) {
bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
...@@ -544,13 +574,13 @@ static int intel_crt_get_modes(struct drm_connector *connector) ...@@ -544,13 +574,13 @@ static int intel_crt_get_modes(struct drm_connector *connector)
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); 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)) if (ret || !IS_G4X(dev))
return ret; return ret;
/* Try to probe digital port for output in DVI-I -> VGA mode. */ /* Try to probe digital port for output in DVI-I -> VGA mode. */
i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); 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, static int intel_crt_set_property(struct drm_connector *connector,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment