diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index b6b1ecfca652ea0cd03fc8ed1dd53babb4a3636b..d6826607efdad437edc1685a0fe1248c65067569 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1302,6 +1302,7 @@ struct intel_dp {
 	u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
 	u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE];
+	u8 lttpr_common_caps[DP_LTTPR_COMMON_CAP_SIZE];
 	u8 fec_capable;
 	/* source rates */
 	int num_source_rates;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 5a0a50d36dfb251f2f12c6d837852603f69517a2..2a7527108fa076cfcfac70945ac07498be690926 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4790,6 +4790,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 {
 	int ret;
 
+	intel_dp_lttpr_init(intel_dp);
+
 	if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd))
 		return false;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
index 71a8c9a546a332fa10aa6111bb52cceabee6d136..a19f0fd50c6931087795b8288f73239aed5145cf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
@@ -34,6 +34,55 @@ intel_dp_dump_link_status(const u8 link_status[DP_LINK_STATUS_SIZE])
 		      link_status[3], link_status[4], link_status[5]);
 }
 
+static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp)
+{
+	if (drm_dp_read_lttpr_common_caps(&intel_dp->aux,
+					  intel_dp->lttpr_common_caps) < 0) {
+		memset(intel_dp->lttpr_common_caps, 0,
+		       sizeof(intel_dp->lttpr_common_caps));
+		return false;
+	}
+
+	drm_dbg_kms(&dp_to_i915(intel_dp)->drm,
+		    "LTTPR common capabilities: %*ph\n",
+		    (int)sizeof(intel_dp->lttpr_common_caps),
+		    intel_dp->lttpr_common_caps);
+
+	return true;
+}
+
+static bool
+intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
+{
+	u8 val = enable ? DP_PHY_REPEATER_MODE_TRANSPARENT :
+			  DP_PHY_REPEATER_MODE_NON_TRANSPARENT;
+
+	return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
+}
+
+/**
+ * intel_dp_lttpr_init - detect LTTPRs and init the LTTPR link training mode
+ * @intel_dp: Intel DP struct
+ *
+ * Read the LTTPR common capabilities and switch to transparent link training
+ * mode.
+ */
+int intel_dp_lttpr_init(struct intel_dp *intel_dp)
+{
+	if (intel_dp_is_edp(intel_dp))
+		return 0;
+
+	intel_dp_read_lttpr_common_caps(intel_dp);
+
+	/*
+	 * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
+	 * non-transparent mode.
+	 */
+	intel_dp_set_lttpr_transparent_mode(intel_dp, true);
+
+	return 0;
+}
+
 static u8 dp_voltage_max(u8 preemph)
 {
 	switch (preemph & DP_TRAIN_PRE_EMPHASIS_MASK) {
@@ -492,6 +541,12 @@ static void intel_dp_schedule_fallback_link_training(struct intel_dp *intel_dp,
 void intel_dp_start_link_train(struct intel_dp *intel_dp,
 			       const struct intel_crtc_state *crtc_state)
 {
+	/*
+	 * TODO: Reiniting LTTPRs here won't be needed once proper connector
+	 * HW state readout is added.
+	 */
+	intel_dp_lttpr_init(intel_dp);
+
 	if (!intel_dp_link_train(intel_dp, crtc_state))
 		intel_dp_schedule_fallback_link_training(intel_dp, crtc_state);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.h b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
index bf9474e41aedf9a19e10ec7eed9ac151f9f2ab7c..b3fb1d125b9b2acb529abc3cbe041dd664fb09a0 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.h
@@ -11,6 +11,8 @@
 struct intel_crtc_state;
 struct intel_dp;
 
+int intel_dp_lttpr_init(struct intel_dp *intel_dp);
+
 void intel_dp_get_adjust_train(struct intel_dp *intel_dp,
 			       const struct intel_crtc_state *crtc_state,
 			       const u8 link_status[DP_LINK_STATUS_SIZE]);