Lines Matching +full:s +full:- +full:mode
1 // SPDX-License-Identifier: MIT
52 struct mutex lock; /* protects the TypeC port mode */
62 enum tc_port_mode mode; member
75 static const char *tc_port_mode_name(enum tc_port_mode mode) in tc_port_mode_name() argument
79 [TC_PORT_TBT_ALT] = "tbt-alt", in tc_port_mode_name()
80 [TC_PORT_DP_ALT] = "dp-alt", in tc_port_mode_name()
84 if (WARN_ON(mode >= ARRAY_SIZE(names))) in tc_port_mode_name()
85 mode = TC_PORT_DISCONNECTED; in tc_port_mode_name()
87 return names[mode]; in tc_port_mode_name()
92 return dig_port->tc; in to_tc_port()
97 return to_i915(tc->dig_port->base.base.dev); in tc_to_i915()
101 enum tc_port_mode mode) in intel_tc_port_in_mode() argument
103 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_in_mode()
104 enum phy phy = intel_port_to_phy(i915, dig_port->base.port); in intel_tc_port_in_mode()
107 return intel_phy_is_tc(i915, phy) && tc->mode == mode; in intel_tc_port_in_mode()
127 * platform and TC mode (legacy, DP-alt, TBT):
130 * --------------------------
132 * - TCSS/IOM access for PHY ready state.
134 * - DE/north-,south-HPD ISR access for HPD live state.
137 * -----------------------------------
139 * - DE/DDI_BUF access for port enabled state.
141 * - DE/DDI_BUF access for PHY owned state.
144 * -------------------------------------
145 * ICL/legacy mode:
146 * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
147 * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
149 * ADLP/legacy, DP-alt modes:
150 * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
154 * -------------------------
155 * ICL/DP-alt, TBT mode:
156 * - TCSS/TBT: block TC-cold power state for using the (direct or
157 * TBT DP-IN) AUX and main lanes.
160 * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
161 * - TCSS/PHY: block TC-cold power state for using the (direct or
162 * TBT DP-IN) AUX and main lanes.
164 * ADLP/TBT mode:
165 * - TCSS/TBT: block TC-cold power state for using the (TBT DP-IN)
169 * - TCSS/IOM,FIA access for PHY ready, owned state
170 * - TCSS/PHY: block TC-cold power state for using the (direct or
171 * TBT DP-IN) AUX and main lanes.
175 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_cold_requires_aux_pw()
179 intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); in intel_tc_cold_requires_aux_pw()
200 tc->lock_power_domain = domain; in tc_cold_block()
220 drm_WARN_ON(&tc_to_i915(tc)->drm, tc->lock_power_domain != domain); in tc_cold_unblock()
230 drm_WARN_ON(&i915->drm, in assert_display_core_power_enabled()
242 drm_WARN_ON(&i915->drm, !enabled); in assert_tc_cold_blocked()
249 enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port); in tc_port_power_domain()
251 return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1; in tc_port_power_domain()
259 drm_WARN_ON(&i915->drm, in assert_tc_port_power_enabled()
265 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_get_lane_mask()
269 lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); in intel_tc_port_get_lane_mask()
271 drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff); in intel_tc_port_get_lane_mask()
274 lane_mask &= DP_LANE_ASSIGNMENT_MASK(tc->phy_fia_idx); in intel_tc_port_get_lane_mask()
275 return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(tc->phy_fia_idx); in intel_tc_port_get_lane_mask()
280 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_get_pin_assignment_mask()
284 pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(tc->phy_fia)); in intel_tc_port_get_pin_assignment_mask()
286 drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff); in intel_tc_port_get_pin_assignment_mask()
289 return (pin_mask & DP_PIN_ASSIGNMENT_MASK(tc->phy_fia_idx)) >> in intel_tc_port_get_pin_assignment_mask()
290 DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx); in intel_tc_port_get_pin_assignment_mask()
295 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in lnl_tc_port_get_max_lane_count()
296 enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port); in lnl_tc_port_get_max_lane_count()
320 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in mtl_tc_port_get_max_lane_count()
341 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_get_max_lane_count()
367 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_max_lane_count()
369 enum phy phy = intel_port_to_phy(i915, dig_port->base.port); in intel_tc_port_max_lane_count()
371 if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT) in intel_tc_port_max_lane_count()
388 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_set_fia_lane_count()
390 bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; in intel_tc_port_set_fia_lane_count()
393 drm_WARN_ON(&i915->drm, in intel_tc_port_set_fia_lane_count()
394 lane_reversal && tc->mode != TC_PORT_LEGACY); in intel_tc_port_set_fia_lane_count()
398 val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia)); in intel_tc_port_set_fia_lane_count()
399 val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
404 DFLEXDPMLE1_DPMLETC_ML3(tc->phy_fia_idx) : in intel_tc_port_set_fia_lane_count()
405 DFLEXDPMLE1_DPMLETC_ML0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
409 DFLEXDPMLE1_DPMLETC_ML3_2(tc->phy_fia_idx) : in intel_tc_port_set_fia_lane_count()
410 DFLEXDPMLE1_DPMLETC_ML1_0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
413 val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
419 intel_de_write(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia), val); in intel_tc_port_set_fia_lane_count()
428 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); in tc_port_fixup_legacy_flag()
433 if (tc->legacy_port) in tc_port_fixup_legacy_flag()
443 drm_dbg_kms(&i915->drm, in tc_port_fixup_legacy_flag()
444 "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n", in tc_port_fixup_legacy_flag()
445 tc->port_name, live_status_mask, valid_hpd_mask); in tc_port_fixup_legacy_flag()
447 tc->legacy_port = !tc->legacy_port; in tc_port_fixup_legacy_flag()
453 enum port port = tc->dig_port->base.port; in tc_phy_load_fia_params()
461 tc->phy_fia = tc_port / 2; in tc_phy_load_fia_params()
462 tc->phy_fia_idx = tc_port % 2; in tc_phy_load_fia_params()
464 tc->phy_fia = FIA1; in tc_phy_load_fia_params()
465 tc->phy_fia_idx = tc_port; in tc_phy_load_fia_params()
471 * -------------------
477 struct intel_digital_port *dig_port = tc->dig_port; in icl_tc_phy_cold_off_domain()
479 if (tc->legacy_port) in icl_tc_phy_cold_off_domain()
480 return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); in icl_tc_phy_cold_off_domain()
488 struct intel_digital_port *dig_port = tc->dig_port; in icl_tc_phy_hpd_live_status()
489 u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; in icl_tc_phy_hpd_live_status()
496 fia_isr = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); in icl_tc_phy_hpd_live_status()
501 drm_dbg_kms(&i915->drm, in icl_tc_phy_hpd_live_status()
502 "Port %s: PHY in TCCOLD, nothing connected\n", in icl_tc_phy_hpd_live_status()
503 tc->port_name); in icl_tc_phy_hpd_live_status()
507 if (fia_isr & TC_LIVE_STATE_TBT(tc->phy_fia_idx)) in icl_tc_phy_hpd_live_status()
509 if (fia_isr & TC_LIVE_STATE_TC(tc->phy_fia_idx)) in icl_tc_phy_hpd_live_status()
520 * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink
521 * is connected and it's ready to switch the ownership to display. The flag
522 * will be left cleared when a TBT-alt sink is connected, where the PHY is
533 val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(tc->phy_fia)); in icl_tc_phy_is_ready()
535 drm_dbg_kms(&i915->drm, in icl_tc_phy_is_ready()
536 "Port %s: PHY in TCCOLD, assuming not ready\n", in icl_tc_phy_is_ready()
537 tc->port_name); in icl_tc_phy_is_ready()
541 return val & DP_PHY_MODE_STATUS_COMPLETED(tc->phy_fia_idx); in icl_tc_phy_is_ready()
552 val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); in icl_tc_phy_take_ownership()
554 drm_dbg_kms(&i915->drm, in icl_tc_phy_take_ownership()
555 "Port %s: PHY in TCCOLD, can't %s ownership\n", in icl_tc_phy_take_ownership()
556 tc->port_name, take ? "take" : "release"); in icl_tc_phy_take_ownership()
561 val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_take_ownership()
563 val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_take_ownership()
565 intel_de_write(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia), val); in icl_tc_phy_take_ownership()
577 val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); in icl_tc_phy_is_owned()
579 drm_dbg_kms(&i915->drm, in icl_tc_phy_is_owned()
580 "Port %s: PHY in TCCOLD, assume not owned\n", in icl_tc_phy_is_owned()
581 tc->port_name); in icl_tc_phy_is_owned()
585 return val & DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_is_owned()
595 tc->mode = tc_phy_get_current_mode(tc); in icl_tc_phy_get_hw_state()
596 if (tc->mode != TC_PORT_DISCONNECTED) in icl_tc_phy_get_hw_state()
597 tc->lock_wakeref = tc_cold_block(tc); in icl_tc_phy_get_hw_state()
607 * Unlike the other ports, type-C ports are not available to use as soon as we
608 * get a hotplug. The type-C PHYs can be shared between multiple controllers:
611 * set the type-C power state.
617 struct intel_digital_port *dig_port = tc->dig_port; in tc_phy_verify_legacy_or_dp_alt_mode()
621 if (tc->mode == TC_PORT_LEGACY) { in tc_phy_verify_legacy_or_dp_alt_mode()
622 drm_WARN_ON(&i915->drm, max_lanes != 4); in tc_phy_verify_legacy_or_dp_alt_mode()
626 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DP_ALT); in tc_phy_verify_legacy_or_dp_alt_mode()
629 * Now we have to re-check the live state, in case the port recently in tc_phy_verify_legacy_or_dp_alt_mode()
630 * became disconnected. Not necessary for legacy mode. in tc_phy_verify_legacy_or_dp_alt_mode()
633 drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n", in tc_phy_verify_legacy_or_dp_alt_mode()
634 tc->port_name); in tc_phy_verify_legacy_or_dp_alt_mode()
639 drm_dbg_kms(&i915->drm, in tc_phy_verify_legacy_or_dp_alt_mode()
640 "Port %s: PHY max lanes %d < required lanes %d\n", in tc_phy_verify_legacy_or_dp_alt_mode()
641 tc->port_name, in tc_phy_verify_legacy_or_dp_alt_mode()
654 tc->lock_wakeref = tc_cold_block(tc); in icl_tc_phy_connect()
656 if (tc->mode == TC_PORT_TBT_ALT) in icl_tc_phy_connect()
661 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in icl_tc_phy_connect()
662 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership (ready %s)\n", in icl_tc_phy_connect()
663 tc->port_name, in icl_tc_phy_connect()
677 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in icl_tc_phy_connect()
688 switch (tc->mode) { in icl_tc_phy_disconnect()
694 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in icl_tc_phy_disconnect()
697 MISSING_CASE(tc->mode); in icl_tc_phy_disconnect()
719 * -------------------
736 drm_WARN_ON(&i915->drm, val == 0xffffffff); in tgl_tc_phy_init()
754 * --------------------
760 struct intel_digital_port *dig_port = tc->dig_port; in adlp_tc_phy_cold_off_domain()
762 if (tc->mode != TC_PORT_TBT_ALT) in adlp_tc_phy_cold_off_domain()
763 return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); in adlp_tc_phy_cold_off_domain()
771 struct intel_digital_port *dig_port = tc->dig_port; in adlp_tc_phy_hpd_live_status()
772 enum hpd_pin hpd_pin = dig_port->base.hpd_pin; in adlp_tc_phy_hpd_live_status()
773 u32 cpu_isr_bits = i915->display.hotplug.hpd[hpd_pin]; in adlp_tc_phy_hpd_live_status()
774 u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; in adlp_tc_phy_hpd_live_status()
798 * PHY ownership. The IOM firmware sets this flag when it's ready to switch
799 * the ownership to display, regardless of what sink is connected (TBT-alt,
800 * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT
806 enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port); in adlp_tc_phy_is_ready()
813 drm_dbg_kms(&i915->drm, in adlp_tc_phy_is_ready()
814 "Port %s: PHY in TCCOLD, assuming not ready\n", in adlp_tc_phy_is_ready()
815 tc->port_name); in adlp_tc_phy_is_ready()
826 enum port port = tc->dig_port->base.port; in adlp_tc_phy_take_ownership()
839 enum port port = tc->dig_port->base.port; in adlp_tc_phy_is_owned()
857 tc->mode = tc_phy_get_current_mode(tc); in adlp_tc_phy_get_hw_state()
858 if (tc->mode != TC_PORT_DISCONNECTED) in adlp_tc_phy_get_hw_state()
859 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_get_hw_state()
871 if (tc->mode == TC_PORT_TBT_ALT) { in adlp_tc_phy_connect()
872 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_connect()
879 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in adlp_tc_phy_connect()
880 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership\n", in adlp_tc_phy_connect()
881 tc->port_name); in adlp_tc_phy_connect()
886 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in adlp_tc_phy_connect()
887 drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n", in adlp_tc_phy_connect()
888 tc->port_name); in adlp_tc_phy_connect()
892 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_connect()
902 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in adlp_tc_phy_connect()
920 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in adlp_tc_phy_disconnect()
922 switch (tc->mode) { in adlp_tc_phy_disconnect()
930 MISSING_CASE(tc->mode); in adlp_tc_phy_disconnect()
954 * ----------------------
959 struct intel_digital_port *dig_port = tc->dig_port; in xelpdp_tc_phy_hpd_live_status()
960 enum hpd_pin hpd_pin = dig_port->base.hpd_pin; in xelpdp_tc_phy_hpd_live_status()
961 u32 pica_isr_bits = i915->display.hotplug.hpd[hpd_pin]; in xelpdp_tc_phy_hpd_live_status()
962 u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; in xelpdp_tc_phy_hpd_live_status()
978 if (tc->legacy_port && (pch_isr & pch_isr_bit)) in xelpdp_tc_phy_hpd_live_status()
988 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_tcss_power_is_enabled()
1001 drm_dbg_kms(&i915->drm, in xelpdp_tc_phy_wait_for_tcss_power()
1002 "Port %s: timeout waiting for TCSS power to get %s\n", in xelpdp_tc_phy_wait_for_tcss_power()
1004 tc->port_name); in xelpdp_tc_phy_wait_for_tcss_power()
1014 enum port port = tc->dig_port->base.port; in __xelpdp_tc_phy_enable_tcss_power()
1042 if (drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) in xelpdp_tc_phy_enable_tcss_power()
1057 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_take_ownership()
1073 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_is_owned()
1088 tc->mode = tc_phy_get_current_mode(tc); in xelpdp_tc_phy_get_hw_state()
1089 if (tc->mode != TC_PORT_DISCONNECTED) in xelpdp_tc_phy_get_hw_state()
1090 tc->lock_wakeref = tc_cold_block(tc); in xelpdp_tc_phy_get_hw_state()
1092 drm_WARN_ON(&i915->drm, in xelpdp_tc_phy_get_hw_state()
1093 (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) && in xelpdp_tc_phy_get_hw_state()
1101 tc->lock_wakeref = tc_cold_block(tc); in xelpdp_tc_phy_connect()
1103 if (tc->mode == TC_PORT_TBT_ALT) in xelpdp_tc_phy_connect()
1121 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in xelpdp_tc_phy_connect()
1128 switch (tc->mode) { in xelpdp_tc_phy_disconnect()
1135 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in xelpdp_tc_phy_disconnect()
1138 MISSING_CASE(tc->mode); in xelpdp_tc_phy_disconnect()
1155 * -----------------------
1160 return tc->phy_ops->cold_off_domain(tc); in tc_phy_cold_off_domain()
1168 mask = tc->phy_ops->hpd_live_status(tc); in tc_phy_hpd_live_status()
1170 /* The sink can be connected only in a single mode. */ in tc_phy_hpd_live_status()
1171 drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1); in tc_phy_hpd_live_status()
1178 return tc->phy_ops->is_ready(tc); in tc_phy_is_ready()
1183 return tc->phy_ops->is_owned(tc); in tc_phy_is_owned()
1188 tc->phy_ops->get_hw_state(tc); in tc_phy_get_hw_state()
1196 drm_WARN_ON(&i915->drm, phy_is_owned && !phy_is_ready); in tc_phy_is_ready_and_owned()
1204 struct intel_encoder *encoder = &tc->dig_port->base; in tc_phy_is_connected()
1205 struct drm_i915_private *i915 = to_i915(encoder->base.dev); in tc_phy_is_connected()
1215 drm_dbg_kms(&i915->drm, in tc_phy_is_connected()
1216 "Port %s: PHY connected: %s (ready: %s, owned: %s, pll_type: %s)\n", in tc_phy_is_connected()
1217 tc->port_name, in tc_phy_is_connected()
1221 port_pll_type == ICL_PORT_DPLL_DEFAULT ? "tbt" : "non-tbt"); in tc_phy_is_connected()
1231 drm_err(&i915->drm, "Port %s: timeout waiting for PHY ready\n", in tc_phy_wait_for_ready()
1232 tc->port_name); in tc_phy_wait_for_ready()
1244 return fls(live_status_mask) - 1; in hpd_mask_to_tc_mode()
1270 if (tc->legacy_port) in get_tc_mode_in_phy_owned_state()
1291 if (tc->legacy_port) in get_tc_mode_in_phy_not_owned_state()
1305 enum tc_port_mode mode; in tc_phy_get_current_mode() local
1308 * For legacy ports the IOM firmware initializes the PHY during boot-up in tc_phy_get_current_mode()
1312 if (tc->legacy_port) in tc_phy_get_current_mode()
1319 mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); in tc_phy_get_current_mode()
1321 drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT); in tc_phy_get_current_mode()
1322 mode = get_tc_mode_in_phy_owned_state(tc, live_mode); in tc_phy_get_current_mode()
1325 drm_dbg_kms(&i915->drm, in tc_phy_get_current_mode()
1326 "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n", in tc_phy_get_current_mode()
1327 tc->port_name, in tc_phy_get_current_mode()
1328 tc_port_mode_name(mode), in tc_phy_get_current_mode()
1333 return mode; in tc_phy_get_current_mode()
1338 if (tc->legacy_port) in default_tc_mode()
1347 enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask); in hpd_mask_to_target_mode() local
1349 if (mode != TC_PORT_DISCONNECTED) in hpd_mask_to_target_mode()
1350 return mode; in hpd_mask_to_target_mode()
1371 tc->mode = hpd_mask_to_target_mode(tc, live_status_mask); in tc_phy_connect()
1373 connected = tc->phy_ops->connect(tc, required_lanes); in tc_phy_connect()
1374 if (!connected && tc->mode != default_tc_mode(tc)) { in tc_phy_connect()
1375 tc->mode = default_tc_mode(tc); in tc_phy_connect()
1376 connected = tc->phy_ops->connect(tc, required_lanes); in tc_phy_connect()
1379 drm_WARN_ON(&i915->drm, !connected); in tc_phy_connect()
1384 if (tc->mode != TC_PORT_DISCONNECTED) { in tc_phy_disconnect()
1385 tc->phy_ops->disconnect(tc); in tc_phy_disconnect()
1386 tc->mode = TC_PORT_DISCONNECTED; in tc_phy_disconnect()
1392 mutex_lock(&tc->lock); in tc_phy_init()
1393 tc->phy_ops->init(tc); in tc_phy_init()
1394 mutex_unlock(&tc->lock); in tc_phy_init()
1401 struct intel_digital_port *dig_port = tc->dig_port; in intel_tc_port_reset_mode()
1402 enum tc_port_mode old_tc_mode = tc->mode; in intel_tc_port_reset_mode()
1411 drm_WARN_ON(&i915->drm, aux_powered); in intel_tc_port_reset_mode()
1418 drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n", in intel_tc_port_reset_mode()
1419 tc->port_name, in intel_tc_port_reset_mode()
1421 tc_port_mode_name(tc->mode)); in intel_tc_port_reset_mode()
1426 return tc_phy_get_target_mode(tc) != tc->mode; in intel_tc_port_needs_reset()
1439 tc->link_refcount++; in __intel_tc_port_get_link()
1444 tc->link_refcount--; in __intel_tc_port_put_link()
1450 struct intel_digital_port *dig_port = tc->dig_port; in tc_port_is_enabled()
1454 return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) & in tc_port_is_enabled()
1459 * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
1462 * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
1467 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_init_mode()
1471 mutex_lock(&tc->lock); in intel_tc_port_init_mode()
1473 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); in intel_tc_port_init_mode()
1474 drm_WARN_ON(&i915->drm, tc->lock_wakeref); in intel_tc_port_init_mode()
1475 drm_WARN_ON(&i915->drm, tc->link_refcount); in intel_tc_port_init_mode()
1479 * Save the initial mode for the state check in in intel_tc_port_init_mode()
1482 tc->init_mode = tc->mode; in intel_tc_port_init_mode()
1486 * MST topology resume, but the PHY mode can only be changed if the in intel_tc_port_init_mode()
1497 } else if (tc->mode == TC_PORT_DISCONNECTED) { in intel_tc_port_init_mode()
1498 drm_WARN_ON(&i915->drm, !tc->legacy_port); in intel_tc_port_init_mode()
1499 drm_err(&i915->drm, in intel_tc_port_init_mode()
1500 "Port %s: PHY disconnected on enabled port, connecting it\n", in intel_tc_port_init_mode()
1501 tc->port_name); in intel_tc_port_init_mode()
1508 /* Prevent changing tc->mode until intel_tc_port_sanitize_mode() is called. */ in intel_tc_port_init_mode()
1511 mutex_unlock(&tc->lock); in intel_tc_port_init_mode()
1518 struct intel_digital_port *dig_port = tc->dig_port; in tc_port_has_active_links()
1522 if (dig_port->dp.is_mst) { in tc_port_has_active_links()
1525 } else if (crtc_state && crtc_state->hw.active) { in tc_port_has_active_links()
1526 pll_type = intel_ddi_port_pll_type(&dig_port->base, crtc_state); in tc_port_has_active_links()
1531 drm_err(&i915->drm, in tc_port_has_active_links()
1532 "Port %s: PHY disconnected with %d active link(s)\n", in tc_port_has_active_links()
1533 tc->port_name, active_links); in tc_port_has_active_links()
1539 * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
1543 * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
1545 * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
1553 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_sanitize_mode()
1556 mutex_lock(&tc->lock); in intel_tc_port_sanitize_mode()
1558 drm_WARN_ON(&i915->drm, tc->link_refcount != 1); in intel_tc_port_sanitize_mode()
1561 * TBT-alt is the default mode in any case the PHY ownership is not in intel_tc_port_sanitize_mode()
1562 * held (regardless of the sink's connected live state), so in intel_tc_port_sanitize_mode()
1563 * we'll just switch to disconnected mode from it here without in intel_tc_port_sanitize_mode()
1566 if (tc->init_mode != TC_PORT_TBT_ALT && in intel_tc_port_sanitize_mode()
1567 tc->init_mode != TC_PORT_DISCONNECTED) in intel_tc_port_sanitize_mode()
1568 drm_dbg_kms(&i915->drm, in intel_tc_port_sanitize_mode()
1569 "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", in intel_tc_port_sanitize_mode()
1570 tc->port_name, in intel_tc_port_sanitize_mode()
1571 tc_port_mode_name(tc->init_mode)); in intel_tc_port_sanitize_mode()
1576 drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", in intel_tc_port_sanitize_mode()
1577 tc->port_name, in intel_tc_port_sanitize_mode()
1578 tc_port_mode_name(tc->mode)); in intel_tc_port_sanitize_mode()
1580 mutex_unlock(&tc->lock); in intel_tc_port_sanitize_mode()
1584 * The type-C ports are different because even when they are connected, they may
1596 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_connected_locked()
1600 drm_WARN_ON(&i915->drm, !intel_tc_port_ref_held(dig_port)); in intel_tc_port_connected_locked()
1602 if (tc->mode != TC_PORT_DISCONNECTED) in intel_tc_port_connected_locked()
1603 mask = BIT(tc->mode); in intel_tc_port_connected_locked()
1614 mutex_lock(&tc->lock); in intel_tc_port_connected()
1616 mutex_unlock(&tc->lock); in intel_tc_port_connected()
1625 mutex_lock(&tc->lock); in __intel_tc_port_link_needs_reset()
1627 ret = tc->link_refcount && in __intel_tc_port_link_needs_reset()
1628 tc->mode == TC_PORT_DP_ALT && in __intel_tc_port_link_needs_reset()
1631 mutex_unlock(&tc->lock); in __intel_tc_port_link_needs_reset()
1638 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_link_needs_reset()
1639 enum phy phy = intel_port_to_phy(i915, dig_port->base.port); in intel_tc_port_link_needs_reset()
1652 struct intel_digital_port *dig_port = tc->dig_port; in reset_link_commit()
1653 struct intel_dp *intel_dp = enc_to_intel_dp(&dig_port->base); in reset_link_commit()
1658 ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex, ctx); in reset_link_commit()
1669 for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) { in reset_link_commit()
1672 crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); in reset_link_commit()
1676 crtc_state->uapi.connectors_changed = true; in reset_link_commit()
1682 return drm_atomic_commit(&state->base); in reset_link_commit()
1693 _state = drm_atomic_state_alloc(&i915->drm); in reset_link()
1695 return -ENOMEM; in reset_link()
1698 state->internal = true; in reset_link()
1703 drm_atomic_state_put(&state->base); in reset_link()
1718 mutex_lock(&i915->drm.mode_config.mutex); in intel_tc_port_link_reset_work()
1720 drm_dbg_kms(&i915->drm, in intel_tc_port_link_reset_work()
1721 "Port %s: TypeC DP-alt sink disconnected, resetting link\n", in intel_tc_port_link_reset_work()
1722 tc->port_name); in intel_tc_port_link_reset_work()
1724 drm_WARN_ON(&i915->drm, ret); in intel_tc_port_link_reset_work()
1726 mutex_unlock(&i915->drm.mode_config.mutex); in intel_tc_port_link_reset_work()
1735 &to_tc_port(dig_port)->link_reset_work, in intel_tc_port_link_reset()
1743 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_link_cancel_reset_work()
1744 enum phy phy = intel_port_to_phy(i915, dig_port->base.port); in intel_tc_port_link_cancel_reset_work()
1750 cancel_delayed_work(&tc->link_reset_work); in intel_tc_port_link_cancel_reset_work()
1758 mutex_lock(&tc->lock); in __intel_tc_port_lock()
1760 cancel_delayed_work(&tc->disconnect_phy_work); in __intel_tc_port_lock()
1762 if (!tc->link_refcount) in __intel_tc_port_lock()
1766 drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_DISCONNECTED); in __intel_tc_port_lock()
1767 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_TBT_ALT && in __intel_tc_port_lock()
1786 mutex_lock(&tc->lock); in intel_tc_port_disconnect_phy_work()
1788 if (!tc->link_refcount) in intel_tc_port_disconnect_phy_work()
1791 mutex_unlock(&tc->lock); in intel_tc_port_disconnect_phy_work()
1802 flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work); in intel_tc_port_flush_work()
1809 cancel_delayed_work_sync(&tc->link_reset_work); in intel_tc_port_suspend()
1817 if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED) in intel_tc_port_unlock()
1818 queue_delayed_work(system_unbound_wq, &tc->disconnect_phy_work, in intel_tc_port_unlock()
1821 mutex_unlock(&tc->lock); in intel_tc_port_unlock()
1828 return mutex_is_locked(&tc->lock) || in intel_tc_port_ref_held()
1829 tc->link_refcount; in intel_tc_port_ref_held()
1852 * that are active in DP-alt mode with their sink disconnected, until in intel_tc_port_put_link()
1861 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_init()
1863 enum port port = dig_port->base.port; in intel_tc_port_init()
1866 if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) in intel_tc_port_init()
1867 return -EINVAL; in intel_tc_port_init()
1871 return -ENOMEM; in intel_tc_port_init()
1873 dig_port->tc = tc; in intel_tc_port_init()
1874 tc->dig_port = dig_port; in intel_tc_port_init()
1877 tc->phy_ops = &xelpdp_tc_phy_ops; in intel_tc_port_init()
1879 tc->phy_ops = &adlp_tc_phy_ops; in intel_tc_port_init()
1881 tc->phy_ops = &tgl_tc_phy_ops; in intel_tc_port_init()
1883 tc->phy_ops = &icl_tc_phy_ops; in intel_tc_port_init()
1885 tc->port_name = kasprintf(GFP_KERNEL, "%c/TC#%d", port_name(port), in intel_tc_port_init()
1887 if (!tc->port_name) { in intel_tc_port_init()
1889 return -ENOMEM; in intel_tc_port_init()
1892 mutex_init(&tc->lock); in intel_tc_port_init()
1894 INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work); in intel_tc_port_init()
1895 INIT_DELAYED_WORK(&tc->link_reset_work, intel_tc_port_link_reset_work); in intel_tc_port_init()
1896 tc->legacy_port = is_legacy; in intel_tc_port_init()
1897 tc->mode = TC_PORT_DISCONNECTED; in intel_tc_port_init()
1898 tc->link_refcount = 0; in intel_tc_port_init()
1911 kfree(dig_port->tc->port_name); in intel_tc_port_cleanup()
1912 kfree(dig_port->tc); in intel_tc_port_cleanup()
1913 dig_port->tc = NULL; in intel_tc_port_cleanup()