diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index 0d524735dcf9..27be2a490297 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -2197,17 +2197,30 @@ static int readout_enabled_lane_count(struct intel_encoder *encoder) { struct intel_display *display = to_intel_display(encoder); u8 enabled_tx_lane_count = 0; - int max_tx_lane_count; + int max_tx_lane_count = 4; + bool lane_reversal; int tx_lane; + lane_reversal = intel_de_read(display, XELPDP_PORT_BUF_CTL1(display, encoder->port)) & + XELPDP_PORT_REVERSAL; + /* * TODO: also check inactive TX lanes in all PHY lanes owned by the * display. For now checking only those PHY lane(s) which are owned * based on the active TX lane count (i.e. * 1,2 active TX lanes -> PHY lane#0 * 3,4 active TX lanes -> PHY lane#0 and PHY lane#1). + * + * In case of lane reversal for 1, 2 active TX lanes, only PHY + * lane#1 is used. This is only possible in TypeC legacy mode or if + * the port is connected to a non-TC PHY. In both of these cases both + * PHY lane#0 and #1 are owned by display, so check all 4 TX lanes in + * both PHY lanes in those cases. */ - max_tx_lane_count = DDI_PORT_WIDTH_GET(intel_de_read(display, DDI_BUF_CTL(encoder->port))); + if (!lane_reversal) + max_tx_lane_count = DDI_PORT_WIDTH_GET(intel_de_read(display, + DDI_BUF_CTL(encoder->port))); + if (!drm_WARN_ON(display->drm, max_tx_lane_count == 0)) max_tx_lane_count = round_up(max_tx_lane_count, 2); @@ -3214,6 +3227,13 @@ static void intel_cx0pll_enable(struct intel_encoder *encoder, INTEL_CX0_LANE0; intel_wakeref_t wakeref = intel_cx0_phy_transaction_begin(encoder); + /* + * Lane reversal is never used in DP-alt mode, in that case the + * corresponding lane swapping (based on the TypeC cable flip state + * for instance) is handled automatically by the HW via a TCSS mux. + */ + drm_WARN_ON(display->drm, lane_reversal && intel_tc_port_in_dp_alt_mode(dig_port)); + /* * 1. Program PORT_CLOCK_CTL REGISTER to configure * clock muxes, gating and SSC