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
105 return intel_encoder_is_tc(&dig_port->base) && tc->mode == mode; in intel_tc_port_in_mode()
127 return intel_encoder_is_tc(&dig_port->base) && !tc->legacy_port; in intel_tc_port_handles_hpd_glitches()
132 * platform and TC mode (legacy, DP-alt, TBT):
135 * --------------------------
137 * - TCSS/IOM access for PHY ready state.
139 * - DE/north-,south-HPD ISR access for HPD live state.
142 * -----------------------------------
144 * - DE/DDI_BUF access for port enabled state.
146 * - DE/DDI_BUF access for PHY owned state.
149 * -------------------------------------
150 * ICL/legacy mode:
151 * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
152 * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
154 * ADLP/legacy, DP-alt modes:
155 * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
159 * -------------------------
160 * ICL/DP-alt, TBT mode:
161 * - TCSS/TBT: block TC-cold power state for using the (direct or
162 * TBT DP-IN) AUX and main lanes.
165 * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
166 * - TCSS/PHY: block TC-cold power state for using the (direct or
167 * TBT DP-IN) AUX and main lanes.
169 * ADLP/TBT mode:
170 * - TCSS/TBT: block TC-cold power state for using the (TBT DP-IN)
174 * - TCSS/IOM,FIA access for PHY ready, owned state
175 * - TCSS/PHY: block TC-cold power state for using the (direct or
176 * TBT DP-IN) AUX and main lanes.
184 intel_display_power_legacy_aux_domain(display, dig_port->aux_ch); in intel_tc_cold_requires_aux_pw()
190 struct intel_display *display = to_intel_display(tc->dig_port); in __tc_cold_block()
205 tc->lock_power_domain = domain; in tc_cold_block()
214 struct intel_display *display = to_intel_display(tc->dig_port); in __tc_cold_unblock()
225 drm_WARN_ON(&tc_to_i915(tc)->drm, tc->lock_power_domain != domain); in tc_cold_unblock()
233 struct intel_display *display = to_intel_display(tc->dig_port); in assert_display_core_power_enabled()
235 drm_WARN_ON(display->drm, in assert_display_core_power_enabled()
242 struct intel_display *display = to_intel_display(tc->dig_port); in assert_tc_cold_blocked()
247 drm_WARN_ON(display->drm, !enabled); in assert_tc_cold_blocked()
253 enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); in tc_port_power_domain()
255 return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1; in tc_port_power_domain()
261 struct intel_display *display = to_intel_display(tc->dig_port); in assert_tc_port_power_enabled()
263 drm_WARN_ON(display->drm, in assert_tc_port_power_enabled()
269 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_get_lane_mask()
273 lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); in intel_tc_port_get_lane_mask()
275 drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff); in intel_tc_port_get_lane_mask()
278 lane_mask &= DP_LANE_ASSIGNMENT_MASK(tc->phy_fia_idx); in intel_tc_port_get_lane_mask()
279 return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(tc->phy_fia_idx); in intel_tc_port_get_lane_mask()
284 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_get_pin_assignment_mask()
288 pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(tc->phy_fia)); in intel_tc_port_get_pin_assignment_mask()
290 drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff); in intel_tc_port_get_pin_assignment_mask()
293 return (pin_mask & DP_PIN_ASSIGNMENT_MASK(tc->phy_fia_idx)) >> in intel_tc_port_get_pin_assignment_mask()
294 DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx); in intel_tc_port_get_pin_assignment_mask()
300 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in lnl_tc_port_get_max_lane_count()
301 enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); in lnl_tc_port_get_max_lane_count()
372 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_max_lane_count()
375 if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) in intel_tc_port_max_lane_count()
392 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_set_fia_lane_count()
394 bool lane_reversal = dig_port->lane_reversal; in intel_tc_port_set_fia_lane_count()
400 drm_WARN_ON(&i915->drm, in intel_tc_port_set_fia_lane_count()
401 lane_reversal && tc->mode != TC_PORT_LEGACY); in intel_tc_port_set_fia_lane_count()
405 val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia)); in intel_tc_port_set_fia_lane_count()
406 val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
411 DFLEXDPMLE1_DPMLETC_ML3(tc->phy_fia_idx) : in intel_tc_port_set_fia_lane_count()
412 DFLEXDPMLE1_DPMLETC_ML0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
416 DFLEXDPMLE1_DPMLETC_ML3_2(tc->phy_fia_idx) : in intel_tc_port_set_fia_lane_count()
417 DFLEXDPMLE1_DPMLETC_ML1_0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
420 val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
426 intel_de_write(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia), val); in intel_tc_port_set_fia_lane_count()
435 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); in tc_port_fixup_legacy_flag()
440 if (tc->legacy_port) in tc_port_fixup_legacy_flag()
450 drm_dbg_kms(&i915->drm, in tc_port_fixup_legacy_flag()
451 "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n", in tc_port_fixup_legacy_flag()
452 tc->port_name, live_status_mask, valid_hpd_mask); in tc_port_fixup_legacy_flag()
454 tc->legacy_port = !tc->legacy_port; in tc_port_fixup_legacy_flag()
459 enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); in tc_phy_load_fia_params()
466 tc->phy_fia = tc_port / 2; in tc_phy_load_fia_params()
467 tc->phy_fia_idx = tc_port % 2; in tc_phy_load_fia_params()
469 tc->phy_fia = FIA1; in tc_phy_load_fia_params()
470 tc->phy_fia_idx = tc_port; in tc_phy_load_fia_params()
476 * -------------------
481 struct intel_display *display = to_intel_display(tc->dig_port); in icl_tc_phy_cold_off_domain()
482 struct intel_digital_port *dig_port = tc->dig_port; in icl_tc_phy_cold_off_domain()
484 if (tc->legacy_port) in icl_tc_phy_cold_off_domain()
485 return intel_display_power_legacy_aux_domain(display, dig_port->aux_ch); in icl_tc_phy_cold_off_domain()
492 struct intel_display *display = to_intel_display(tc->dig_port); in icl_tc_phy_hpd_live_status()
494 struct intel_digital_port *dig_port = tc->dig_port; in icl_tc_phy_hpd_live_status()
495 u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; in icl_tc_phy_hpd_live_status()
502 fia_isr = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); in icl_tc_phy_hpd_live_status()
507 drm_dbg_kms(&i915->drm, in icl_tc_phy_hpd_live_status()
508 "Port %s: PHY in TCCOLD, nothing connected\n", in icl_tc_phy_hpd_live_status()
509 tc->port_name); in icl_tc_phy_hpd_live_status()
513 if (fia_isr & TC_LIVE_STATE_TBT(tc->phy_fia_idx)) in icl_tc_phy_hpd_live_status()
515 if (fia_isr & TC_LIVE_STATE_TC(tc->phy_fia_idx)) in icl_tc_phy_hpd_live_status()
526 * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink
527 * is connected and it's ready to switch the ownership to display. The flag
528 * will be left cleared when a TBT-alt sink is connected, where the PHY is
539 val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(tc->phy_fia)); in icl_tc_phy_is_ready()
541 drm_dbg_kms(&i915->drm, in icl_tc_phy_is_ready()
542 "Port %s: PHY in TCCOLD, assuming not ready\n", in icl_tc_phy_is_ready()
543 tc->port_name); in icl_tc_phy_is_ready()
547 return val & DP_PHY_MODE_STATUS_COMPLETED(tc->phy_fia_idx); in icl_tc_phy_is_ready()
558 val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); in icl_tc_phy_take_ownership()
560 drm_dbg_kms(&i915->drm, in icl_tc_phy_take_ownership()
561 "Port %s: PHY in TCCOLD, can't %s ownership\n", in icl_tc_phy_take_ownership()
562 tc->port_name, take ? "take" : "release"); in icl_tc_phy_take_ownership()
567 val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_take_ownership()
569 val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_take_ownership()
571 intel_de_write(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia), val); in icl_tc_phy_take_ownership()
583 val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); in icl_tc_phy_is_owned()
585 drm_dbg_kms(&i915->drm, in icl_tc_phy_is_owned()
586 "Port %s: PHY in TCCOLD, assume not owned\n", in icl_tc_phy_is_owned()
587 tc->port_name); in icl_tc_phy_is_owned()
591 return val & DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_is_owned()
601 tc->mode = tc_phy_get_current_mode(tc); in icl_tc_phy_get_hw_state()
602 if (tc->mode != TC_PORT_DISCONNECTED) in icl_tc_phy_get_hw_state()
603 tc->lock_wakeref = tc_cold_block(tc); in icl_tc_phy_get_hw_state()
613 * Unlike the other ports, type-C ports are not available to use as soon as we
614 * get a hotplug. The type-C PHYs can be shared between multiple controllers:
617 * set the type-C power state.
623 struct intel_digital_port *dig_port = tc->dig_port; in tc_phy_verify_legacy_or_dp_alt_mode()
627 if (tc->mode == TC_PORT_LEGACY) { in tc_phy_verify_legacy_or_dp_alt_mode()
628 drm_WARN_ON(&i915->drm, max_lanes != 4); in tc_phy_verify_legacy_or_dp_alt_mode()
632 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DP_ALT); in tc_phy_verify_legacy_or_dp_alt_mode()
635 * Now we have to re-check the live state, in case the port recently in tc_phy_verify_legacy_or_dp_alt_mode()
636 * became disconnected. Not necessary for legacy mode. in tc_phy_verify_legacy_or_dp_alt_mode()
639 drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n", in tc_phy_verify_legacy_or_dp_alt_mode()
640 tc->port_name); in tc_phy_verify_legacy_or_dp_alt_mode()
645 drm_dbg_kms(&i915->drm, in tc_phy_verify_legacy_or_dp_alt_mode()
646 "Port %s: PHY max lanes %d < required lanes %d\n", in tc_phy_verify_legacy_or_dp_alt_mode()
647 tc->port_name, in tc_phy_verify_legacy_or_dp_alt_mode()
660 tc->lock_wakeref = tc_cold_block(tc); in icl_tc_phy_connect()
662 if (tc->mode == TC_PORT_TBT_ALT) in icl_tc_phy_connect()
667 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in icl_tc_phy_connect()
668 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership (ready %s)\n", in icl_tc_phy_connect()
669 tc->port_name, in icl_tc_phy_connect()
683 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in icl_tc_phy_connect()
694 switch (tc->mode) { in icl_tc_phy_disconnect()
700 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in icl_tc_phy_disconnect()
703 MISSING_CASE(tc->mode); in icl_tc_phy_disconnect()
725 * -------------------
735 struct intel_display *display = to_intel_display(tc->dig_port); in tgl_tc_phy_init()
743 drm_WARN_ON(&i915->drm, val == 0xffffffff); in tgl_tc_phy_init()
761 * --------------------
766 struct intel_display *display = to_intel_display(tc->dig_port); in adlp_tc_phy_cold_off_domain()
767 struct intel_digital_port *dig_port = tc->dig_port; in adlp_tc_phy_cold_off_domain()
769 if (tc->mode != TC_PORT_TBT_ALT) in adlp_tc_phy_cold_off_domain()
770 return intel_display_power_legacy_aux_domain(display, dig_port->aux_ch); in adlp_tc_phy_cold_off_domain()
777 struct intel_display *display = to_intel_display(tc->dig_port); in adlp_tc_phy_hpd_live_status()
779 struct intel_digital_port *dig_port = tc->dig_port; in adlp_tc_phy_hpd_live_status()
780 enum hpd_pin hpd_pin = dig_port->base.hpd_pin; in adlp_tc_phy_hpd_live_status()
781 u32 cpu_isr_bits = i915->display.hotplug.hpd[hpd_pin]; in adlp_tc_phy_hpd_live_status()
782 u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; in adlp_tc_phy_hpd_live_status()
806 * PHY ownership. The IOM firmware sets this flag when it's ready to switch
807 * the ownership to display, regardless of what sink is connected (TBT-alt,
808 * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT
814 enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); in adlp_tc_phy_is_ready()
821 drm_dbg_kms(&i915->drm, in adlp_tc_phy_is_ready()
822 "Port %s: PHY in TCCOLD, assuming not ready\n", in adlp_tc_phy_is_ready()
823 tc->port_name); in adlp_tc_phy_is_ready()
834 enum port port = tc->dig_port->base.port; in adlp_tc_phy_take_ownership()
847 enum port port = tc->dig_port->base.port; in adlp_tc_phy_is_owned()
858 struct intel_display *display = to_intel_display(tc->dig_port); in adlp_tc_phy_get_hw_state()
865 tc->mode = tc_phy_get_current_mode(tc); in adlp_tc_phy_get_hw_state()
866 if (tc->mode != TC_PORT_DISCONNECTED) in adlp_tc_phy_get_hw_state()
867 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_get_hw_state()
874 struct intel_display *display = to_intel_display(tc->dig_port); in adlp_tc_phy_connect()
880 if (tc->mode == TC_PORT_TBT_ALT) { in adlp_tc_phy_connect()
881 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_connect()
888 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in adlp_tc_phy_connect()
889 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership\n", in adlp_tc_phy_connect()
890 tc->port_name); in adlp_tc_phy_connect()
895 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in adlp_tc_phy_connect()
896 drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n", in adlp_tc_phy_connect()
897 tc->port_name); in adlp_tc_phy_connect()
901 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_connect()
911 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in adlp_tc_phy_connect()
922 struct intel_display *display = to_intel_display(tc->dig_port); in adlp_tc_phy_disconnect()
929 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in adlp_tc_phy_disconnect()
931 switch (tc->mode) { in adlp_tc_phy_disconnect()
939 MISSING_CASE(tc->mode); in adlp_tc_phy_disconnect()
963 * ----------------------
967 struct intel_display *display = to_intel_display(tc->dig_port); in xelpdp_tc_phy_hpd_live_status()
969 struct intel_digital_port *dig_port = tc->dig_port; in xelpdp_tc_phy_hpd_live_status()
970 enum hpd_pin hpd_pin = dig_port->base.hpd_pin; in xelpdp_tc_phy_hpd_live_status()
971 u32 pica_isr_bits = i915->display.hotplug.hpd[hpd_pin]; in xelpdp_tc_phy_hpd_live_status()
972 u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; in xelpdp_tc_phy_hpd_live_status()
988 if (tc->legacy_port && (pch_isr & pch_isr_bit)) in xelpdp_tc_phy_hpd_live_status()
998 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_tcss_power_is_enabled()
1012 drm_dbg_kms(&i915->drm, in xelpdp_tc_phy_wait_for_tcss_power()
1013 "Port %s: timeout waiting for TCSS power to get %s\n", in xelpdp_tc_phy_wait_for_tcss_power()
1015 tc->port_name); in xelpdp_tc_phy_wait_for_tcss_power()
1024 * handshake violation when pwwreq= 0->1 during TC7/10 entry
1031 drm_dbg_kms(display->drm, in xelpdp_tc_power_request_wa()
1044 drm_dbg_kms(display->drm, in xelpdp_tc_power_request_wa()
1052 struct intel_display *display = to_intel_display(tc->dig_port); in __xelpdp_tc_phy_enable_tcss_power()
1053 enum port port = tc->dig_port->base.port; in __xelpdp_tc_phy_enable_tcss_power()
1085 if (drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) in xelpdp_tc_phy_enable_tcss_power()
1100 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_take_ownership()
1117 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_is_owned()
1133 tc->mode = tc_phy_get_current_mode(tc); in xelpdp_tc_phy_get_hw_state()
1134 if (tc->mode != TC_PORT_DISCONNECTED) in xelpdp_tc_phy_get_hw_state()
1135 tc->lock_wakeref = tc_cold_block(tc); in xelpdp_tc_phy_get_hw_state()
1137 drm_WARN_ON(&i915->drm, in xelpdp_tc_phy_get_hw_state()
1138 (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) && in xelpdp_tc_phy_get_hw_state()
1146 tc->lock_wakeref = tc_cold_block(tc); in xelpdp_tc_phy_connect()
1148 if (tc->mode == TC_PORT_TBT_ALT) in xelpdp_tc_phy_connect()
1166 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in xelpdp_tc_phy_connect()
1173 switch (tc->mode) { in xelpdp_tc_phy_disconnect()
1180 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in xelpdp_tc_phy_disconnect()
1183 MISSING_CASE(tc->mode); in xelpdp_tc_phy_disconnect()
1200 * -----------------------
1205 return tc->phy_ops->cold_off_domain(tc); in tc_phy_cold_off_domain()
1213 mask = tc->phy_ops->hpd_live_status(tc); in tc_phy_hpd_live_status()
1215 /* The sink can be connected only in a single mode. */ in tc_phy_hpd_live_status()
1216 drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1); in tc_phy_hpd_live_status()
1223 return tc->phy_ops->is_ready(tc); in tc_phy_is_ready()
1228 return tc->phy_ops->is_owned(tc); in tc_phy_is_owned()
1233 tc->phy_ops->get_hw_state(tc); in tc_phy_get_hw_state()
1241 drm_WARN_ON(&i915->drm, phy_is_owned && !phy_is_ready); in tc_phy_is_ready_and_owned()
1249 struct intel_encoder *encoder = &tc->dig_port->base; in tc_phy_is_connected()
1250 struct drm_i915_private *i915 = to_i915(encoder->base.dev); in tc_phy_is_connected()
1260 drm_dbg_kms(&i915->drm, in tc_phy_is_connected()
1261 "Port %s: PHY connected: %s (ready: %s, owned: %s, pll_type: %s)\n", in tc_phy_is_connected()
1262 tc->port_name, in tc_phy_is_connected()
1266 port_pll_type == ICL_PORT_DPLL_DEFAULT ? "tbt" : "non-tbt"); in tc_phy_is_connected()
1276 drm_err(&i915->drm, "Port %s: timeout waiting for PHY ready\n", in tc_phy_wait_for_ready()
1277 tc->port_name); in tc_phy_wait_for_ready()
1289 return fls(live_status_mask) - 1; in hpd_mask_to_tc_mode()
1315 if (tc->legacy_port) in get_tc_mode_in_phy_owned_state()
1336 if (tc->legacy_port) in get_tc_mode_in_phy_not_owned_state()
1350 enum tc_port_mode mode; in tc_phy_get_current_mode() local
1353 * For legacy ports the IOM firmware initializes the PHY during boot-up in tc_phy_get_current_mode()
1357 if (tc->legacy_port) in tc_phy_get_current_mode()
1364 mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); in tc_phy_get_current_mode()
1366 drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT); in tc_phy_get_current_mode()
1367 mode = get_tc_mode_in_phy_owned_state(tc, live_mode); in tc_phy_get_current_mode()
1370 drm_dbg_kms(&i915->drm, in tc_phy_get_current_mode()
1371 "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n", in tc_phy_get_current_mode()
1372 tc->port_name, in tc_phy_get_current_mode()
1373 tc_port_mode_name(mode), in tc_phy_get_current_mode()
1378 return mode; in tc_phy_get_current_mode()
1383 if (tc->legacy_port) in default_tc_mode()
1392 enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask); in hpd_mask_to_target_mode() local
1394 if (mode != TC_PORT_DISCONNECTED) in hpd_mask_to_target_mode()
1395 return mode; in hpd_mask_to_target_mode()
1416 tc->mode = hpd_mask_to_target_mode(tc, live_status_mask); in tc_phy_connect()
1418 connected = tc->phy_ops->connect(tc, required_lanes); in tc_phy_connect()
1419 if (!connected && tc->mode != default_tc_mode(tc)) { in tc_phy_connect()
1420 tc->mode = default_tc_mode(tc); in tc_phy_connect()
1421 connected = tc->phy_ops->connect(tc, required_lanes); in tc_phy_connect()
1424 drm_WARN_ON(&i915->drm, !connected); in tc_phy_connect()
1429 if (tc->mode != TC_PORT_DISCONNECTED) { in tc_phy_disconnect()
1430 tc->phy_ops->disconnect(tc); in tc_phy_disconnect()
1431 tc->mode = TC_PORT_DISCONNECTED; in tc_phy_disconnect()
1437 mutex_lock(&tc->lock); in tc_phy_init()
1438 tc->phy_ops->init(tc); in tc_phy_init()
1439 mutex_unlock(&tc->lock); in tc_phy_init()
1445 struct intel_display *display = to_intel_display(tc->dig_port); in intel_tc_port_reset_mode()
1446 struct intel_digital_port *dig_port = tc->dig_port; in intel_tc_port_reset_mode()
1447 enum tc_port_mode old_tc_mode = tc->mode; in intel_tc_port_reset_mode()
1456 drm_WARN_ON(display->drm, aux_powered); in intel_tc_port_reset_mode()
1463 drm_dbg_kms(display->drm, "Port %s: TC port mode reset (%s -> %s)\n", in intel_tc_port_reset_mode()
1464 tc->port_name, in intel_tc_port_reset_mode()
1466 tc_port_mode_name(tc->mode)); in intel_tc_port_reset_mode()
1471 return tc_phy_get_target_mode(tc) != tc->mode; in intel_tc_port_needs_reset()
1484 tc->link_refcount++; in __intel_tc_port_get_link()
1489 tc->link_refcount--; in __intel_tc_port_put_link()
1495 struct intel_digital_port *dig_port = tc->dig_port; in tc_port_is_enabled()
1499 return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) & in tc_port_is_enabled()
1504 * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
1507 * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
1512 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_init_mode()
1516 mutex_lock(&tc->lock); in intel_tc_port_init_mode()
1518 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); in intel_tc_port_init_mode()
1519 drm_WARN_ON(&i915->drm, tc->lock_wakeref); in intel_tc_port_init_mode()
1520 drm_WARN_ON(&i915->drm, tc->link_refcount); in intel_tc_port_init_mode()
1524 * Save the initial mode for the state check in in intel_tc_port_init_mode()
1527 tc->init_mode = tc->mode; in intel_tc_port_init_mode()
1531 * MST topology resume, but the PHY mode can only be changed if the in intel_tc_port_init_mode()
1542 } else if (tc->mode == TC_PORT_DISCONNECTED) { in intel_tc_port_init_mode()
1543 drm_WARN_ON(&i915->drm, !tc->legacy_port); in intel_tc_port_init_mode()
1544 drm_err(&i915->drm, in intel_tc_port_init_mode()
1545 "Port %s: PHY disconnected on enabled port, connecting it\n", in intel_tc_port_init_mode()
1546 tc->port_name); in intel_tc_port_init_mode()
1553 /* Prevent changing tc->mode until intel_tc_port_sanitize_mode() is called. */ in intel_tc_port_init_mode()
1556 mutex_unlock(&tc->lock); in intel_tc_port_init_mode()
1563 struct intel_digital_port *dig_port = tc->dig_port; in tc_port_has_active_links()
1567 if (dig_port->dp.is_mst) { in tc_port_has_active_links()
1570 } else if (crtc_state && crtc_state->hw.active) { in tc_port_has_active_links()
1571 pll_type = intel_ddi_port_pll_type(&dig_port->base, crtc_state); in tc_port_has_active_links()
1576 drm_err(&i915->drm, in tc_port_has_active_links()
1577 "Port %s: PHY disconnected with %d active link(s)\n", in tc_port_has_active_links()
1578 tc->port_name, active_links); in tc_port_has_active_links()
1584 * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
1588 * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
1590 * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
1598 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_sanitize_mode()
1601 mutex_lock(&tc->lock); in intel_tc_port_sanitize_mode()
1603 drm_WARN_ON(&i915->drm, tc->link_refcount != 1); in intel_tc_port_sanitize_mode()
1606 * TBT-alt is the default mode in any case the PHY ownership is not in intel_tc_port_sanitize_mode()
1607 * held (regardless of the sink's connected live state), so in intel_tc_port_sanitize_mode()
1608 * we'll just switch to disconnected mode from it here without in intel_tc_port_sanitize_mode()
1611 if (tc->init_mode != TC_PORT_TBT_ALT && in intel_tc_port_sanitize_mode()
1612 tc->init_mode != TC_PORT_DISCONNECTED) in intel_tc_port_sanitize_mode()
1613 drm_dbg_kms(&i915->drm, in intel_tc_port_sanitize_mode()
1614 "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", in intel_tc_port_sanitize_mode()
1615 tc->port_name, in intel_tc_port_sanitize_mode()
1616 tc_port_mode_name(tc->init_mode)); in intel_tc_port_sanitize_mode()
1621 drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", in intel_tc_port_sanitize_mode()
1622 tc->port_name, in intel_tc_port_sanitize_mode()
1623 tc_port_mode_name(tc->mode)); in intel_tc_port_sanitize_mode()
1625 mutex_unlock(&tc->lock); in intel_tc_port_sanitize_mode()
1629 * The type-C ports are different because even when they are connected, they may
1641 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_connected()
1645 drm_WARN_ON(&i915->drm, !intel_tc_port_ref_held(dig_port)); in intel_tc_port_connected()
1647 if (tc->mode != TC_PORT_DISCONNECTED) in intel_tc_port_connected()
1648 mask = BIT(tc->mode); in intel_tc_port_connected()
1657 mutex_lock(&tc->lock); in __intel_tc_port_link_needs_reset()
1659 ret = tc->link_refcount && in __intel_tc_port_link_needs_reset()
1660 tc->mode == TC_PORT_DP_ALT && in __intel_tc_port_link_needs_reset()
1663 mutex_unlock(&tc->lock); in __intel_tc_port_link_needs_reset()
1670 if (!intel_encoder_is_tc(&dig_port->base)) in intel_tc_port_link_needs_reset()
1681 struct intel_digital_port *dig_port = tc->dig_port; in reset_link_commit()
1682 struct intel_dp *intel_dp = enc_to_intel_dp(&dig_port->base); in reset_link_commit()
1687 ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex, ctx); in reset_link_commit()
1698 for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) { in reset_link_commit()
1701 crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); in reset_link_commit()
1705 crtc_state->uapi.connectors_changed = true; in reset_link_commit()
1711 return drm_atomic_commit(&state->base); in reset_link_commit()
1722 _state = drm_atomic_state_alloc(&i915->drm); in reset_link()
1724 return -ENOMEM; in reset_link()
1727 state->internal = true; in reset_link()
1732 drm_atomic_state_put(&state->base); in reset_link()
1747 mutex_lock(&i915->drm.mode_config.mutex); in intel_tc_port_link_reset_work()
1749 drm_dbg_kms(&i915->drm, in intel_tc_port_link_reset_work()
1750 "Port %s: TypeC DP-alt sink disconnected, resetting link\n", in intel_tc_port_link_reset_work()
1751 tc->port_name); in intel_tc_port_link_reset_work()
1753 drm_WARN_ON(&i915->drm, ret); in intel_tc_port_link_reset_work()
1755 mutex_unlock(&i915->drm.mode_config.mutex); in intel_tc_port_link_reset_work()
1764 &to_tc_port(dig_port)->link_reset_work, in intel_tc_port_link_reset()
1774 if (!intel_encoder_is_tc(&dig_port->base)) in intel_tc_port_link_cancel_reset_work()
1777 cancel_delayed_work(&tc->link_reset_work); in intel_tc_port_link_cancel_reset_work()
1785 mutex_lock(&tc->lock); in __intel_tc_port_lock()
1787 cancel_delayed_work(&tc->disconnect_phy_work); in __intel_tc_port_lock()
1789 if (!tc->link_refcount) in __intel_tc_port_lock()
1793 drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_DISCONNECTED); in __intel_tc_port_lock()
1794 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_TBT_ALT && in __intel_tc_port_lock()
1813 mutex_lock(&tc->lock); in intel_tc_port_disconnect_phy_work()
1815 if (!tc->link_refcount) in intel_tc_port_disconnect_phy_work()
1818 mutex_unlock(&tc->lock); in intel_tc_port_disconnect_phy_work()
1829 flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work); in intel_tc_port_flush_work()
1836 cancel_delayed_work_sync(&tc->link_reset_work); in intel_tc_port_suspend()
1844 if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED) in intel_tc_port_unlock()
1845 queue_delayed_work(system_unbound_wq, &tc->disconnect_phy_work, in intel_tc_port_unlock()
1848 mutex_unlock(&tc->lock); in intel_tc_port_unlock()
1855 return mutex_is_locked(&tc->lock) || in intel_tc_port_ref_held()
1856 tc->link_refcount; in intel_tc_port_ref_held()
1879 * that are active in DP-alt mode with their sink disconnected, until in intel_tc_port_put_link()
1888 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_init()
1890 enum port port = dig_port->base.port; in intel_tc_port_init()
1891 enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); in intel_tc_port_init()
1893 if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) in intel_tc_port_init()
1894 return -EINVAL; in intel_tc_port_init()
1898 return -ENOMEM; in intel_tc_port_init()
1900 dig_port->tc = tc; in intel_tc_port_init()
1901 tc->dig_port = dig_port; in intel_tc_port_init()
1904 tc->phy_ops = &xelpdp_tc_phy_ops; in intel_tc_port_init()
1906 tc->phy_ops = &adlp_tc_phy_ops; in intel_tc_port_init()
1908 tc->phy_ops = &tgl_tc_phy_ops; in intel_tc_port_init()
1910 tc->phy_ops = &icl_tc_phy_ops; in intel_tc_port_init()
1912 tc->port_name = kasprintf(GFP_KERNEL, "%c/TC#%d", port_name(port), in intel_tc_port_init()
1914 if (!tc->port_name) { in intel_tc_port_init()
1916 return -ENOMEM; in intel_tc_port_init()
1919 mutex_init(&tc->lock); in intel_tc_port_init()
1921 INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work); in intel_tc_port_init()
1922 INIT_DELAYED_WORK(&tc->link_reset_work, intel_tc_port_link_reset_work); in intel_tc_port_init()
1923 tc->legacy_port = is_legacy; in intel_tc_port_init()
1924 tc->mode = TC_PORT_DISCONNECTED; in intel_tc_port_init()
1925 tc->link_refcount = 0; in intel_tc_port_init()
1938 kfree(dig_port->tc->port_name); in intel_tc_port_cleanup()
1939 kfree(dig_port->tc); in intel_tc_port_cleanup()
1940 dig_port->tc = NULL; in intel_tc_port_cleanup()