From 627736aa0f2e42879b86d2b7d63dab7d04e1cf11 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Mon, 26 Oct 2015 09:50:37 +0200 Subject: [PATCH] DEBUG drm/i915: fallback to lower link rates during DP MST link training --- drivers/gpu/drm/i915/intel_dp.c | 23 ++++++++--------------- drivers/gpu/drm/i915/intel_dp_mst.c | 34 +++++++++++++++++++++++++++------- drivers/gpu/drm/i915/intel_drv.h | 2 +- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index ca2d923..4f0a339 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3646,16 +3646,17 @@ static void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) } /* Enable corresponding port and start training pattern 1 */ -void +bool intel_dp_start_link_train(struct intel_dp *intel_dp) { struct drm_encoder *encoder = &dp_to_dig_port(intel_dp)->base.base; struct drm_device *dev = encoder->dev; int i; uint8_t voltage; - int voltage_tries, loop_tries; + int voltage_tries; uint32_t DP = intel_dp->DP; uint8_t link_config[2]; + bool cr_done = false; if (HAS_DDI(dev)) intel_ddi_prepare_link_retrain(encoder); @@ -3686,7 +3687,6 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) voltage = 0xff; voltage_tries = 0; - loop_tries = 0; for (;;) { uint8_t link_status[DP_LINK_STATUS_SIZE]; @@ -3697,6 +3697,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } if (drm_dp_clock_recovery_ok(link_status, intel_dp->lane_count)) { + cr_done = true; DRM_DEBUG_KMS("clock recovery OK\n"); break; } @@ -3722,18 +3723,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) for (i = 0; i < intel_dp->lane_count; i++) if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) break; - if (i == intel_dp->lane_count) { - ++loop_tries; - if (loop_tries == 5) { - DRM_ERROR("too many full retries, give up\n"); - break; - } - intel_dp_reset_link_train(intel_dp, &DP, - DP_TRAINING_PATTERN_1 | - DP_LINK_SCRAMBLING_DISABLE); - voltage_tries = 0; - continue; - } + if (i == intel_dp->lane_count) + break; /* Check to see if we've tried the same voltage 5 times */ if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { @@ -3754,6 +3745,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) } intel_dp->DP = DP; + + return cr_done; } void diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8c127201..eba5bf9 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -178,18 +178,38 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder) if (intel_dp->active_mst_links == 0) { enum port port = intel_ddi_get_encoder_port(encoder); + const int default_rates[] = { 162000, 270000, 540000 }; + int i; - /* FIXME: add support for SKL */ - if (INTEL_INFO(dev)->gen < 9) - I915_WRITE(PORT_CLK_SEL(port), - intel_crtc->config->ddi_pll_sel); + for (i = intel_dp->link_bw >> 3; i >= 0; i--) { + int rate = default_rates[i]; + intel_crtc->config->port_clock = rate; + intel_dp->link_bw = drm_dp_link_rate_to_bw_code(rate); - intel_ddi_init_dp_buf_reg(&intel_dig_port->base); + if (IS_HASWELL(dev) || IS_BROADWELL(dev)) + hsw_dp_set_ddi_pll_sel(intel_crtc->config); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + /* FIXME: add support for SKL */ + if (INTEL_INFO(dev)->gen < 9) + I915_WRITE(PORT_CLK_SEL(port), + intel_crtc->config->ddi_pll_sel); + intel_ddi_init_dp_buf_reg(&intel_dig_port->base); + + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + + DRM_DEBUG_KMS("Starting clock recovery with rate %d\n", + rate); + if (intel_dp_start_link_train(intel_dp)) + break; + } + + if (i >= 0) + DRM_DEBUG_KMS("clock recovery succeeded with rate %d\n", + intel_crtc->config->port_clock); + else + DRM_ERROR("clock recovery failed\n"); - intel_dp_start_link_train(intel_dp); intel_dp_complete_link_train(intel_dp); intel_dp_stop_link_train(intel_dp); } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 04d4261..4cc1732 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1164,7 +1164,7 @@ void assert_csr_loaded(struct drm_i915_private *dev_priv); void intel_dp_init(struct drm_device *dev, int output_reg, enum port port); bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port, struct intel_connector *intel_connector); -void intel_dp_start_link_train(struct intel_dp *intel_dp); +bool intel_dp_start_link_train(struct intel_dp *intel_dp); void intel_dp_complete_link_train(struct intel_dp *intel_dp); void intel_dp_stop_link_train(struct intel_dp *intel_dp); void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode); -- 2.4.3