diff mbox

[BUG] i915 HDMI connector status is connected after disconnection

Message ID 20180706170349.79ae08d0@gbai-ub1604-LTS (mailing list archive)
State New, archived
Headers show

Commit Message

Guang Bai July 7, 2018, 12:03 a.m. UTC
On Fri, 6 Jul 2018 13:38:06 -0700
Rodrigo Vivi <rodrigo.vivi@intel.com> wrote:

> On Fri, Jul 06, 2018 at 10:41:18AM -0700, Guang Bai wrote:
> > On Fri, 6 Jul 2018 14:44:58 +0800
> > Chris Chiu <chiu@endlessm.com> wrote:
> >   
> > > On Thu, Jul 5, 2018 at 10:40 PM, Ville Syrjälä
> > > <ville.syrjala@linux.intel.com> wrote:  
> > > > On Thu, Jul 05, 2018 at 03:58:36PM +0800, Chris Chiu wrote:    
> > > >> Hi,
> > > >>     We have few ASUS laptops X705FD (The new WiskyLake), X560UD
> > > >> (intel i5-8250U), X530UN (intel i7-8550U) share the same
> > > >> problem, which is the HDMI connector status stays connected
> > > >> even the HDMI cable has been unplugged. Look into the
> > > >> "/sys/class/drm/card0-HDMI-A-1/status" for checking the status
> > > >> while plug/unplug the HDMI, it shows "disconnected" before
> > > >> plug in HDMI cable, then switch to "connected" after plugin,
> > > >> and still stay "connected" after unplug. This would cause the
> > > >> audio output path cannot correctly switch from HDMI to
> > > >> internal speaker after unplugging the HDMI.
> > > >>
> > > >> I then try to verify with the latest kernel 4.18.0-rc3+, the
> > > >> bug still present. The full "dmesg" log is here.
> > > >> https://gist.github.com/mschiu77/d761d7c5cf191b7868d4d7788ae087f1
> > > >>
> > > >> The HDMI cable is plugged in at ~26th second.
> > > >> "[ 26.214371] [drm:drm_detect_monitor_audio [drm]] Monitor has
> > > >> basic audio support"
> > > >> then unplug the HDMI at ~73th second.
> > > >> "[ 73.328361] [drm:drm_detect_monitor_audio [drm]] Monitor has
> > > >> basic audio support"
> > > >>
> > > >> Please advise what I can do to fix this. Thanks    
> > > >
> > > > Pull the cable out faster?
> > > >
> > > > I presume this is the same old case of hpd disconnecting
> > > > slightly before ddc and we still manage to read the EDID when
> > > > processing the hpd irq. We kinda tried to fix that with the
> > > > live status check but that thing failed spectacularly.
> > > >
> > > > --
> > > > Ville Syrjälä
> > > > Intel    
> > > 
> > > Thanks for the suggestion. I tried pulling the cable out faster,
> > > the status shows correctly. I also tried branch drm-tip of
> > > https://cgit.freedesktop.org/drm/drm-tip
> > > but the symptom persists.
> > > 
> > > Anything I can help here? Or any old commit/patch I can try to do
> > > some experiments?
> > > 
> > > Chris
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx  
> > 
> > I'm working on a same issue with HP KBL ThinPro laptop where both
> > 
> > kernel 4.9.79 & 4.15.7 are failing the same way:
> > - Unplug the HDMI cable slowly the connector status is still
> >   "connected"
> > 
> > Debugging shows from kernel 4.9 and up to 4.18 drim/i915 behaves the
> > same way:
> > - When the HDMI calbe is unplugged, there is a transition time when
> >   the DDC lines are still connected and i915 can read back the EDID
> >   and honors "connected" state
> > 
> > This problem does not happen on Windows7 & Windows 10 on the same
> > failing platform - Windows KMD does *not* read the DDC when seeing
> > the corresponding PCH/HPD pins indicating "disconnected" within
> > 300ms-400ms period - This checking is done during bottom-half
> > interrupt routines
> > 
> > I worked patches with both 4.15.7 and 4.17.1 intercepting this
> > Windows KMD logics; It seems these patches work for HP KBL ThinPro
> > laptop - My patches are being tested by HP team - I was just about
> > to post the open discussion on this topic to collect inputs from
> > our community  
> 
> please send them out anyways ;)
> 
> > - Do we have to refactor the HDMI hot-plug handling codes to cope
> > with this long standing issue?  
> 
> What is your proposal for re-work?
> 
> > - Is that OK to add 300ms-500ms delay "msleep(100)" in a loop in the
> >   bottom half of interrupt routines?  
> 
> Well, We fight to add the delays only when they are required by specs,
> rather than experimental on single display/configuration...
> but/however/nevertheless we have cases that we retry aux
> communications 32 times because a specific monitor...
> 
> please show your patch and we discuss on top of it...
> 
> > 
> > Regards,
> > -Guang
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx  

Following is my temp/test patch evaluated by customers per this HDMI
hot-plut issue:

From 1b5a3c32bd50c88c22cb375f7815c9462f29eae5 Mon Sep 17 00:00:00 2001
From: Guang Bai <guang.bai@intel.com>
Date: Fri, 6 Jul 2018 16:46:55 -0700
Subject: [PATCH] drm/i915: Temp/testing codes to address HDMI hot-plug
issue

When slowly unplugging the HDMI cable, some platforms still
show the HDMI "connected" status - This issue happens from
kernel 4.9 and up to 4.17.1 and drm-tip
---
 drivers/gpu/drm/i915/intel_hotplug.c | 45
+++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+),
1 deletion(-)

        if (old_status == connector->status)
@@ -285,6 +287,45 @@ static bool intel_hpd_irq_event(struct drm_device
        *dev, return true;
 }

+static bool intel_hpd_irq_event2(struct drm_i915_private *dev_priv,
+                                struct drm_connector *connector)
+{
+       struct drm_device *dev = &dev_priv->drm;
+       struct intel_connector *intel_connector =
to_intel_connector(connector);
+       struct intel_encoder *intel_encoder = intel_connector->encoder;
+       enum hpd_pin pin = intel_encoder->hpd_pin;
+       bool changed = false;
+       bool check_connect = false;
+       u32 count = 0;
+
+       DRM_DEBUG_KMS(">>> HP-TEST: Enter %s ...\n", __FUNCTION__);
+
+       if (HAS_PCH_SPT(dev_priv) &&
+           dev_priv->hotplug.stats[pin].state == HPD_ENABLED) {
+               do {
+                       msleep(100);
+                       /*
+                        * Hard-code CPT PORT-B hot-plug status bit
checking.
+                        * Runtime checking based on port & pin TBD
+                        */
+                       if (I915_READ(SDEISR) & SDE_PORTB_HOTPLUG_CPT) {
+                               check_connect = true;
+                               break;
+                       }
+               } while (++count <= 4);
+       } else
+               check_connect = true;
+
+       if (check_connect) {
+               changed |= intel_hpd_irq_event(dev, connector);
+       } else {
+               changed = (intel_connector->base.status !=
+                          connector_status_disconnected);
+               intel_connector->base.status =
connector_status_disconnected;
+       }
+       return changed;
+}
+
 static void i915_digport_work_func(struct work_struct *work)
 {
        struct drm_i915_private *dev_priv =
@@ -370,9 +411,11 @@ static void i915_hotplug_work_func(struct
work_struct *work) if (hpd_event_bits & (1 << intel_encoder->hpd_pin)) {
                        DRM_DEBUG_KMS("Connector %s (pin %i) received
hotplug event.\n", connector->name, intel_encoder->hpd_pin);
+                       DRM_DEBUG_KMS(">>> HP-TEST:
intel_encoder->hot_plug = %llx...\n",
+                                       (unsigned long
long)(intel_encoder->hot_plug)); if (intel_encoder->hot_plug)
                                intel_encoder->hot_plug(intel_encoder);
-                       if (intel_hpd_irq_event(dev, connector))
+                       if (intel_hpd_irq_event2(dev_priv, connector))
                                changed = true;
                }
        }
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_hotplug.c
b/drivers/gpu/drm/i915/intel_hotplug.c index 875d5d2..fafa9a7 100644
--- a/drivers/gpu/drm/i915/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/intel_hotplug.c
@@ -271,6 +271,8 @@  static bool intel_hpd_irq_event(struct drm_device
*dev, WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
        old_status = connector->status;

+       DRM_DEBUG_KMS(">>> HP-TEST: Enter %s ...\n", __FUNCTION__);
+
        connector->status = drm_helper_probe_detect(connector, NULL,
  false);