> -----Original Message----- > From: Intel-gfx <intel-gfx-boun...@lists.freedesktop.org> On Behalf Of Imre > Deak > Sent: Tuesday, 5 August 2025 12.34 > To: intel-gfx@lists.freedesktop.org; intel...@lists.freedesktop.org > Cc: sta...@vger.kernel.org; Lin, Charlton <charlton....@intel.com>; > Almahallawy, Khaled <khaled.almahall...@intel.com> > Subject: [PATCH v2 02/19] drm/i915/icl+/tc: Cache the max lane count value > > The PHY's pin assignment value in the TCSS_DDI_STATUS register - as set by > the HW/FW based on the connected DP-alt sink's > TypeC/PD pin assignment negotiation - gets cleared by the HW/FW on LNL+ as > soon as the sink gets disconnected, even if the PHY > ownership got acquired already by the driver (and hence the PHY itself is > still connected and used by the display). This is similar to > how the PHY Ready flag gets cleared on LNL+ in the same register. > > To be able to query the max lane count value on LNL+ - which is based on the > above pin assignment - at all times even after the > sink gets disconnected, the max lane count must be determined and cached > during the PHY's HW readout and connect sequences. > Do that here, leaving the actual use of the cached value to a follow-up > change. > > v2: Don't read out the pin configuration if the PHY is disconnected. > > Cc: sta...@vger.kernel.org # v6.8+ > Reported-by: Charlton Lin <charlton....@intel.com> > Tested-by: Khaled Almahallawy <khaled.almahall...@intel.com>
Reviewed-by: Mika Kahola <mika.kah...@intel.com> > Signed-off-by: Imre Deak <imre.d...@intel.com> > --- > drivers/gpu/drm/i915/display/intel_tc.c | 57 +++++++++++++++++++++---- > 1 file changed, 48 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_tc.c > b/drivers/gpu/drm/i915/display/intel_tc.c > index 73a08bd84a70a..b8453fc3ab688 100644 > --- a/drivers/gpu/drm/i915/display/intel_tc.c > +++ b/drivers/gpu/drm/i915/display/intel_tc.c > @@ -66,6 +66,7 @@ struct intel_tc_port { > enum tc_port_mode init_mode; > enum phy_fia phy_fia; > u8 phy_fia_idx; > + u8 max_lane_count; > }; > > static enum intel_display_power_domain > @@ -365,12 +366,12 @@ static int intel_tc_port_get_max_lane_count(struct > intel_digital_port *dig_port) > } > } > > -int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) > +static int get_max_lane_count(struct intel_tc_port *tc) > { > - struct intel_display *display = to_intel_display(dig_port); > - struct intel_tc_port *tc = to_tc_port(dig_port); > + struct intel_display *display = to_intel_display(tc->dig_port); > + struct intel_digital_port *dig_port = tc->dig_port; > > - if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) > + if (tc->mode != TC_PORT_DP_ALT) > return 4; > > assert_tc_cold_blocked(tc); > @@ -384,6 +385,21 @@ int intel_tc_port_max_lane_count(struct > intel_digital_port *dig_port) > return intel_tc_port_get_max_lane_count(dig_port); > } > > +static void read_pin_configuration(struct intel_tc_port *tc) { > + tc->max_lane_count = get_max_lane_count(tc); } > + > +int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port) { > + struct intel_tc_port *tc = to_tc_port(dig_port); > + > + if (!intel_encoder_is_tc(&dig_port->base)) > + return 4; > + > + return get_max_lane_count(tc); > +} > + > void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port, > int required_lanes) > { > @@ -596,9 +612,12 @@ static void icl_tc_phy_get_hw_state(struct intel_tc_port > *tc) > tc_cold_wref = __tc_cold_block(tc, &domain); > > tc->mode = tc_phy_get_current_mode(tc); > - if (tc->mode != TC_PORT_DISCONNECTED) > + if (tc->mode != TC_PORT_DISCONNECTED) { > tc->lock_wakeref = tc_cold_block(tc); > > + read_pin_configuration(tc); > + } > + > __tc_cold_unblock(tc, domain, tc_cold_wref); } > > @@ -656,8 +675,11 @@ static bool icl_tc_phy_connect(struct intel_tc_port *tc, > > tc->lock_wakeref = tc_cold_block(tc); > > - if (tc->mode == TC_PORT_TBT_ALT) > + if (tc->mode == TC_PORT_TBT_ALT) { > + read_pin_configuration(tc); > + > return true; > + } > > if ((!tc_phy_is_ready(tc) || > !icl_tc_phy_take_ownership(tc, true)) && @@ -668,6 +690,7 @@ > static bool icl_tc_phy_connect(struct intel_tc_port > *tc, > goto out_unblock_tc_cold; > } > > + read_pin_configuration(tc); > > if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) > goto out_release_phy; > @@ -858,9 +881,12 @@ static void adlp_tc_phy_get_hw_state(struct > intel_tc_port *tc) > port_wakeref = intel_display_power_get(display, port_power_domain); > > tc->mode = tc_phy_get_current_mode(tc); > - if (tc->mode != TC_PORT_DISCONNECTED) > + if (tc->mode != TC_PORT_DISCONNECTED) { > tc->lock_wakeref = tc_cold_block(tc); > > + read_pin_configuration(tc); > + } > + > intel_display_power_put(display, port_power_domain, port_wakeref); } > > @@ -873,6 +899,9 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, > int required_lanes) > > if (tc->mode == TC_PORT_TBT_ALT) { > tc->lock_wakeref = tc_cold_block(tc); > + > + read_pin_configuration(tc); > + > return true; > } > > @@ -894,6 +923,8 @@ static bool adlp_tc_phy_connect(struct intel_tc_port *tc, > int required_lanes) > > tc->lock_wakeref = tc_cold_block(tc); > > + read_pin_configuration(tc); > + > if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) > goto out_unblock_tc_cold; > > @@ -1124,9 +1155,12 @@ static void xelpdp_tc_phy_get_hw_state(struct > intel_tc_port *tc) > tc_cold_wref = __tc_cold_block(tc, &domain); > > tc->mode = tc_phy_get_current_mode(tc); > - if (tc->mode != TC_PORT_DISCONNECTED) > + if (tc->mode != TC_PORT_DISCONNECTED) { > tc->lock_wakeref = tc_cold_block(tc); > > + read_pin_configuration(tc); > + } > + > drm_WARN_ON(display->drm, > (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) > && > !xelpdp_tc_phy_tcss_power_is_enabled(tc)); > @@ -1138,14 +1172,19 @@ static bool xelpdp_tc_phy_connect(struct > intel_tc_port *tc, int required_lanes) { > tc->lock_wakeref = tc_cold_block(tc); > > - if (tc->mode == TC_PORT_TBT_ALT) > + if (tc->mode == TC_PORT_TBT_ALT) { > + read_pin_configuration(tc); > + > return true; > + } > > if (!xelpdp_tc_phy_enable_tcss_power(tc, true)) > goto out_unblock_tccold; > > xelpdp_tc_phy_take_ownership(tc, true); > > + read_pin_configuration(tc); > + > if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes)) > goto out_release_phy; > > -- > 2.49.1