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.
180 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_cold_requires_aux_pw()
184 intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); in intel_tc_cold_requires_aux_pw()
205 tc->lock_power_domain = domain; in tc_cold_block()
225 drm_WARN_ON(&tc_to_i915(tc)->drm, tc->lock_power_domain != domain); in tc_cold_unblock()
235 drm_WARN_ON(&i915->drm, in assert_display_core_power_enabled()
247 drm_WARN_ON(&i915->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()
263 drm_WARN_ON(&i915->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()
299 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in lnl_tc_port_get_max_lane_count()
300 enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); in lnl_tc_port_get_max_lane_count()
324 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in mtl_tc_port_get_max_lane_count()
345 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_get_max_lane_count()
371 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_max_lane_count()
374 if (!intel_encoder_is_tc(&dig_port->base) || tc->mode != TC_PORT_DP_ALT) in intel_tc_port_max_lane_count()
391 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_set_fia_lane_count()
393 bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; in intel_tc_port_set_fia_lane_count()
399 drm_WARN_ON(&i915->drm, in intel_tc_port_set_fia_lane_count()
400 lane_reversal && tc->mode != TC_PORT_LEGACY); in intel_tc_port_set_fia_lane_count()
404 val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia)); in intel_tc_port_set_fia_lane_count()
405 val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
410 DFLEXDPMLE1_DPMLETC_ML3(tc->phy_fia_idx) : in intel_tc_port_set_fia_lane_count()
411 DFLEXDPMLE1_DPMLETC_ML0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
415 DFLEXDPMLE1_DPMLETC_ML3_2(tc->phy_fia_idx) : in intel_tc_port_set_fia_lane_count()
416 DFLEXDPMLE1_DPMLETC_ML1_0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
419 val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc->phy_fia_idx); in intel_tc_port_set_fia_lane_count()
425 intel_de_write(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia), val); in intel_tc_port_set_fia_lane_count()
434 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); in tc_port_fixup_legacy_flag()
439 if (tc->legacy_port) in tc_port_fixup_legacy_flag()
449 drm_dbg_kms(&i915->drm, in tc_port_fixup_legacy_flag()
450 "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n", in tc_port_fixup_legacy_flag()
451 tc->port_name, live_status_mask, valid_hpd_mask); in tc_port_fixup_legacy_flag()
453 tc->legacy_port = !tc->legacy_port; in tc_port_fixup_legacy_flag()
458 enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); in tc_phy_load_fia_params()
465 tc->phy_fia = tc_port / 2; in tc_phy_load_fia_params()
466 tc->phy_fia_idx = tc_port % 2; in tc_phy_load_fia_params()
468 tc->phy_fia = FIA1; in tc_phy_load_fia_params()
469 tc->phy_fia_idx = tc_port; in tc_phy_load_fia_params()
475 * -------------------
481 struct intel_digital_port *dig_port = tc->dig_port; in icl_tc_phy_cold_off_domain()
483 if (tc->legacy_port) in icl_tc_phy_cold_off_domain()
484 return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); in icl_tc_phy_cold_off_domain()
492 struct intel_digital_port *dig_port = tc->dig_port; in icl_tc_phy_hpd_live_status()
493 u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin]; in icl_tc_phy_hpd_live_status()
500 fia_isr = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia)); in icl_tc_phy_hpd_live_status()
505 drm_dbg_kms(&i915->drm, in icl_tc_phy_hpd_live_status()
506 "Port %s: PHY in TCCOLD, nothing connected\n", in icl_tc_phy_hpd_live_status()
507 tc->port_name); in icl_tc_phy_hpd_live_status()
511 if (fia_isr & TC_LIVE_STATE_TBT(tc->phy_fia_idx)) in icl_tc_phy_hpd_live_status()
513 if (fia_isr & TC_LIVE_STATE_TC(tc->phy_fia_idx)) in icl_tc_phy_hpd_live_status()
524 * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink
525 * is connected and it's ready to switch the ownership to display. The flag
526 * will be left cleared when a TBT-alt sink is connected, where the PHY is
537 val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(tc->phy_fia)); in icl_tc_phy_is_ready()
539 drm_dbg_kms(&i915->drm, in icl_tc_phy_is_ready()
540 "Port %s: PHY in TCCOLD, assuming not ready\n", in icl_tc_phy_is_ready()
541 tc->port_name); in icl_tc_phy_is_ready()
545 return val & DP_PHY_MODE_STATUS_COMPLETED(tc->phy_fia_idx); in icl_tc_phy_is_ready()
556 val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); in icl_tc_phy_take_ownership()
558 drm_dbg_kms(&i915->drm, in icl_tc_phy_take_ownership()
559 "Port %s: PHY in TCCOLD, can't %s ownership\n", in icl_tc_phy_take_ownership()
560 tc->port_name, take ? "take" : "release"); in icl_tc_phy_take_ownership()
565 val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); 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 intel_de_write(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia), val); in icl_tc_phy_take_ownership()
581 val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia)); in icl_tc_phy_is_owned()
583 drm_dbg_kms(&i915->drm, in icl_tc_phy_is_owned()
584 "Port %s: PHY in TCCOLD, assume not owned\n", in icl_tc_phy_is_owned()
585 tc->port_name); in icl_tc_phy_is_owned()
589 return val & DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx); in icl_tc_phy_is_owned()
599 tc->mode = tc_phy_get_current_mode(tc); in icl_tc_phy_get_hw_state()
600 if (tc->mode != TC_PORT_DISCONNECTED) in icl_tc_phy_get_hw_state()
601 tc->lock_wakeref = tc_cold_block(tc); in icl_tc_phy_get_hw_state()
611 * Unlike the other ports, type-C ports are not available to use as soon as we
612 * get a hotplug. The type-C PHYs can be shared between multiple controllers:
615 * set the type-C power state.
621 struct intel_digital_port *dig_port = tc->dig_port; in tc_phy_verify_legacy_or_dp_alt_mode()
625 if (tc->mode == TC_PORT_LEGACY) { in tc_phy_verify_legacy_or_dp_alt_mode()
626 drm_WARN_ON(&i915->drm, max_lanes != 4); in tc_phy_verify_legacy_or_dp_alt_mode()
630 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DP_ALT); in tc_phy_verify_legacy_or_dp_alt_mode()
633 * Now we have to re-check the live state, in case the port recently in tc_phy_verify_legacy_or_dp_alt_mode()
634 * became disconnected. Not necessary for legacy mode. in tc_phy_verify_legacy_or_dp_alt_mode()
637 drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n", in tc_phy_verify_legacy_or_dp_alt_mode()
638 tc->port_name); in tc_phy_verify_legacy_or_dp_alt_mode()
643 drm_dbg_kms(&i915->drm, in tc_phy_verify_legacy_or_dp_alt_mode()
644 "Port %s: PHY max lanes %d < required lanes %d\n", in tc_phy_verify_legacy_or_dp_alt_mode()
645 tc->port_name, in tc_phy_verify_legacy_or_dp_alt_mode()
658 tc->lock_wakeref = tc_cold_block(tc); in icl_tc_phy_connect()
660 if (tc->mode == TC_PORT_TBT_ALT) in icl_tc_phy_connect()
665 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in icl_tc_phy_connect()
666 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership (ready %s)\n", in icl_tc_phy_connect()
667 tc->port_name, in icl_tc_phy_connect()
681 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in icl_tc_phy_connect()
692 switch (tc->mode) { in icl_tc_phy_disconnect()
698 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in icl_tc_phy_disconnect()
701 MISSING_CASE(tc->mode); in icl_tc_phy_disconnect()
723 * -------------------
740 drm_WARN_ON(&i915->drm, val == 0xffffffff); in tgl_tc_phy_init()
758 * --------------------
764 struct intel_digital_port *dig_port = tc->dig_port; in adlp_tc_phy_cold_off_domain()
766 if (tc->mode != TC_PORT_TBT_ALT) in adlp_tc_phy_cold_off_domain()
767 return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch); in adlp_tc_phy_cold_off_domain()
775 struct intel_digital_port *dig_port = tc->dig_port; in adlp_tc_phy_hpd_live_status()
776 enum hpd_pin hpd_pin = dig_port->base.hpd_pin; in adlp_tc_phy_hpd_live_status()
777 u32 cpu_isr_bits = i915->display.hotplug.hpd[hpd_pin]; in adlp_tc_phy_hpd_live_status()
778 u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; in adlp_tc_phy_hpd_live_status()
802 * PHY ownership. The IOM firmware sets this flag when it's ready to switch
803 * the ownership to display, regardless of what sink is connected (TBT-alt,
804 * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT
810 enum tc_port tc_port = intel_encoder_to_tc(&tc->dig_port->base); in adlp_tc_phy_is_ready()
817 drm_dbg_kms(&i915->drm, in adlp_tc_phy_is_ready()
818 "Port %s: PHY in TCCOLD, assuming not ready\n", in adlp_tc_phy_is_ready()
819 tc->port_name); in adlp_tc_phy_is_ready()
830 enum port port = tc->dig_port->base.port; in adlp_tc_phy_take_ownership()
843 enum port port = tc->dig_port->base.port; in adlp_tc_phy_is_owned()
861 tc->mode = tc_phy_get_current_mode(tc); in adlp_tc_phy_get_hw_state()
862 if (tc->mode != TC_PORT_DISCONNECTED) in adlp_tc_phy_get_hw_state()
863 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_get_hw_state()
875 if (tc->mode == TC_PORT_TBT_ALT) { in adlp_tc_phy_connect()
876 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_connect()
883 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in adlp_tc_phy_connect()
884 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership\n", in adlp_tc_phy_connect()
885 tc->port_name); in adlp_tc_phy_connect()
890 !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) { in adlp_tc_phy_connect()
891 drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n", in adlp_tc_phy_connect()
892 tc->port_name); in adlp_tc_phy_connect()
896 tc->lock_wakeref = tc_cold_block(tc); in adlp_tc_phy_connect()
906 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in adlp_tc_phy_connect()
924 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in adlp_tc_phy_disconnect()
926 switch (tc->mode) { in adlp_tc_phy_disconnect()
934 MISSING_CASE(tc->mode); in adlp_tc_phy_disconnect()
958 * ----------------------
963 struct intel_digital_port *dig_port = tc->dig_port; in xelpdp_tc_phy_hpd_live_status()
964 enum hpd_pin hpd_pin = dig_port->base.hpd_pin; in xelpdp_tc_phy_hpd_live_status()
965 u32 pica_isr_bits = i915->display.hotplug.hpd[hpd_pin]; in xelpdp_tc_phy_hpd_live_status()
966 u32 pch_isr_bit = i915->display.hotplug.pch_hpd[hpd_pin]; in xelpdp_tc_phy_hpd_live_status()
982 if (tc->legacy_port && (pch_isr & pch_isr_bit)) in xelpdp_tc_phy_hpd_live_status()
992 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_tcss_power_is_enabled()
1006 drm_dbg_kms(&i915->drm, in xelpdp_tc_phy_wait_for_tcss_power()
1007 "Port %s: timeout waiting for TCSS power to get %s\n", in xelpdp_tc_phy_wait_for_tcss_power()
1009 tc->port_name); in xelpdp_tc_phy_wait_for_tcss_power()
1019 enum port port = tc->dig_port->base.port; in __xelpdp_tc_phy_enable_tcss_power()
1048 if (drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) in xelpdp_tc_phy_enable_tcss_power()
1063 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_take_ownership()
1080 enum port port = tc->dig_port->base.port; in xelpdp_tc_phy_is_owned()
1096 tc->mode = tc_phy_get_current_mode(tc); in xelpdp_tc_phy_get_hw_state()
1097 if (tc->mode != TC_PORT_DISCONNECTED) in xelpdp_tc_phy_get_hw_state()
1098 tc->lock_wakeref = tc_cold_block(tc); in xelpdp_tc_phy_get_hw_state()
1100 drm_WARN_ON(&i915->drm, in xelpdp_tc_phy_get_hw_state()
1101 (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) && in xelpdp_tc_phy_get_hw_state()
1109 tc->lock_wakeref = tc_cold_block(tc); in xelpdp_tc_phy_connect()
1111 if (tc->mode == TC_PORT_TBT_ALT) in xelpdp_tc_phy_connect()
1129 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in xelpdp_tc_phy_connect()
1136 switch (tc->mode) { in xelpdp_tc_phy_disconnect()
1143 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref)); in xelpdp_tc_phy_disconnect()
1146 MISSING_CASE(tc->mode); in xelpdp_tc_phy_disconnect()
1163 * -----------------------
1168 return tc->phy_ops->cold_off_domain(tc); in tc_phy_cold_off_domain()
1176 mask = tc->phy_ops->hpd_live_status(tc); in tc_phy_hpd_live_status()
1178 /* The sink can be connected only in a single mode. */ in tc_phy_hpd_live_status()
1179 drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1); in tc_phy_hpd_live_status()
1186 return tc->phy_ops->is_ready(tc); in tc_phy_is_ready()
1191 return tc->phy_ops->is_owned(tc); in tc_phy_is_owned()
1196 tc->phy_ops->get_hw_state(tc); in tc_phy_get_hw_state()
1204 drm_WARN_ON(&i915->drm, phy_is_owned && !phy_is_ready); in tc_phy_is_ready_and_owned()
1212 struct intel_encoder *encoder = &tc->dig_port->base; in tc_phy_is_connected()
1213 struct drm_i915_private *i915 = to_i915(encoder->base.dev); in tc_phy_is_connected()
1223 drm_dbg_kms(&i915->drm, in tc_phy_is_connected()
1224 "Port %s: PHY connected: %s (ready: %s, owned: %s, pll_type: %s)\n", in tc_phy_is_connected()
1225 tc->port_name, in tc_phy_is_connected()
1229 port_pll_type == ICL_PORT_DPLL_DEFAULT ? "tbt" : "non-tbt"); in tc_phy_is_connected()
1239 drm_err(&i915->drm, "Port %s: timeout waiting for PHY ready\n", in tc_phy_wait_for_ready()
1240 tc->port_name); in tc_phy_wait_for_ready()
1252 return fls(live_status_mask) - 1; in hpd_mask_to_tc_mode()
1278 if (tc->legacy_port) in get_tc_mode_in_phy_owned_state()
1299 if (tc->legacy_port) in get_tc_mode_in_phy_not_owned_state()
1313 enum tc_port_mode mode; in tc_phy_get_current_mode() local
1316 * For legacy ports the IOM firmware initializes the PHY during boot-up in tc_phy_get_current_mode()
1320 if (tc->legacy_port) in tc_phy_get_current_mode()
1327 mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode); in tc_phy_get_current_mode()
1329 drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT); in tc_phy_get_current_mode()
1330 mode = get_tc_mode_in_phy_owned_state(tc, live_mode); in tc_phy_get_current_mode()
1333 drm_dbg_kms(&i915->drm, in tc_phy_get_current_mode()
1334 "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n", in tc_phy_get_current_mode()
1335 tc->port_name, in tc_phy_get_current_mode()
1336 tc_port_mode_name(mode), in tc_phy_get_current_mode()
1341 return mode; in tc_phy_get_current_mode()
1346 if (tc->legacy_port) in default_tc_mode()
1355 enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask); in hpd_mask_to_target_mode() local
1357 if (mode != TC_PORT_DISCONNECTED) in hpd_mask_to_target_mode()
1358 return mode; in hpd_mask_to_target_mode()
1379 tc->mode = hpd_mask_to_target_mode(tc, live_status_mask); in tc_phy_connect()
1381 connected = tc->phy_ops->connect(tc, required_lanes); in tc_phy_connect()
1382 if (!connected && tc->mode != default_tc_mode(tc)) { in tc_phy_connect()
1383 tc->mode = default_tc_mode(tc); in tc_phy_connect()
1384 connected = tc->phy_ops->connect(tc, required_lanes); in tc_phy_connect()
1387 drm_WARN_ON(&i915->drm, !connected); in tc_phy_connect()
1392 if (tc->mode != TC_PORT_DISCONNECTED) { in tc_phy_disconnect()
1393 tc->phy_ops->disconnect(tc); in tc_phy_disconnect()
1394 tc->mode = TC_PORT_DISCONNECTED; in tc_phy_disconnect()
1400 mutex_lock(&tc->lock); in tc_phy_init()
1401 tc->phy_ops->init(tc); in tc_phy_init()
1402 mutex_unlock(&tc->lock); in tc_phy_init()
1409 struct intel_digital_port *dig_port = tc->dig_port; in intel_tc_port_reset_mode()
1410 enum tc_port_mode old_tc_mode = tc->mode; in intel_tc_port_reset_mode()
1419 drm_WARN_ON(&i915->drm, aux_powered); in intel_tc_port_reset_mode()
1426 drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n", in intel_tc_port_reset_mode()
1427 tc->port_name, in intel_tc_port_reset_mode()
1429 tc_port_mode_name(tc->mode)); in intel_tc_port_reset_mode()
1434 return tc_phy_get_target_mode(tc) != tc->mode; in intel_tc_port_needs_reset()
1447 tc->link_refcount++; in __intel_tc_port_get_link()
1452 tc->link_refcount--; in __intel_tc_port_put_link()
1458 struct intel_digital_port *dig_port = tc->dig_port; in tc_port_is_enabled()
1462 return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) & in tc_port_is_enabled()
1467 * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
1470 * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
1475 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_init_mode()
1479 mutex_lock(&tc->lock); in intel_tc_port_init_mode()
1481 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED); in intel_tc_port_init_mode()
1482 drm_WARN_ON(&i915->drm, tc->lock_wakeref); in intel_tc_port_init_mode()
1483 drm_WARN_ON(&i915->drm, tc->link_refcount); in intel_tc_port_init_mode()
1487 * Save the initial mode for the state check in in intel_tc_port_init_mode()
1490 tc->init_mode = tc->mode; in intel_tc_port_init_mode()
1494 * MST topology resume, but the PHY mode can only be changed if the in intel_tc_port_init_mode()
1505 } else if (tc->mode == TC_PORT_DISCONNECTED) { in intel_tc_port_init_mode()
1506 drm_WARN_ON(&i915->drm, !tc->legacy_port); in intel_tc_port_init_mode()
1507 drm_err(&i915->drm, in intel_tc_port_init_mode()
1508 "Port %s: PHY disconnected on enabled port, connecting it\n", in intel_tc_port_init_mode()
1509 tc->port_name); in intel_tc_port_init_mode()
1516 /* Prevent changing tc->mode until intel_tc_port_sanitize_mode() is called. */ in intel_tc_port_init_mode()
1519 mutex_unlock(&tc->lock); in intel_tc_port_init_mode()
1526 struct intel_digital_port *dig_port = tc->dig_port; in tc_port_has_active_links()
1530 if (dig_port->dp.is_mst) { in tc_port_has_active_links()
1533 } else if (crtc_state && crtc_state->hw.active) { in tc_port_has_active_links()
1534 pll_type = intel_ddi_port_pll_type(&dig_port->base, crtc_state); in tc_port_has_active_links()
1539 drm_err(&i915->drm, in tc_port_has_active_links()
1540 "Port %s: PHY disconnected with %d active link(s)\n", in tc_port_has_active_links()
1541 tc->port_name, active_links); in tc_port_has_active_links()
1547 * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
1551 * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
1553 * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
1561 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_sanitize_mode()
1564 mutex_lock(&tc->lock); in intel_tc_port_sanitize_mode()
1566 drm_WARN_ON(&i915->drm, tc->link_refcount != 1); in intel_tc_port_sanitize_mode()
1569 * TBT-alt is the default mode in any case the PHY ownership is not in intel_tc_port_sanitize_mode()
1570 * held (regardless of the sink's connected live state), so in intel_tc_port_sanitize_mode()
1571 * we'll just switch to disconnected mode from it here without in intel_tc_port_sanitize_mode()
1574 if (tc->init_mode != TC_PORT_TBT_ALT && in intel_tc_port_sanitize_mode()
1575 tc->init_mode != TC_PORT_DISCONNECTED) in intel_tc_port_sanitize_mode()
1576 drm_dbg_kms(&i915->drm, in intel_tc_port_sanitize_mode()
1577 "Port %s: PHY left in %s mode on disabled port, disconnecting it\n", in intel_tc_port_sanitize_mode()
1578 tc->port_name, in intel_tc_port_sanitize_mode()
1579 tc_port_mode_name(tc->init_mode)); in intel_tc_port_sanitize_mode()
1584 drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n", in intel_tc_port_sanitize_mode()
1585 tc->port_name, in intel_tc_port_sanitize_mode()
1586 tc_port_mode_name(tc->mode)); in intel_tc_port_sanitize_mode()
1588 mutex_unlock(&tc->lock); in intel_tc_port_sanitize_mode()
1592 * The type-C ports are different because even when they are connected, they may
1604 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_connected()
1608 drm_WARN_ON(&i915->drm, !intel_tc_port_ref_held(dig_port)); in intel_tc_port_connected()
1610 if (tc->mode != TC_PORT_DISCONNECTED) in intel_tc_port_connected()
1611 mask = BIT(tc->mode); in intel_tc_port_connected()
1620 mutex_lock(&tc->lock); in __intel_tc_port_link_needs_reset()
1622 ret = tc->link_refcount && in __intel_tc_port_link_needs_reset()
1623 tc->mode == TC_PORT_DP_ALT && in __intel_tc_port_link_needs_reset()
1626 mutex_unlock(&tc->lock); in __intel_tc_port_link_needs_reset()
1633 if (!intel_encoder_is_tc(&dig_port->base)) in intel_tc_port_link_needs_reset()
1644 struct intel_digital_port *dig_port = tc->dig_port; in reset_link_commit()
1645 struct intel_dp *intel_dp = enc_to_intel_dp(&dig_port->base); in reset_link_commit()
1650 ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex, ctx); in reset_link_commit()
1661 for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) { in reset_link_commit()
1664 crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); in reset_link_commit()
1668 crtc_state->uapi.connectors_changed = true; in reset_link_commit()
1674 return drm_atomic_commit(&state->base); in reset_link_commit()
1685 _state = drm_atomic_state_alloc(&i915->drm); in reset_link()
1687 return -ENOMEM; in reset_link()
1690 state->internal = true; in reset_link()
1695 drm_atomic_state_put(&state->base); in reset_link()
1710 mutex_lock(&i915->drm.mode_config.mutex); in intel_tc_port_link_reset_work()
1712 drm_dbg_kms(&i915->drm, in intel_tc_port_link_reset_work()
1713 "Port %s: TypeC DP-alt sink disconnected, resetting link\n", in intel_tc_port_link_reset_work()
1714 tc->port_name); in intel_tc_port_link_reset_work()
1716 drm_WARN_ON(&i915->drm, ret); in intel_tc_port_link_reset_work()
1718 mutex_unlock(&i915->drm.mode_config.mutex); in intel_tc_port_link_reset_work()
1727 &to_tc_port(dig_port)->link_reset_work, in intel_tc_port_link_reset()
1737 if (!intel_encoder_is_tc(&dig_port->base)) in intel_tc_port_link_cancel_reset_work()
1740 cancel_delayed_work(&tc->link_reset_work); in intel_tc_port_link_cancel_reset_work()
1748 mutex_lock(&tc->lock); in __intel_tc_port_lock()
1750 cancel_delayed_work(&tc->disconnect_phy_work); in __intel_tc_port_lock()
1752 if (!tc->link_refcount) in __intel_tc_port_lock()
1756 drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_DISCONNECTED); in __intel_tc_port_lock()
1757 drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_TBT_ALT && in __intel_tc_port_lock()
1776 mutex_lock(&tc->lock); in intel_tc_port_disconnect_phy_work()
1778 if (!tc->link_refcount) in intel_tc_port_disconnect_phy_work()
1781 mutex_unlock(&tc->lock); in intel_tc_port_disconnect_phy_work()
1792 flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work); in intel_tc_port_flush_work()
1799 cancel_delayed_work_sync(&tc->link_reset_work); in intel_tc_port_suspend()
1807 if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED) in intel_tc_port_unlock()
1808 queue_delayed_work(system_unbound_wq, &tc->disconnect_phy_work, in intel_tc_port_unlock()
1811 mutex_unlock(&tc->lock); in intel_tc_port_unlock()
1818 return mutex_is_locked(&tc->lock) || in intel_tc_port_ref_held()
1819 tc->link_refcount; in intel_tc_port_ref_held()
1842 * that are active in DP-alt mode with their sink disconnected, until in intel_tc_port_put_link()
1851 struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); in intel_tc_port_init()
1853 enum port port = dig_port->base.port; in intel_tc_port_init()
1854 enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base); in intel_tc_port_init()
1856 if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE)) in intel_tc_port_init()
1857 return -EINVAL; in intel_tc_port_init()
1861 return -ENOMEM; in intel_tc_port_init()
1863 dig_port->tc = tc; in intel_tc_port_init()
1864 tc->dig_port = dig_port; in intel_tc_port_init()
1867 tc->phy_ops = &xelpdp_tc_phy_ops; in intel_tc_port_init()
1869 tc->phy_ops = &adlp_tc_phy_ops; in intel_tc_port_init()
1871 tc->phy_ops = &tgl_tc_phy_ops; in intel_tc_port_init()
1873 tc->phy_ops = &icl_tc_phy_ops; in intel_tc_port_init()
1875 tc->port_name = kasprintf(GFP_KERNEL, "%c/TC#%d", port_name(port), in intel_tc_port_init()
1877 if (!tc->port_name) { in intel_tc_port_init()
1879 return -ENOMEM; in intel_tc_port_init()
1882 mutex_init(&tc->lock); in intel_tc_port_init()
1884 INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work); in intel_tc_port_init()
1885 INIT_DELAYED_WORK(&tc->link_reset_work, intel_tc_port_link_reset_work); in intel_tc_port_init()
1886 tc->legacy_port = is_legacy; in intel_tc_port_init()
1887 tc->mode = TC_PORT_DISCONNECTED; in intel_tc_port_init()
1888 tc->link_refcount = 0; in intel_tc_port_init()
1901 kfree(dig_port->tc->port_name); in intel_tc_port_cleanup()
1902 kfree(dig_port->tc); in intel_tc_port_cleanup()
1903 dig_port->tc = NULL; in intel_tc_port_cleanup()