Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+89 −57
Original line number Diff line number Diff line
@@ -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;
	}

	/* 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 (clock = 0; clock <= max_clock; clock++) {
			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,
		}
	}

	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;
}

@@ -1088,11 +1086,21 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
}

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;
	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:
	default:
		signal_levels |= DP_VOLTAGE_0_4;
@@ -1107,7 +1115,7 @@ intel_dp_signal_levels(uint8_t train_set, int lane_count)
		signal_levels |= DP_VOLTAGE_1_2;
		break;
	}
	switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) {
	switch (preemphasis) {
	case DP_TRAIN_PRE_EMPHASIS_0:
	default:
		signal_levels |= DP_PRE_EMPHASIS_0;
@@ -1193,6 +1201,18 @@ intel_channel_eq_ok(struct intel_dp *intel_dp)
	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
intel_dp_set_link_train(struct intel_dp *intel_dp,
			uint32_t dp_reg_value,
@@ -1205,6 +1225,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
	I915_WRITE(intel_dp->output_reg, dp_reg_value);
	POSTING_READ(intel_dp->output_reg);

	if (!intel_dp_aux_handshake_required(intel_dp))
		return true;

	intel_dp_aux_native_write_1(intel_dp,
				    DP_TRAINING_PATTERN_SET,
				    dp_train_pat);
@@ -1237,6 +1260,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
	POSTING_READ(intel_dp->output_reg);
	intel_wait_for_vblank(dev, intel_crtc->pipe);

	if (intel_dp_aux_handshake_required(intel_dp))
		/* Write the link configuration data */
		intel_dp_aux_native_write(intel_dp, DP_LINK_BW_SET,
					  intel_dp->link_configuration,
@@ -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]);
			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
		} 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;
		}

@@ -1272,7 +1296,10 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
			break;
		/* 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))
				break;

@@ -1300,6 +1327,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
			/* Compute new intel_dp->train_set as requested by target */
			intel_get_adjust_train(intel_dp);
		}
	}

	intel_dp->DP = 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]);
			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
		} 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;
		}

@@ -1339,7 +1367,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
					     DP_TRAINING_PATTERN_2))
			break;

		udelay(400);
		udelay(500);

		if (!intel_dp_aux_handshake_required(intel_dp)) {
			break;
		} else {
			if (!intel_dp_get_link_status(intel_dp))
				break;

@@ -1356,7 +1388,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
			intel_get_adjust_train(intel_dp);
			++tries;
		}

	}
	if (HAS_PCH_CPT(dev) && !is_edp(intel_dp))
		reg = DP | DP_LINK_TRAIN_OFF_CPT;
	else