<div dir="ltr"><div>Thanks</div><div><br></div>Reviewed-by: Rodrigo Vivi <<a href="mailto:rodrigo.vivi@intel.com">rodrigo.vivi@intel.com</a>><div><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Sep 11, 2015 at 4:38 AM Sonika Jindal <<a href="mailto:sonika.jindal@intel.com">sonika.jindal@intel.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The Bspec is very clear that Live status must be checked about before<br>
trying to read EDID over DDC channel. This patch makes sure that HDMI<br>
EDID is read only when live status is up.<br>
<br>
The live status doesn't seem to perform very consistent across various<br>
platforms when tested with different monitors. The reason behind that is<br>
some monitors are late to provide right voltage to set live_status up.<br>
So, after getting the interrupt, for a small duration, live status reg<br>
fluctuates, and then settles down showing the correct staus.<br>
<br>
This is explained here in, in a rough way:<br>
HPD line  ________________<br>
                         |\ T1 = Monitor Hotplug causing IRQ<br>
                         | \______________________________________<br>
                         | |<br>
                         | |<br>
                         | |   T2 = Live status is stable<br>
                         | |  _____________________________________<br>
                         | | /|<br>
Live status _____________|_|/ |<br>
                         | |  |<br>
                         | |  |<br>
                         | |  |<br>
                        T0 T1  T2<br>
<br>
(Between T1 and T2 Live status fluctuates or can be even low, depending on<br>
 the monitor)<br>
<br>
After several experiments, we have concluded that a max delay<br>
of 30ms is enough to allow the live status to settle down with<br>
most of the monitors. This total delay of 30ms has been split into<br>
a resolution of 3 retries of 10ms each, for the better cases.<br>
<br>
This delay is kept at 30ms, keeping in consideration that, HDCP compliance<br>
expect the HPD handler to respond a plug out in 100ms, by disabling port.<br>
<br>
v2: Adding checks for VLV/CHV as well. Reusing old ibx and g4x functions<br>
to check digital port status. Adding a separate function to get bxt live<br>
status (Daniel)<br>
v3: Using intel_encoder->hpd_pin to check the live status (Siva)<br>
Moving the live status read to intel_hdmi_probe and passing parameter<br>
to read/not to read the edid. (me)<br>
v4:<br>
* Added live status check for all platforms using<br>
intel_digital_port_connected.<br>
* Rebased on top of Jani's DP cleanup series<br>
* Some monitors take time in setting the live status. So retry for few<br>
times if this is a connect HPD<br>
v5: Removed extra "drm/i915" from commit message. Adding Shashank's sob<br>
    which was missed.<br>
v6: Drop the (!detect_edid && !live_status check) check because for DDI<br>
ports which are enumerated as hdmi as well as DP, we don't have a<br>
mechanism to differentiate between DP and hdmi inside the encoder's<br>
hot_plug. This leads to call to the hdmi's hot_plug hook for DP as well<br>
as hdmi which leads to issues during unplug because of the above check.<br>
v7: Make intel_digital_port_connected global in this patch, some<br>
reformatting of while loop, adding a print when live status is not<br>
up. (Rodrigo)<br>
<br>
Signed-off-by: Shashank Sharma <<a href="mailto:shashank.sharma@intel.com" target="_blank">shashank.sharma@intel.com</a>><br>
Signed-off-by: Sonika Jindal <<a href="mailto:sonika.jindal@intel.com" target="_blank">sonika.jindal@intel.com</a>><br>
---<br>
 drivers/gpu/drm/i915/intel_dp.c   |    2 +-<br>
 drivers/gpu/drm/i915/intel_drv.h  |    2 ++<br>
 drivers/gpu/drm/i915/intel_hdmi.c |   26 +++++++++++++++++++-------<br>
 3 files changed, 22 insertions(+), 8 deletions(-)<br>
<br>
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c<br>
index bf17030..fedf6d1 100644<br>
--- a/drivers/gpu/drm/i915/intel_dp.c<br>
+++ b/drivers/gpu/drm/i915/intel_dp.c<br>
@@ -4695,7 +4695,7 @@ static bool bxt_digital_port_connected(struct drm_i915_private *dev_priv,<br>
  *<br>
  * Return %true if @port is connected, %false otherwise.<br>
  */<br>
-static bool intel_digital_port_connected(struct drm_i915_private *dev_priv,<br>
+bool intel_digital_port_connected(struct drm_i915_private *dev_priv,<br>
                                         struct intel_digital_port *port)<br>
 {<br>
        if (HAS_PCH_IBX(dev_priv))<br>
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h<br>
index b6c2c20..ac6d748 100644<br>
--- a/drivers/gpu/drm/i915/intel_drv.h<br>
+++ b/drivers/gpu/drm/i915/intel_drv.h<br>
@@ -1210,6 +1210,8 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp);<br>
 void intel_edp_drrs_invalidate(struct drm_device *dev,<br>
                unsigned frontbuffer_bits);<br>
 void intel_edp_drrs_flush(struct drm_device *dev, unsigned frontbuffer_bits);<br>
+bool intel_digital_port_connected(struct drm_i915_private *dev_priv,<br>
+                                        struct intel_digital_port *port);<br>
<br>
 /* intel_dp_mst.c */<br>
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);<br>
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c<br>
index 1eda71a..d366ca5 100644<br>
--- a/drivers/gpu/drm/i915/intel_hdmi.c<br>
+++ b/drivers/gpu/drm/i915/intel_hdmi.c<br>
@@ -1329,22 +1329,23 @@ intel_hdmi_unset_edid(struct drm_connector *connector)<br>
 }<br>
<br>
 static bool<br>
-intel_hdmi_set_edid(struct drm_connector *connector)<br>
+intel_hdmi_set_edid(struct drm_connector *connector, bool force)<br>
 {<br>
        struct drm_i915_private *dev_priv = to_i915(connector->dev);<br>
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);<br>
        struct intel_encoder *intel_encoder =<br>
                &hdmi_to_dig_port(intel_hdmi)->base;<br>
        enum intel_display_power_domain power_domain;<br>
-       struct edid *edid;<br>
+       struct edid *edid = NULL;<br>
        bool connected = false;<br>
<br>
        power_domain = intel_display_port_power_domain(intel_encoder);<br>
        intel_display_power_get(dev_priv, power_domain);<br>
<br>
-       edid = drm_get_edid(connector,<br>
-                           intel_gmbus_get_adapter(dev_priv,<br>
-                                                   intel_hdmi->ddc_bus));<br>
+       if (force)<br>
+               edid = drm_get_edid(connector,<br>
+                                   intel_gmbus_get_adapter(dev_priv,<br>
+                                   intel_hdmi->ddc_bus));<br>
<br>
        intel_display_power_put(dev_priv, power_domain);<br>
<br>
@@ -1374,14 +1375,25 @@ void intel_hdmi_probe(struct intel_encoder *intel_encoder)<br>
                        enc_to_intel_hdmi(&intel_encoder->base);<br>
        struct intel_connector *intel_connector =<br>
                                intel_hdmi->attached_connector;<br>
+       struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);<br>
+       bool live_status = false;<br>
+       unsigned int retry = 3;<br>
+<br>
+       while (!live_status && --retry) {<br>
+               live_status = intel_digital_port_connected(dev_priv,<br>
+                               hdmi_to_dig_port(intel_hdmi));<br>
+               mdelay(10);<br>
+       }<br>
<br>
+       if (!live_status)<br>
+               DRM_DEBUG_KMS("Live status not up!");<br>
        /*<br>
         * We are here, means there is a hotplug or a force<br>
         * detection. Clear the cached EDID and probe the<br>
         * DDC bus to check the current status of HDMI.<br>
         */<br>
        intel_hdmi_unset_edid(&intel_connector->base);<br>
-       if (intel_hdmi_set_edid(&intel_connector->base))<br>
+       if (intel_hdmi_set_edid(&intel_connector->base, live_status))<br>
                DRM_DEBUG_DRIVER("DDC probe: got EDID\n");<br>
        else<br>
                DRM_DEBUG_DRIVER("DDC probe: no EDID\n");<br>
@@ -1432,7 +1444,7 @@ intel_hdmi_force(struct drm_connector *connector)<br>
        if (connector->status != connector_status_connected)<br>
                return;<br>
<br>
-       intel_hdmi_set_edid(connector);<br>
+       intel_hdmi_set_edid(connector, true);<br>
        hdmi_to_dig_port(intel_hdmi)->base.type = INTEL_OUTPUT_HDMI;<br>
 }<br>
<br>
--<br>
1.7.10.4<br>
<br>
_______________________________________________<br>
Intel-gfx mailing list<br>
<a href="mailto:Intel-gfx@lists.freedesktop.org" target="_blank">Intel-gfx@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/intel-gfx" rel="noreferrer" target="_blank">http://lists.freedesktop.org/mailman/listinfo/intel-gfx</a><br>
</blockquote></div>