diff options
author | Kai-Heng Feng <kai.heng.feng@canonical.com> | 2020-06-10 10:55:10 +0300 |
---|---|---|
committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2020-10-01 19:22:10 +0300 |
commit | f542d671ffcec772a561cd41c7e2394392d9dafb (patch) | |
tree | b60cdebde43109a43a519e661e0483edc1189b77 /drivers/gpu/drm/i915/display/intel_lspcon.c | |
parent | ef79fafe9dae31037c48bd11676746315725452d (diff) | |
download | linux-f542d671ffcec772a561cd41c7e2394392d9dafb.tar.xz |
drm/i915: Init lspcon after HPD in intel_dp_detect()
On HP 800 G4 DM, if HDMI cable isn't plugged before boot, the HDMI port
becomes useless and never responds to cable hotplugging:
[ 3.031904] [drm:lspcon_init [i915]] *ERROR* Failed to probe lspcon
[ 3.031945] [drm:intel_ddi_init [i915]] *ERROR* LSPCON init failed on port D
Seems like the lspcon chip on the system only gets powered after the
cable is plugged.
Consilidate lspcon_init() into lspcon_resume() to dynamically init
lspcon chip, and make HDMI port work.
v6:
- Rebase on latest for-linux-next.
v5:
- Consolidate lspcon_resume() with lspcon_init().
- Move more logic into lspcon code.
v4:
- Trust VBT in intel_infoframe_init().
- Init lspcon in intel_dp_detect().
v3:
- Make sure it's handled under long HPD case.
v2:
- Move lspcon_init() inside of intel_dp_hpd_pulse().
Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/203
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200610075542.12882-1-kai.heng.feng@canonical.com
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_lspcon.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_lspcon.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index dc1b35559afd..db2e1e938572 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -525,26 +525,6 @@ u32 lspcon_infoframes_enabled(struct intel_encoder *encoder, return 0; } -void lspcon_resume(struct intel_lspcon *lspcon) -{ - enum drm_lspcon_mode expected_mode; - - if (lspcon_wake_native_aux_ch(lspcon)) { - expected_mode = DRM_LSPCON_MODE_PCON; - lspcon_resume_in_pcon_wa(lspcon); - } else { - expected_mode = DRM_LSPCON_MODE_LS; - } - - if (lspcon_wait_mode(lspcon, expected_mode) == DRM_LSPCON_MODE_PCON) - return; - - if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON)) - DRM_ERROR("LSPCON resume failed\n"); - else - DRM_DEBUG_KMS("LSPCON resume success\n"); -} - void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon) { lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); @@ -554,15 +534,8 @@ bool lspcon_init(struct intel_digital_port *dig_port) { struct intel_dp *dp = &dig_port->dp; struct intel_lspcon *lspcon = &dig_port->lspcon; - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); struct drm_connector *connector = &dp->attached_connector->base; - if (!HAS_LSPCON(dev_priv)) { - DRM_ERROR("LSPCON is not supported on this platform\n"); - return false; - } - lspcon->active = false; lspcon->mode = DRM_LSPCON_MODE_INVALID; @@ -586,3 +559,37 @@ bool lspcon_init(struct intel_digital_port *dig_port) DRM_DEBUG_KMS("Success: LSPCON init\n"); return true; } + +void lspcon_resume(struct intel_digital_port *dig_port) +{ + struct intel_lspcon *lspcon = &dig_port->lspcon; + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + enum drm_lspcon_mode expected_mode; + + if (!intel_bios_is_lspcon_present(dev_priv, dig_port->base.port)) + return; + + if (!lspcon->active) { + if (!lspcon_init(dig_port)) { + DRM_ERROR("LSPCON init failed on port %c\n", + port_name(dig_port->base.port)); + return; + } + } + + if (lspcon_wake_native_aux_ch(lspcon)) { + expected_mode = DRM_LSPCON_MODE_PCON; + lspcon_resume_in_pcon_wa(lspcon); + } else { + expected_mode = DRM_LSPCON_MODE_LS; + } + + if (lspcon_wait_mode(lspcon, expected_mode) == DRM_LSPCON_MODE_PCON) + return; + + if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON)) + DRM_ERROR("LSPCON resume failed\n"); + else + DRM_DEBUG_KMS("LSPCON resume success\n"); +} |