Commit 869184a6 authored by Jesse Barnes's avatar Jesse Barnes Committed by Chris Wilson

drm/i915/dp: use VBT provided eDP params if available

We can skip most of the link training step if we use the VBT provided
values.
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 89667383
...@@ -581,6 +581,17 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -581,6 +581,17 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
mode->clock = dev_priv->panel_fixed_mode->clock; mode->clock = dev_priv->panel_fixed_mode->clock;
} }
/* Just use VBT values for eDP */
if (is_edp(intel_dp)) {
intel_dp->lane_count = dev_priv->edp.lanes;
intel_dp->link_bw = dev_priv->edp.rate;
adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
DRM_DEBUG_KMS("eDP link bw %02x lane count %d clock %d\n",
intel_dp->link_bw, intel_dp->lane_count,
adjusted_mode->clock);
return true;
}
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
for (clock = 0; clock <= max_clock; clock++) { for (clock = 0; clock <= max_clock; clock++) {
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
...@@ -599,19 +610,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -599,19 +610,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
} }
} }
if (is_edp(intel_dp)) {
/* okay we failed just pick the highest */
intel_dp->lane_count = max_lane_count;
intel_dp->link_bw = bws[max_clock];
adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw);
DRM_DEBUG_KMS("Force picking display port link bw %02x lane "
"count %d clock %d\n",
intel_dp->link_bw, intel_dp->lane_count,
adjusted_mode->clock);
return true;
}
return false; return false;
} }
...@@ -1088,11 +1086,21 @@ intel_get_adjust_train(struct intel_dp *intel_dp) ...@@ -1088,11 +1086,21 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
} }
static uint32_t static uint32_t
intel_dp_signal_levels(uint8_t train_set, int lane_count) intel_dp_signal_levels(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t signal_levels = 0; uint32_t signal_levels = 0;
u8 train_set = intel_dp->train_set[0];
u32 vswing = train_set & DP_TRAIN_VOLTAGE_SWING_MASK;
u32 preemphasis = train_set & DP_TRAIN_PRE_EMPHASIS_MASK;
if (is_edp(intel_dp)) {
vswing = dev_priv->edp.vswing;
preemphasis = dev_priv->edp.preemphasis;
}
switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { switch (vswing) {
case DP_TRAIN_VOLTAGE_SWING_400: case DP_TRAIN_VOLTAGE_SWING_400:
default: default:
signal_levels |= DP_VOLTAGE_0_4; signal_levels |= DP_VOLTAGE_0_4;
...@@ -1107,7 +1115,7 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count) ...@@ -1107,7 +1115,7 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count)
signal_levels |= DP_VOLTAGE_1_2; signal_levels |= DP_VOLTAGE_1_2;
break; break;
} }
switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { switch (preemphasis) {
case DP_TRAIN_PRE_EMPHASIS_0: case DP_TRAIN_PRE_EMPHASIS_0:
default: default:
signal_levels |= DP_PRE_EMPHASIS_0; signal_levels |= DP_PRE_EMPHASIS_0;
...@@ -1193,6 +1201,18 @@ intel_channel_eq_ok(struct intel_dp *intel_dp) ...@@ -1193,6 +1201,18 @@ intel_channel_eq_ok(struct intel_dp *intel_dp)
return true; return true;
} }
static bool
intel_dp_aux_handshake_required(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (is_edp(intel_dp) && dev_priv->no_aux_handshake)
return false;
return true;
}
static bool static bool
intel_dp_set_link_train(struct intel_dp *intel_dp, intel_dp_set_link_train(struct intel_dp *intel_dp,
uint32_t dp_reg_value, uint32_t dp_reg_value,
...@@ -1205,6 +1225,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, ...@@ -1205,6 +1225,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
I915_WRITE(intel_dp->output_reg, dp_reg_value); I915_WRITE(intel_dp->output_reg, dp_reg_value);
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
if (!intel_dp_aux_handshake_required(intel_dp))
return true;
intel_dp_aux_native_write_1(intel_dp, intel_dp_aux_native_write_1(intel_dp,
DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_SET,
dp_train_pat); dp_train_pat);
...@@ -1237,6 +1260,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -1237,6 +1260,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
POSTING_READ(intel_dp->output_reg); POSTING_READ(intel_dp->output_reg);
intel_wait_for_vblank(dev, intel_crtc->pipe); intel_wait_for_vblank(dev, intel_crtc->pipe);
if (intel_dp_aux_handshake_required(intel_dp))
/* Write the link configuration data */ /* Write the link configuration data */
intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET, intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
intel_dp->link_configuration, intel_dp->link_configuration,
...@@ -1258,7 +1282,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -1258,7 +1282,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else { } else {
signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); signal_levels = intel_dp_signal_levels(intel_dp);
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
} }
...@@ -1272,7 +1296,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -1272,7 +1296,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
break; break;
/* Set training pattern 1 */ /* Set training pattern 1 */
udelay(100); udelay(500);
if (intel_dp_aux_handshake_required(intel_dp)) {
break;
} else {
if (!intel_dp_get_link_status(intel_dp)) if (!intel_dp_get_link_status(intel_dp))
break; break;
...@@ -1300,6 +1327,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) ...@@ -1300,6 +1327,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
/* Compute new intel_dp->train_set as requested by target */ /* Compute new intel_dp->train_set as requested by target */
intel_get_adjust_train(intel_dp); intel_get_adjust_train(intel_dp);
} }
}
intel_dp->DP = DP; intel_dp->DP = DP;
} }
...@@ -1325,7 +1353,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ...@@ -1325,7 +1353,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
} else { } else {
signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count); signal_levels = intel_dp_signal_levels(intel_dp);
DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
} }
...@@ -1339,7 +1367,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ...@@ -1339,7 +1367,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
DP_TRAINING_PATTERN_2)) DP_TRAINING_PATTERN_2))
break; break;
udelay(400); udelay(500);
if (!intel_dp_aux_handshake_required(intel_dp)) {
break;
} else {
if (!intel_dp_get_link_status(intel_dp)) if (!intel_dp_get_link_status(intel_dp))
break; break;
...@@ -1356,7 +1388,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp) ...@@ -1356,7 +1388,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
intel_get_adjust_train(intel_dp); intel_get_adjust_train(intel_dp);
++tries; ++tries;
} }
}
if (HAS_PCH_CPT(dev) && !is_edp(intel_dp)) if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
reg = DP | DP_LINK_TRAIN_OFF_CPT; reg = DP | DP_LINK_TRAIN_OFF_CPT;
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment