diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 70d44edd8c6e..3a0f6a3c9f98 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2208,6 +2208,55 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel
 			    str_enable_disable(enable));
 }
 
+#define CABLE_SPEED_SHIFT 4
+
+enum dp_cable_speed {
+	DP_CABLE_HBR3 = 1,
+	DP_CABLE_UHBR10,
+	DP_CABLE_GEN3_UHBR20,
+	DP_CABLE_GEN4_UHBR20
+};
+
+static void intel_dp_set_cable_attributes(struct intel_dp *intel_dp,
+					  u8 cable_attributes)
+{
+	u8 cable_speed;
+	bool active_cable, retimer;
+	u8 cable_attr_dpcd;
+
+	cable_speed = cable_attributes >> CABLE_SPEED_SHIFT;
+
+	switch (cable_speed) {
+	case DP_CABLE_HBR3:
+		cable_attr_dpcd = 0;
+		break;
+	case DP_CABLE_UHBR10:
+		cable_attr_dpcd = 1;
+		break;
+	case DP_CABLE_GEN3_UHBR20:
+	case DP_CABLE_GEN4_UHBR20:
+		cable_attr_dpcd = 2;
+		break;
+	default:
+		cable_attr_dpcd = 0;
+		break;
+	}
+
+	active_cable = (cable_attributes << TCSS_DDI_STATUS_CABLE_ATTR_SHIFT) &
+		       TCSS_DDI_STATUS_ACTIVE_CABLE;
+	retimer = (cable_attributes << TCSS_DDI_STATUS_CABLE_ATTR_SHIFT) &
+		  TCSS_DDI_STATUS_RETIMER_REDRIVER;
+	if (retimer && active_cable)
+		cable_attr_dpcd |= DP_CABLE_TYPE_RETIMER_ACTIVE;
+	else if (active_cable)
+		cable_attr_dpcd |= DP_CABLE_TYPE_LRD_ACTIVE;
+	else
+		cable_attr_dpcd |= DP_CABLE_TYPE_PASSIVE;
+
+	drm_dp_dpcd_writeb(&intel_dp->aux, DP_CABLE_ATTRIBUTES_UPDATED_BY_TX,
+			   cable_attr_dpcd);
+}
+
 static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
 					const struct intel_crtc_state *crtc_state)
 {
@@ -2414,6 +2463,7 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 
 	intel_dp_set_link_params(intel_dp,
 				 crtc_state->port_clock,
@@ -2480,6 +2530,13 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	intel_dp_check_frl_training(intel_dp);
 	intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
 
+	if (intel_tc_port_in_dp_alt_mode(dig_port)) {
+		u8 cable_attributes;
+
+		cable_attributes = intel_tc_get_cable_attributes(dig_port);
+		intel_dp_set_cable_attributes(intel_dp, cable_attributes);
+	}
+
 	/*
 	 * 6. The rest of the below are substeps under the bspec's "Enable and
 	 * Train Display Port" step.  Note that steps that are specific to
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index 3ebf41859043..6b10a8839563 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -260,6 +260,16 @@ assert_tc_port_power_enabled(struct intel_tc_port *tc)
 		    !intel_display_power_is_enabled(i915, tc_port_power_domain(tc)));
 }
 
+u8 intel_tc_get_cable_attributes(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+	enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
+
+	return (intel_de_read(i915, TCSS_DDI_STATUS(tc_port)) &
+		TCSS_DDI_STATUS_CABLE_ATTR_MASK) >>
+		TCSS_DDI_STATUS_CABLE_ATTR_SHIFT;
+}
+
 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h
index 3b16491925fa..edafe92844b4 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -43,5 +43,6 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy);
 void intel_tc_port_cleanup(struct intel_digital_port *dig_port);
 
 bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port);
+u8 intel_tc_get_cable_attributes(struct intel_digital_port *dig_port);
 
 #endif /* __INTEL_TC_H__ */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 0523418129c5..991ecf082b5c 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -6576,6 +6576,11 @@ enum skl_power_gate {
 #define TCSS_DDI_STATUS(tc)			_MMIO(_PICK_EVEN(tc, \
 								 _TCSS_DDI_STATUS_1, \
 								 _TCSS_DDI_STATUS_2))
+#define  TCSS_DDI_STATUS_CABLE_ATTR_SHIFT	9
+#define  TCSS_DDI_STATUS_CABLE_ATTR_MASK	REG_GENMASK(14, 9)
+#define  TCSS_DDI_STATUS_ACTIVE_CABLE		REG_BIT(11)
+#define  TCSS_DDI_STATUS_CABLE_TYPE		REG_BIT(10)
+#define  TCSS_DDI_STATUS_RETIMER_REDRIVER	REG_BIT(9)
 #define  TCSS_DDI_STATUS_READY			REG_BIT(2)
 #define  TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT	REG_BIT(1)
 #define  TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT	REG_BIT(0)
diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
index b046f79f4744..dde715d567c2 100644
--- a/include/drm/display/drm_dp.h
+++ b/include/drm/display/drm_dp.h
@@ -654,6 +654,13 @@
 # define DP_LANE13_POST_CURSOR2_SET_MASK    (3 << 4)
 # define DP_LANE13_MAX_POST_CURSOR2_REACHED (1 << 6)
 
+#define DP_CABLE_ATTRIBUTES_UPDATED_BY_TX   0x110
+# define DP_CABLE_TYPE_MASK		    (0x7 << 3)
+# define DP_CABLE_TYPE_UNKNOWN		    (0x0 << 3)
+# define DP_CABLE_TYPE_PASSIVE		    (0x1 << 3)
+# define DP_CABLE_TYPE_LRD_ACTIVE	    (0x2 << 3)
+# define DP_CABLE_TYPE_RETIMER_ACTIVE	    (0x3 << 3)
+
 #define DP_MSTM_CTRL			    0x111   /* 1.2 */
 # define DP_MST_EN			    (1 << 0)
 # define DP_UP_REQ_EN			    (1 << 1)
@@ -1139,6 +1146,8 @@
 # define DP_128B132B_TRAINING_AUX_RD_INTERVAL_32_MS             0x05
 # define DP_128B132B_TRAINING_AUX_RD_INTERVAL_64_MS             0x06
 
+#define DP_CABLE_ATTRIBUTES_UPDATED_BY_RX               0x2217 /* 2.1 */
+
 #define DP_TEST_264BIT_CUSTOM_PATTERN_7_0		0x2230
 #define DP_TEST_264BIT_CUSTOM_PATTERN_263_256	0x2250
 
