From f542d671ffcec772a561cd41c7e2394392d9dafb Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 10 Jun 2020 15:55:10 +0800 Subject: drm/i915: Init lspcon after HPD in intel_dp_detect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200610075542.12882-1-kai.heng.feng@canonical.com --- drivers/gpu/drm/i915/display/intel_lspcon.c | 61 ++++++++++++++++------------- 1 file changed, 34 insertions(+), 27 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_lspcon.c') 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"); +} -- cgit v1.2.3 From c7da2782abca7fc1a143a8246ddf3d3175d7fbf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 2 Oct 2020 12:04:46 +0300 Subject: drm/i915: Make lspcon_init() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make lspcon_init() static since it's no longer needed outside the compilation unit. This was correct in Kai-Heng's lspcon patch, but I fumbled this when applying it. Cc: Kai-Heng Feng Reported-by: kernel test robot Fixes: f542d671ffce ("drm/i915: Init lspcon after HPD in intel_dp_detect()") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20201002090446.21104-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/display/intel_lspcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915/display/intel_lspcon.c') diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index db2e1e938572..ee95fc353a56 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -530,7 +530,7 @@ void lspcon_wait_pcon_mode(struct intel_lspcon *lspcon) lspcon_wait_mode(lspcon, DRM_LSPCON_MODE_PCON); } -bool lspcon_init(struct intel_digital_port *dig_port) +static bool lspcon_init(struct intel_digital_port *dig_port) { struct intel_dp *dp = &dig_port->dp; struct intel_lspcon *lspcon = &dig_port->lspcon; -- cgit v1.2.3 From 06fa32846884fa059f87b666dedeb12f900a31c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Sep 2020 21:41:54 +0300 Subject: drm/i915: Nuke lspcon_downsampling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crtc_state->lspcon_downsampling isn't particularly useful at the moment since we can't even do proper readout for it. Let's get rid of it. Will help with unifying the LSPCON with the regular DFP YCbCr output support. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200924184156.24491-1-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_lspcon.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_lspcon.c') diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index ee95fc353a56..b21cb337e318 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -195,7 +195,6 @@ void lspcon_ycbcr420_config(struct drm_connector *connector, connector->ycbcr_420_allowed) { crtc_state->port_clock /= 2; crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR444; - crtc_state->lspcon_downsampling = true; } } @@ -492,14 +491,19 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, return; } - if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) { - if (crtc_state->lspcon_downsampling) - frame.avi.colorspace = HDMI_COLORSPACE_YUV420; - else - frame.avi.colorspace = HDMI_COLORSPACE_YUV444; - } else { + /* + * Currently there is no interface defined to + * check user preference between RGB/YCBCR444 + * or YCBCR420. So the only possible case for + * YCBCR444 usage is driving YCBCR420 output + * with LSPCON, when pipe is configured for + * YCBCR444 output and LSPCON takes care of + * downsampling it. + */ + if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444) + frame.avi.colorspace = HDMI_COLORSPACE_YUV420; + else frame.avi.colorspace = HDMI_COLORSPACE_RGB; - } drm_hdmi_avi_infoframe_quant_range(&frame.avi, conn_state->connector, -- cgit v1.2.3 From ebde5f89b32a258f15a2d094b02b6de0bbdf5beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Sep 2020 21:41:55 +0300 Subject: drm/i915: Nuke lspcon_ycbcr420_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the lspcon special case from intel_dp_compute_config() and just treat it like any other DFP than can do 4:4:4->4:2:0 conversion. The only difference between the two codepaths was that the lspcon code tried to already halve port_clock. That was just total nonsense as we hadn't even computed the base port_clock at that time. All that stuff happens intel_dp_compute_link_config*() and it already takes care of the 4:2:0 clock reduction. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200924184156.24491-2-ville.syrjala@linux.intel.com Reviewed-by: Uma Shankar --- drivers/gpu/drm/i915/display/intel_lspcon.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers/gpu/drm/i915/display/intel_lspcon.c') diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index b21cb337e318..e37d45e531df 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -184,20 +184,6 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) return true; } -void lspcon_ycbcr420_config(struct drm_connector *connector, - struct intel_crtc_state *crtc_state) -{ - const struct drm_display_info *info = &connector->display_info; - const struct drm_display_mode *adjusted_mode = - &crtc_state->hw.adjusted_mode; - - if (drm_mode_is_420_only(info, adjusted_mode) && - connector->ycbcr_420_allowed) { - crtc_state->port_clock /= 2; - crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR444; - } -} - static bool lspcon_probe(struct intel_lspcon *lspcon) { int retry; -- cgit v1.2.3