]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/i915/ltphy: Enable/Disable Tx after Non TBT Enable sequence
authorSuraj Kandpal <suraj.kandpal@intel.com>
Sat, 1 Nov 2025 03:25:08 +0000 (08:55 +0530)
committerSuraj Kandpal <suraj.kandpal@intel.com>
Sat, 1 Nov 2025 03:34:17 +0000 (09:04 +0530)
We need to enable and disable the Tx for each active lane after the
Non-TBT enable sequence is done.

Bspec: 74500, 74497, 74701
Signed-off-by: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Arun R Murthy <arun.r.murthy@intel.com>
Link: https://patch.msgid.link/20251101032513.4171255-21-suraj.kandpal@intel.com
drivers/gpu/drm/i915/display/intel_lt_phy.c
drivers/gpu/drm/i915/display/intel_lt_phy_regs.h

index eb6ec4de8045abb1ebb22d2bb6ea64840123e1da..5f75e72abd343111de888c541631a15b73e67dda 100644 (file)
@@ -1507,6 +1507,92 @@ intel_lt_phy_program_pll(struct intel_encoder *encoder,
        }
 }
 
+static void
+intel_lt_phy_enable_disable_tx(struct intel_encoder *encoder,
+                              const struct intel_crtc_state *crtc_state)
+{
+       struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+       bool lane_reversal = dig_port->lane_reversal;
+       u8 lane_count = crtc_state->lane_count;
+       bool is_dp_alt =
+               intel_tc_port_in_dp_alt_mode(dig_port);
+       enum intel_tc_pin_assignment tc_pin =
+               intel_tc_port_get_pin_assignment(dig_port);
+       u8 transmitter_mask = 0;
+
+       /*
+        * We have a two transmitters per lane and total of 2 PHY lanes so a total
+        * of 4 transmitters. We prepare a mask of the lanes that need to be activated
+        * and the transmitter which need to be activated for each lane. TX 0,1 correspond
+        * to LANE0 and TX 2, 3 correspond to LANE1.
+        */
+
+       switch (lane_count) {
+       case 1:
+               transmitter_mask = lane_reversal ? REG_BIT8(3) : REG_BIT8(0);
+               if (is_dp_alt) {
+                       if (tc_pin == INTEL_TC_PIN_ASSIGNMENT_D)
+                               transmitter_mask = REG_BIT8(0);
+                       else
+                               transmitter_mask = REG_BIT8(1);
+               }
+               break;
+       case 2:
+               transmitter_mask = lane_reversal ? REG_GENMASK8(3, 2) : REG_GENMASK8(1, 0);
+               if (is_dp_alt)
+                       transmitter_mask = REG_GENMASK8(1, 0);
+               break;
+       case 3:
+               transmitter_mask = lane_reversal ? REG_GENMASK8(3, 1) : REG_GENMASK8(2, 0);
+               if (is_dp_alt)
+                       transmitter_mask = REG_GENMASK8(2, 0);
+               break;
+       case 4:
+               transmitter_mask = REG_GENMASK8(3, 0);
+               break;
+       default:
+               MISSING_CASE(lane_count);
+               transmitter_mask = REG_GENMASK8(3, 0);
+               break;
+       }
+
+       if (transmitter_mask & BIT(0)) {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(0),
+                                      LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(0),
+                                      LT_PHY_TX_LANE_ENABLE);
+       } else {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(0),
+                                      0, LT_PHY_TXY_CTL10_MAC(0), 0);
+       }
+
+       if (transmitter_mask & BIT(1)) {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(1),
+                                      LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(1),
+                                      LT_PHY_TX_LANE_ENABLE);
+       } else {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE0, LT_PHY_TXY_CTL10(1),
+                                      0, LT_PHY_TXY_CTL10_MAC(1), 0);
+       }
+
+       if (transmitter_mask & BIT(2)) {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(0),
+                                      LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(0),
+                                      LT_PHY_TX_LANE_ENABLE);
+       } else {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(0),
+                                      0, LT_PHY_TXY_CTL10_MAC(0), 0);
+       }
+
+       if (transmitter_mask & BIT(3)) {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(1),
+                                      LT_PHY_TX_LANE_ENABLE, LT_PHY_TXY_CTL10_MAC(1),
+                                      LT_PHY_TX_LANE_ENABLE);
+       } else {
+               intel_lt_phy_p2p_write(encoder, INTEL_LT_PHY_LANE1, LT_PHY_TXY_CTL10(1),
+                                      0, LT_PHY_TXY_CTL10_MAC(1), 0);
+       }
+}
+
 void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
                             const struct intel_crtc_state *crtc_state)
 {
@@ -1633,6 +1719,7 @@ void intel_lt_phy_pll_enable(struct intel_encoder *encoder,
        intel_lt_phy_powerdown_change_sequence(encoder, owned_lane_mask,
                                               XELPDP_P0_STATE_ACTIVE);
 
+       intel_lt_phy_enable_disable_tx(encoder, crtc_state);
        intel_lt_phy_transaction_end(encoder, wakeref);
 }
 
index da83a7c5faa3eb2bed8f58ff4eb4ebf117bf1887..9223487d764e22560c608bc9f0b85458359addae 100644 (file)
 #define  LT_PHY_TX_CURSOR_MASK         REG_GENMASK8(5, 0)
 #define  LT_PHY_TX_CURSOR(val)         REG_FIELD_PREP8(LT_PHY_TX_CURSOR_MASK, val)
 
+#define LT_PHY_TXY_CTL10(idx)          (0x40A + (0x200 * (idx)))
+#define LT_PHY_TXY_CTL10_MAC(idx)      _MMIO(LT_PHY_TXY_CTL10(idx))
+#define  LT_PHY_TX_LANE_ENABLE         REG_BIT8(0)
+
 /* LT Phy Vendor Register */
 #define LT_PHY_VDR_0_CONFIG    0xC02
 #define  LT_PHY_VDR_DP_PLL_ENABLE      REG_BIT(7)