For DP alt mode display driver get the information about cable speed and cable type through TCSS_DDI_STATUS register which will be updated by type-c platform driver. Accodingly Update dpcd 0x110 with cable information before link training start. This change came part of DP2.1 SCR. Note: This patch is not tested due to unavailability of cable. Sending as RFC for design review. Signed-off-by: Animesh Manna <animesh.manna@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_ddi.c | 57 ++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_tc.c | 10 +++++ drivers/gpu/drm/i915/display/intel_tc.h | 1 + drivers/gpu/drm/i915/i915_reg.h | 5 +++ include/drm/display/drm_dp.h | 9 ++++ 5 files changed, 82 insertions(+) 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 -- 2.29.0