| From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de> |
| Date: Sun, 31 Dec 2017 23:34:54 +0100 |
| Subject: drm/i915: Try EDID bitbanging on HDMI after failed read |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| commit cfb926e148e99acc02351d72e8b85e32b5f786ef upstream. |
| |
| The ACK/NACK implementation as found in e.g. the G965 has the falling |
| clock edge and the release of the data line after the ACK for the received |
| byte happen at the same time. |
| |
| This is conformant with the I2C specification, which allows a zero hold |
| time, see footnote [3]: "A device must internally provide a hold time of |
| at least 300 ns for the SDA signal (with respect to the V IH(min) of the |
| SCL signal) to bridge the undefined region of the falling edge of SCL." |
| |
| Some HDMI-to-VGA converters apparently fail to adhere to this requirement |
| and latch SDA at the falling clock edge, so instead of an ACK |
| sometimes a NACK is read and the slave (i.e. the EDID ROM) ends the |
| transfer. |
| |
| The bitbanging releases the data line for the ACK only 1/4 bit time after |
| the falling clock edge, so a slave will see the correct value no matter |
| if it samples at the rising or the falling clock edge or in the center. |
| |
| Fallback to bitbanging is already done for the CRT connector. |
| |
| Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92685 |
| Signed-off-by: Stefan BrΓΌns <stefan.bruens@rwth-aachen.de> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| Link: https://patchwork.freedesktop.org/patch/msgid/a39f080b-81a5-4c93-b3f7-7cb0a58daca3@rwthex-w2-a.rwth-ad.de |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/gpu/drm/i915/intel_hdmi.c | 14 +++++++++++--- |
| 1 file changed, 11 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/gpu/drm/i915/intel_hdmi.c |
| +++ b/drivers/gpu/drm/i915/intel_hdmi.c |
| @@ -971,6 +971,7 @@ intel_hdmi_detect(struct drm_connector * |
| struct edid *edid; |
| enum intel_display_power_domain power_domain; |
| enum drm_connector_status status = connector_status_disconnected; |
| + struct i2c_adapter *i2c; |
| |
| DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
| connector->base.id, connector->name); |
| @@ -981,9 +982,16 @@ intel_hdmi_detect(struct drm_connector * |
| intel_hdmi->has_hdmi_sink = false; |
| intel_hdmi->has_audio = false; |
| intel_hdmi->rgb_quant_range_selectable = false; |
| - edid = drm_get_edid(connector, |
| - intel_gmbus_get_adapter(dev_priv, |
| - intel_hdmi->ddc_bus)); |
| + i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); |
| + |
| + edid = drm_get_edid(connector, i2c); |
| + |
| + if (!edid && !intel_gmbus_is_forced_bit(i2c)) { |
| + DRM_DEBUG_KMS("HDMI 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); |
| + } |
| |
| if (edid) { |
| if (edid->input & DRM_EDID_INPUT_DIGITAL) { |