From 98392a79fd6673e9a75721fa4dd0330b6a113338 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 5 Jan 2011 21:31:25 -0500 Subject: [PATCH 2/2] drm/radeon/kms: make dp link training more robust If clock recovery succeeded and and link training fails during channel equalization, restart training with a higher voltage swing and repeat the training. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/atombios_dp.c | 29 ++++++++++++++++++++++++----- 1 files changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index c37de73..b1476f2 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -591,7 +591,7 @@ void dp_link_train(struct drm_encoder *encoder, u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]; u8 tries, voltage; u8 train_set[4]; - int i; + int i, restart_tries = 0; if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) && (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) @@ -635,6 +635,11 @@ void dp_link_train(struct drm_encoder *encoder, dp_set_downspread(radeon_connector, DP_SPREAD_AMP_0_5); else dp_set_downspread(radeon_connector, 0x0); + + /* set initial vs/emph */ + memset(train_set, 0, 4); + +restart_training: if (ASIC_IS_DCE4(rdev)) { /* start training on the source */ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); @@ -649,8 +654,6 @@ void dp_link_train(struct drm_encoder *encoder, dig_connector->dp_clock, enc_id, 0); } - /* set initial vs/emph */ - memset(train_set, 0, 4); udelay(400); /* set training pattern 1 on the sink */ dp_set_training(radeon_connector, DP_TRAINING_PATTERN_1); @@ -739,9 +742,25 @@ void dp_link_train(struct drm_encoder *encoder, tries++; } - if (!channel_eq) + if (!channel_eq) { DRM_ERROR("channel eq failed\n"); - else + for (i = 0; i < dig_connector->dp_lane_count; i++) { + if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + } + /* increase the voltage and try again */ + if (i != dig_connector->dp_lane_count) { + u8 v, p; + for (i = 0; i < 4; i++) { + v = train_set[i] & DP_TRAIN_VOLTAGE_SWING_MASK; + p = train_set[i] & DP_TRAIN_PRE_EMPHASIS_MASK; + v++; + train_set[i] = v | p; + } + if (restart_tries++ < 5) + goto restart_training; + } + } else DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) -- 1.7.1.1