1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2019 Intel Corporation
4 */
5
6#include <linux/iopoll.h>
7
8#include <drm/drm_print.h>
9
10#include "i915_reg.h"
11#include "i915_utils.h"
12#include "intel_atomic.h"
13#include "intel_cx0_phy_regs.h"
14#include "intel_ddi.h"
15#include "intel_de.h"
16#include "intel_display.h"
17#include "intel_display_driver.h"
18#include "intel_display_power_map.h"
19#include "intel_display_regs.h"
20#include "intel_display_types.h"
21#include "intel_dkl_phy_regs.h"
22#include "intel_dp.h"
23#include "intel_dp_mst.h"
24#include "intel_mg_phy_regs.h"
25#include "intel_modeset_lock.h"
26#include "intel_tc.h"
27
28enum tc_port_mode {
29 TC_PORT_DISCONNECTED,
30 TC_PORT_TBT_ALT,
31 TC_PORT_DP_ALT,
32 TC_PORT_LEGACY,
33};
34
35struct intel_tc_port;
36
37struct intel_tc_phy_ops {
38 enum intel_display_power_domain (*cold_off_domain)(struct intel_tc_port *tc);
39 u32 (*hpd_live_status)(struct intel_tc_port *tc);
40 bool (*is_ready)(struct intel_tc_port *tc);
41 bool (*is_owned)(struct intel_tc_port *tc);
42 void (*get_hw_state)(struct intel_tc_port *tc);
43 bool (*connect)(struct intel_tc_port *tc, int required_lanes);
44 void (*disconnect)(struct intel_tc_port *tc);
45 void (*init)(struct intel_tc_port *tc);
46};
47
48struct intel_tc_port {
49 struct intel_digital_port *dig_port;
50
51 const struct intel_tc_phy_ops *phy_ops;
52
53 struct mutex lock; /* protects the TypeC port mode */
54 intel_wakeref_t lock_wakeref;
55#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
56 enum intel_display_power_domain lock_power_domain;
57#endif
58 struct delayed_work disconnect_phy_work;
59 struct delayed_work link_reset_work;
60 int link_refcount;
61 bool legacy_port:1;
62 const char *port_name;
63 enum tc_port_mode mode;
64 enum tc_port_mode init_mode;
65 enum phy_fia phy_fia;
66 enum intel_tc_pin_assignment pin_assignment;
67 u8 phy_fia_idx;
68 u8 max_lane_count;
69};
70
71static enum intel_display_power_domain
72tc_phy_cold_off_domain(struct intel_tc_port *);
73static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc);
74static bool tc_phy_is_ready(struct intel_tc_port *tc);
75static bool tc_phy_wait_for_ready(struct intel_tc_port *tc);
76static enum tc_port_mode tc_phy_get_current_mode(struct intel_tc_port *tc);
77
78static const char *tc_port_mode_name(enum tc_port_mode mode)
79{
80 static const char * const names[] = {
81 [TC_PORT_DISCONNECTED] = "disconnected",
82 [TC_PORT_TBT_ALT] = "tbt-alt",
83 [TC_PORT_DP_ALT] = "dp-alt",
84 [TC_PORT_LEGACY] = "legacy",
85 };
86
87 if (WARN_ON(mode >= ARRAY_SIZE(names)))
88 mode = TC_PORT_DISCONNECTED;
89
90 return names[mode];
91}
92
93static struct intel_tc_port *to_tc_port(struct intel_digital_port *dig_port)
94{
95 return dig_port->tc;
96}
97
98static bool intel_tc_port_in_mode(struct intel_digital_port *dig_port,
99 enum tc_port_mode mode)
100{
101 struct intel_tc_port *tc = to_tc_port(dig_port);
102
103 return intel_encoder_is_tc(encoder: &dig_port->base) && tc->mode == mode;
104}
105
106bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port)
107{
108 return intel_tc_port_in_mode(dig_port, mode: TC_PORT_TBT_ALT);
109}
110
111bool intel_tc_port_in_dp_alt_mode(struct intel_digital_port *dig_port)
112{
113 return intel_tc_port_in_mode(dig_port, mode: TC_PORT_DP_ALT);
114}
115
116bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port)
117{
118 return intel_tc_port_in_mode(dig_port, mode: TC_PORT_LEGACY);
119}
120
121bool intel_tc_port_handles_hpd_glitches(struct intel_digital_port *dig_port)
122{
123 struct intel_tc_port *tc = to_tc_port(dig_port);
124
125 return intel_encoder_is_tc(encoder: &dig_port->base) && !tc->legacy_port;
126}
127
128/*
129 * The display power domains used for TC ports depending on the
130 * platform and TC mode (legacy, DP-alt, TBT):
131 *
132 * POWER_DOMAIN_DISPLAY_CORE:
133 * --------------------------
134 * ADLP/all modes:
135 * - TCSS/IOM access for PHY ready state.
136 * ADLP+/all modes:
137 * - DE/north-,south-HPD ISR access for HPD live state.
138 *
139 * POWER_DOMAIN_PORT_DDI_LANES_<port>:
140 * -----------------------------------
141 * ICL+/all modes:
142 * - DE/DDI_BUF access for port enabled state.
143 * ADLP/all modes:
144 * - DE/DDI_BUF access for PHY owned state.
145 *
146 * POWER_DOMAIN_AUX_USBC<TC port index>:
147 * -------------------------------------
148 * ICL/legacy mode:
149 * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
150 * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
151 * main lanes.
152 * ADLP/legacy, DP-alt modes:
153 * - TCSS/PHY: block TC-cold power state for using the PHY AUX and
154 * main lanes.
155 *
156 * POWER_DOMAIN_TC_COLD_OFF:
157 * -------------------------
158 * ICL/DP-alt, TBT mode:
159 * - TCSS/TBT: block TC-cold power state for using the (direct or
160 * TBT DP-IN) AUX and main lanes.
161 *
162 * TGL/all modes:
163 * - TCSS/IOM,FIA access for PHY ready, owned and HPD live state
164 * - TCSS/PHY: block TC-cold power state for using the (direct or
165 * TBT DP-IN) AUX and main lanes.
166 *
167 * ADLP/TBT mode:
168 * - TCSS/TBT: block TC-cold power state for using the (TBT DP-IN)
169 * AUX and main lanes.
170 *
171 * XELPDP+/all modes:
172 * - TCSS/IOM,FIA access for PHY ready, owned state
173 * - TCSS/PHY: block TC-cold power state for using the (direct or
174 * TBT DP-IN) AUX and main lanes.
175 */
176bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port)
177{
178 struct intel_display *display = to_intel_display(dig_port);
179 struct intel_tc_port *tc = to_tc_port(dig_port);
180
181 return tc_phy_cold_off_domain(tc) ==
182 intel_display_power_legacy_aux_domain(display, aux_ch: dig_port->aux_ch);
183}
184
185static intel_wakeref_t
186__tc_cold_block(struct intel_tc_port *tc, enum intel_display_power_domain *domain)
187{
188 struct intel_display *display = to_intel_display(tc->dig_port);
189
190 *domain = tc_phy_cold_off_domain(tc);
191
192 return intel_display_power_get(display, domain: *domain);
193}
194
195static intel_wakeref_t
196tc_cold_block(struct intel_tc_port *tc)
197{
198 enum intel_display_power_domain domain;
199 intel_wakeref_t wakeref;
200
201 wakeref = __tc_cold_block(tc, domain: &domain);
202#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
203 tc->lock_power_domain = domain;
204#endif
205 return wakeref;
206}
207
208static void
209__tc_cold_unblock(struct intel_tc_port *tc, enum intel_display_power_domain domain,
210 intel_wakeref_t wakeref)
211{
212 struct intel_display *display = to_intel_display(tc->dig_port);
213
214 intel_display_power_put(display, domain, wakeref);
215}
216
217static void
218tc_cold_unblock(struct intel_tc_port *tc, intel_wakeref_t wakeref)
219{
220 struct intel_display __maybe_unused *display = to_intel_display(tc->dig_port);
221 enum intel_display_power_domain domain = tc_phy_cold_off_domain(tc);
222
223#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
224 drm_WARN_ON(display->drm, tc->lock_power_domain != domain);
225#endif
226 __tc_cold_unblock(tc, domain, wakeref);
227}
228
229static void
230assert_display_core_power_enabled(struct intel_tc_port *tc)
231{
232 struct intel_display *display = to_intel_display(tc->dig_port);
233
234 drm_WARN_ON(display->drm,
235 !intel_display_power_is_enabled(display, POWER_DOMAIN_DISPLAY_CORE));
236}
237
238static void
239assert_tc_cold_blocked(struct intel_tc_port *tc)
240{
241 struct intel_display *display = to_intel_display(tc->dig_port);
242 bool enabled;
243
244 enabled = intel_display_power_is_enabled(display,
245 domain: tc_phy_cold_off_domain(tc));
246 drm_WARN_ON(display->drm, !enabled);
247}
248
249static enum intel_display_power_domain
250tc_port_power_domain(struct intel_tc_port *tc)
251{
252 enum tc_port tc_port = intel_encoder_to_tc(encoder: &tc->dig_port->base);
253
254 if (tc_port == TC_PORT_NONE)
255 return POWER_DOMAIN_INVALID;
256
257 return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1;
258}
259
260static void
261assert_tc_port_power_enabled(struct intel_tc_port *tc)
262{
263 struct intel_display *display = to_intel_display(tc->dig_port);
264
265 drm_WARN_ON(display->drm,
266 !intel_display_power_is_enabled(display, tc_port_power_domain(tc)));
267}
268
269static u32 get_lane_mask(struct intel_tc_port *tc)
270{
271 struct intel_display *display = to_intel_display(tc->dig_port);
272 intel_wakeref_t wakeref;
273 u32 lane_mask;
274
275 with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref)
276 lane_mask = intel_de_read(display, PORT_TX_DFLEXDPSP(tc->phy_fia));
277
278 drm_WARN_ON(display->drm, lane_mask == 0xffffffff);
279 assert_tc_cold_blocked(tc);
280
281 lane_mask &= DP_LANE_ASSIGNMENT_MASK(tc->phy_fia_idx);
282 return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
283}
284
285static char pin_assignment_name(enum intel_tc_pin_assignment pin_assignment)
286{
287 if (pin_assignment == INTEL_TC_PIN_ASSIGNMENT_NONE)
288 return '-';
289
290 return 'A' + pin_assignment - INTEL_TC_PIN_ASSIGNMENT_A;
291}
292
293static enum intel_tc_pin_assignment
294get_pin_assignment(struct intel_tc_port *tc)
295{
296 struct intel_display *display = to_intel_display(tc->dig_port);
297 enum tc_port tc_port = intel_encoder_to_tc(encoder: &tc->dig_port->base);
298 enum intel_tc_pin_assignment pin_assignment;
299 intel_wakeref_t wakeref;
300 i915_reg_t reg;
301 u32 mask;
302 u32 val;
303
304 if (tc->mode == TC_PORT_TBT_ALT)
305 return INTEL_TC_PIN_ASSIGNMENT_NONE;
306
307 if (DISPLAY_VER(display) >= 20) {
308 reg = TCSS_DDI_STATUS(tc_port);
309 mask = TCSS_DDI_STATUS_PIN_ASSIGNMENT_MASK;
310 } else {
311 reg = PORT_TX_DFLEXPA1(tc->phy_fia);
312 mask = DP_PIN_ASSIGNMENT_MASK(tc->phy_fia_idx);
313 }
314
315 with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref)
316 val = intel_de_read(display, reg);
317
318 drm_WARN_ON(display->drm, val == 0xffffffff);
319 assert_tc_cold_blocked(tc);
320
321 pin_assignment = (val & mask) >> (ffs(mask) - 1);
322
323 switch (pin_assignment) {
324 case INTEL_TC_PIN_ASSIGNMENT_A:
325 case INTEL_TC_PIN_ASSIGNMENT_B:
326 case INTEL_TC_PIN_ASSIGNMENT_F:
327 drm_WARN_ON(display->drm, DISPLAY_VER(display) > 11);
328 break;
329 case INTEL_TC_PIN_ASSIGNMENT_NONE:
330 case INTEL_TC_PIN_ASSIGNMENT_C:
331 case INTEL_TC_PIN_ASSIGNMENT_D:
332 case INTEL_TC_PIN_ASSIGNMENT_E:
333 break;
334 default:
335 MISSING_CASE(pin_assignment);
336 }
337
338 return pin_assignment;
339}
340
341static int mtl_get_max_lane_count(struct intel_tc_port *tc)
342{
343 enum intel_tc_pin_assignment pin_assignment;
344
345 pin_assignment = get_pin_assignment(tc);
346
347 switch (pin_assignment) {
348 case INTEL_TC_PIN_ASSIGNMENT_NONE:
349 return 0;
350 default:
351 MISSING_CASE(pin_assignment);
352 fallthrough;
353 case INTEL_TC_PIN_ASSIGNMENT_D:
354 return 2;
355 case INTEL_TC_PIN_ASSIGNMENT_C:
356 case INTEL_TC_PIN_ASSIGNMENT_E:
357 return 4;
358 }
359}
360
361static int icl_get_max_lane_count(struct intel_tc_port *tc)
362{
363 u32 lane_mask = 0;
364
365 lane_mask = get_lane_mask(tc);
366
367 switch (lane_mask) {
368 default:
369 MISSING_CASE(lane_mask);
370 fallthrough;
371 case 0x1:
372 case 0x2:
373 case 0x4:
374 case 0x8:
375 return 1;
376 case 0x3:
377 case 0xc:
378 return 2;
379 case 0xf:
380 return 4;
381 }
382}
383
384static int get_max_lane_count(struct intel_tc_port *tc)
385{
386 struct intel_display *display = to_intel_display(tc->dig_port);
387
388 if (tc->mode != TC_PORT_DP_ALT)
389 return 4;
390
391 if (DISPLAY_VER(display) >= 14)
392 return mtl_get_max_lane_count(tc);
393
394 return icl_get_max_lane_count(tc);
395}
396
397static void read_pin_configuration(struct intel_tc_port *tc)
398{
399 tc->pin_assignment = get_pin_assignment(tc);
400 tc->max_lane_count = get_max_lane_count(tc);
401}
402
403int intel_tc_port_max_lane_count(struct intel_digital_port *dig_port)
404{
405 struct intel_tc_port *tc = to_tc_port(dig_port);
406
407 if (!intel_encoder_is_tc(encoder: &dig_port->base))
408 return 4;
409
410 return tc->max_lane_count;
411}
412
413enum intel_tc_pin_assignment
414intel_tc_port_get_pin_assignment(struct intel_digital_port *dig_port)
415{
416 struct intel_tc_port *tc = to_tc_port(dig_port);
417
418 if (!intel_encoder_is_tc(encoder: &dig_port->base))
419 return INTEL_TC_PIN_ASSIGNMENT_NONE;
420
421 return tc->pin_assignment;
422}
423
424void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
425 int required_lanes)
426{
427 struct intel_display *display = to_intel_display(dig_port);
428 struct intel_tc_port *tc = to_tc_port(dig_port);
429 bool lane_reversal = dig_port->lane_reversal;
430 u32 val;
431
432 if (DISPLAY_VER(display) >= 14)
433 return;
434
435 drm_WARN_ON(display->drm,
436 lane_reversal && tc->mode != TC_PORT_LEGACY);
437
438 assert_tc_cold_blocked(tc);
439
440 val = intel_de_read(display, PORT_TX_DFLEXDPMLE1(tc->phy_fia));
441 val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc->phy_fia_idx);
442
443 switch (required_lanes) {
444 case 1:
445 val |= lane_reversal ?
446 DFLEXDPMLE1_DPMLETC_ML3(tc->phy_fia_idx) :
447 DFLEXDPMLE1_DPMLETC_ML0(tc->phy_fia_idx);
448 break;
449 case 2:
450 val |= lane_reversal ?
451 DFLEXDPMLE1_DPMLETC_ML3_2(tc->phy_fia_idx) :
452 DFLEXDPMLE1_DPMLETC_ML1_0(tc->phy_fia_idx);
453 break;
454 case 4:
455 val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc->phy_fia_idx);
456 break;
457 default:
458 MISSING_CASE(required_lanes);
459 }
460
461 intel_de_write(display, PORT_TX_DFLEXDPMLE1(tc->phy_fia), val);
462}
463
464static void tc_port_fixup_legacy_flag(struct intel_tc_port *tc,
465 u32 live_status_mask)
466{
467 struct intel_display *display = to_intel_display(tc->dig_port);
468 u32 valid_hpd_mask;
469
470 drm_WARN_ON(display->drm, tc->mode != TC_PORT_DISCONNECTED);
471
472 if (hweight32(live_status_mask) != 1)
473 return;
474
475 if (tc->legacy_port)
476 valid_hpd_mask = BIT(TC_PORT_LEGACY);
477 else
478 valid_hpd_mask = BIT(TC_PORT_DP_ALT) |
479 BIT(TC_PORT_TBT_ALT);
480
481 if (!(live_status_mask & ~valid_hpd_mask))
482 return;
483
484 /* If live status mismatches the VBT flag, trust the live status. */
485 drm_dbg_kms(display->drm,
486 "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n",
487 tc->port_name, live_status_mask, valid_hpd_mask);
488
489 tc->legacy_port = !tc->legacy_port;
490}
491
492static void tc_phy_load_fia_params(struct intel_tc_port *tc, bool modular_fia)
493{
494 enum tc_port tc_port = intel_encoder_to_tc(encoder: &tc->dig_port->base);
495
496 /*
497 * Each Modular FIA instance houses 2 TC ports. In SOC that has more
498 * than two TC ports, there are multiple instances of Modular FIA.
499 */
500 if (modular_fia) {
501 tc->phy_fia = tc_port / 2;
502 tc->phy_fia_idx = tc_port % 2;
503 } else {
504 tc->phy_fia = FIA1;
505 tc->phy_fia_idx = tc_port;
506 }
507}
508
509/*
510 * ICL TC PHY handlers
511 * -------------------
512 */
513static enum intel_display_power_domain
514icl_tc_phy_cold_off_domain(struct intel_tc_port *tc)
515{
516 struct intel_display *display = to_intel_display(tc->dig_port);
517 struct intel_digital_port *dig_port = tc->dig_port;
518
519 if (tc->legacy_port)
520 return intel_display_power_legacy_aux_domain(display, aux_ch: dig_port->aux_ch);
521
522 return POWER_DOMAIN_TC_COLD_OFF;
523}
524
525static u32 icl_tc_phy_hpd_live_status(struct intel_tc_port *tc)
526{
527 struct intel_display *display = to_intel_display(tc->dig_port);
528 struct intel_digital_port *dig_port = tc->dig_port;
529 u32 isr_bit = display->hotplug.pch_hpd[dig_port->base.hpd_pin];
530 intel_wakeref_t wakeref;
531 u32 fia_isr;
532 u32 pch_isr;
533 u32 mask = 0;
534
535 with_intel_display_power(display, tc_phy_cold_off_domain(tc), wakeref) {
536 fia_isr = intel_de_read(display, PORT_TX_DFLEXDPSP(tc->phy_fia));
537 pch_isr = intel_de_read(display, SDEISR);
538 }
539
540 if (fia_isr == 0xffffffff) {
541 drm_dbg_kms(display->drm,
542 "Port %s: PHY in TCCOLD, nothing connected\n",
543 tc->port_name);
544 return mask;
545 }
546
547 if (fia_isr & TC_LIVE_STATE_TBT(tc->phy_fia_idx))
548 mask |= BIT(TC_PORT_TBT_ALT);
549 if (fia_isr & TC_LIVE_STATE_TC(tc->phy_fia_idx))
550 mask |= BIT(TC_PORT_DP_ALT);
551
552 if (pch_isr & isr_bit)
553 mask |= BIT(TC_PORT_LEGACY);
554
555 return mask;
556}
557
558/*
559 * Return the PHY status complete flag indicating that display can acquire the
560 * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink
561 * is connected and it's ready to switch the ownership to display. The flag
562 * will be left cleared when a TBT-alt sink is connected, where the PHY is
563 * owned by the TBT subsystem and so switching the ownership to display is not
564 * required.
565 */
566static bool icl_tc_phy_is_ready(struct intel_tc_port *tc)
567{
568 struct intel_display *display = to_intel_display(tc->dig_port);
569 u32 val;
570
571 assert_tc_cold_blocked(tc);
572
573 val = intel_de_read(display, PORT_TX_DFLEXDPPMS(tc->phy_fia));
574 if (val == 0xffffffff) {
575 drm_dbg_kms(display->drm,
576 "Port %s: PHY in TCCOLD, assuming not ready\n",
577 tc->port_name);
578 return false;
579 }
580
581 return val & DP_PHY_MODE_STATUS_COMPLETED(tc->phy_fia_idx);
582}
583
584static bool icl_tc_phy_take_ownership(struct intel_tc_port *tc,
585 bool take)
586{
587 struct intel_display *display = to_intel_display(tc->dig_port);
588 u32 val;
589
590 assert_tc_cold_blocked(tc);
591
592 val = intel_de_read(display, PORT_TX_DFLEXDPCSSS(tc->phy_fia));
593 if (val == 0xffffffff) {
594 drm_dbg_kms(display->drm,
595 "Port %s: PHY in TCCOLD, can't %s ownership\n",
596 tc->port_name, take ? "take" : "release");
597
598 return false;
599 }
600
601 val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx);
602 if (take)
603 val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx);
604
605 intel_de_write(display, PORT_TX_DFLEXDPCSSS(tc->phy_fia), val);
606
607 return true;
608}
609
610static bool icl_tc_phy_is_owned(struct intel_tc_port *tc)
611{
612 struct intel_display *display = to_intel_display(tc->dig_port);
613 u32 val;
614
615 assert_tc_cold_blocked(tc);
616
617 val = intel_de_read(display, PORT_TX_DFLEXDPCSSS(tc->phy_fia));
618 if (val == 0xffffffff) {
619 drm_dbg_kms(display->drm,
620 "Port %s: PHY in TCCOLD, assume not owned\n",
621 tc->port_name);
622 return false;
623 }
624
625 return val & DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx);
626}
627
628static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc)
629{
630 enum intel_display_power_domain domain;
631 intel_wakeref_t tc_cold_wref;
632
633 tc_cold_wref = __tc_cold_block(tc, domain: &domain);
634
635 tc->mode = tc_phy_get_current_mode(tc);
636 if (tc->mode != TC_PORT_DISCONNECTED) {
637 tc->lock_wakeref = tc_cold_block(tc);
638
639 read_pin_configuration(tc);
640 }
641
642 __tc_cold_unblock(tc, domain, wakeref: tc_cold_wref);
643}
644
645/*
646 * This function implements the first part of the Connect Flow described by our
647 * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
648 * lanes, EDID, etc) is done as needed in the typical places.
649 *
650 * Unlike the other ports, type-C ports are not available to use as soon as we
651 * get a hotplug. The type-C PHYs can be shared between multiple controllers:
652 * display, USB, etc. As a result, handshaking through FIA is required around
653 * connect and disconnect to cleanly transfer ownership with the controller and
654 * set the type-C power state.
655 */
656static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc,
657 int required_lanes)
658{
659 struct intel_display *display = to_intel_display(tc->dig_port);
660 struct intel_digital_port *dig_port = tc->dig_port;
661 int max_lanes;
662
663 max_lanes = intel_tc_port_max_lane_count(dig_port);
664 if (tc->mode == TC_PORT_LEGACY) {
665 drm_WARN_ON(display->drm, max_lanes != 4);
666 return true;
667 }
668
669 drm_WARN_ON(display->drm, tc->mode != TC_PORT_DP_ALT);
670
671 /*
672 * Now we have to re-check the live state, in case the port recently
673 * became disconnected. Not necessary for legacy mode.
674 */
675 if (!(tc_phy_hpd_live_status(tc) & BIT(TC_PORT_DP_ALT))) {
676 drm_dbg_kms(display->drm, "Port %s: PHY sudden disconnect\n",
677 tc->port_name);
678 return false;
679 }
680
681 if (max_lanes < required_lanes) {
682 drm_dbg_kms(display->drm,
683 "Port %s: PHY max lanes %d < required lanes %d\n",
684 tc->port_name,
685 max_lanes, required_lanes);
686 return false;
687 }
688
689 return true;
690}
691
692static bool icl_tc_phy_connect(struct intel_tc_port *tc,
693 int required_lanes)
694{
695 struct intel_display *display = to_intel_display(tc->dig_port);
696
697 tc->lock_wakeref = tc_cold_block(tc);
698
699 if (tc->mode == TC_PORT_TBT_ALT) {
700 read_pin_configuration(tc);
701
702 return true;
703 }
704
705 if ((!tc_phy_is_ready(tc) ||
706 !icl_tc_phy_take_ownership(tc, take: true)) &&
707 !drm_WARN_ON(display->drm, tc->mode == TC_PORT_LEGACY)) {
708 drm_dbg_kms(display->drm, "Port %s: can't take PHY ownership (ready %s)\n",
709 tc->port_name,
710 str_yes_no(tc_phy_is_ready(tc)));
711 goto out_unblock_tc_cold;
712 }
713
714 read_pin_configuration(tc);
715
716 if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
717 goto out_release_phy;
718
719 return true;
720
721out_release_phy:
722 icl_tc_phy_take_ownership(tc, take: false);
723out_unblock_tc_cold:
724 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
725
726 return false;
727}
728
729/*
730 * See the comment at the connect function. This implements the Disconnect
731 * Flow.
732 */
733static void icl_tc_phy_disconnect(struct intel_tc_port *tc)
734{
735 switch (tc->mode) {
736 case TC_PORT_LEGACY:
737 case TC_PORT_DP_ALT:
738 icl_tc_phy_take_ownership(tc, take: false);
739 fallthrough;
740 case TC_PORT_TBT_ALT:
741 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
742 break;
743 default:
744 MISSING_CASE(tc->mode);
745 }
746}
747
748static void icl_tc_phy_init(struct intel_tc_port *tc)
749{
750 tc_phy_load_fia_params(tc, modular_fia: false);
751}
752
753static const struct intel_tc_phy_ops icl_tc_phy_ops = {
754 .cold_off_domain = icl_tc_phy_cold_off_domain,
755 .hpd_live_status = icl_tc_phy_hpd_live_status,
756 .is_ready = icl_tc_phy_is_ready,
757 .is_owned = icl_tc_phy_is_owned,
758 .get_hw_state = icl_tc_phy_get_hw_state,
759 .connect = icl_tc_phy_connect,
760 .disconnect = icl_tc_phy_disconnect,
761 .init = icl_tc_phy_init,
762};
763
764/*
765 * TGL TC PHY handlers
766 * -------------------
767 */
768static enum intel_display_power_domain
769tgl_tc_phy_cold_off_domain(struct intel_tc_port *tc)
770{
771 return POWER_DOMAIN_TC_COLD_OFF;
772}
773
774static void tgl_tc_phy_init(struct intel_tc_port *tc)
775{
776 struct intel_display *display = to_intel_display(tc->dig_port);
777 intel_wakeref_t wakeref;
778 u32 val;
779
780 with_intel_display_power(display, tc_phy_cold_off_domain(tc), wakeref)
781 val = intel_de_read(display, PORT_TX_DFLEXDPSP(FIA1));
782
783 drm_WARN_ON(display->drm, val == 0xffffffff);
784
785 tc_phy_load_fia_params(tc, modular_fia: val & MODULAR_FIA_MASK);
786}
787
788static const struct intel_tc_phy_ops tgl_tc_phy_ops = {
789 .cold_off_domain = tgl_tc_phy_cold_off_domain,
790 .hpd_live_status = icl_tc_phy_hpd_live_status,
791 .is_ready = icl_tc_phy_is_ready,
792 .is_owned = icl_tc_phy_is_owned,
793 .get_hw_state = icl_tc_phy_get_hw_state,
794 .connect = icl_tc_phy_connect,
795 .disconnect = icl_tc_phy_disconnect,
796 .init = tgl_tc_phy_init,
797};
798
799/*
800 * ADLP TC PHY handlers
801 * --------------------
802 */
803static enum intel_display_power_domain
804adlp_tc_phy_cold_off_domain(struct intel_tc_port *tc)
805{
806 struct intel_display *display = to_intel_display(tc->dig_port);
807 struct intel_digital_port *dig_port = tc->dig_port;
808
809 if (tc->mode != TC_PORT_TBT_ALT)
810 return intel_display_power_legacy_aux_domain(display, aux_ch: dig_port->aux_ch);
811
812 return POWER_DOMAIN_TC_COLD_OFF;
813}
814
815static u32 adlp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
816{
817 struct intel_display *display = to_intel_display(tc->dig_port);
818 struct intel_digital_port *dig_port = tc->dig_port;
819 enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
820 u32 cpu_isr_bits = display->hotplug.hpd[hpd_pin];
821 u32 pch_isr_bit = display->hotplug.pch_hpd[hpd_pin];
822 intel_wakeref_t wakeref;
823 u32 cpu_isr;
824 u32 pch_isr;
825 u32 mask = 0;
826
827 with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
828 cpu_isr = intel_de_read(display, GEN11_DE_HPD_ISR);
829 pch_isr = intel_de_read(display, SDEISR);
830 }
831
832 if (cpu_isr & (cpu_isr_bits & GEN11_DE_TC_HOTPLUG_MASK))
833 mask |= BIT(TC_PORT_DP_ALT);
834 if (cpu_isr & (cpu_isr_bits & GEN11_DE_TBT_HOTPLUG_MASK))
835 mask |= BIT(TC_PORT_TBT_ALT);
836
837 if (pch_isr & pch_isr_bit)
838 mask |= BIT(TC_PORT_LEGACY);
839
840 return mask;
841}
842
843/*
844 * Return the PHY status complete flag indicating that display can acquire the
845 * PHY ownership. The IOM firmware sets this flag when it's ready to switch
846 * the ownership to display, regardless of what sink is connected (TBT-alt,
847 * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT
848 * subsystem and so switching the ownership to display is not required.
849 */
850static bool adlp_tc_phy_is_ready(struct intel_tc_port *tc)
851{
852 struct intel_display *display = to_intel_display(tc->dig_port);
853 enum tc_port tc_port = intel_encoder_to_tc(encoder: &tc->dig_port->base);
854 u32 val;
855
856 assert_display_core_power_enabled(tc);
857
858 val = intel_de_read(display, TCSS_DDI_STATUS(tc_port));
859 if (val == 0xffffffff) {
860 drm_dbg_kms(display->drm,
861 "Port %s: PHY in TCCOLD, assuming not ready\n",
862 tc->port_name);
863 return false;
864 }
865
866 return val & TCSS_DDI_STATUS_READY;
867}
868
869static bool adlp_tc_phy_take_ownership(struct intel_tc_port *tc,
870 bool take)
871{
872 struct intel_display *display = to_intel_display(tc->dig_port);
873 enum port port = tc->dig_port->base.port;
874
875 assert_tc_port_power_enabled(tc);
876
877 intel_de_rmw(display, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP,
878 set: take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0);
879
880 return true;
881}
882
883static bool adlp_tc_phy_is_owned(struct intel_tc_port *tc)
884{
885 struct intel_display *display = to_intel_display(tc->dig_port);
886 enum port port = tc->dig_port->base.port;
887 u32 val;
888
889 assert_tc_port_power_enabled(tc);
890
891 val = intel_de_read(display, DDI_BUF_CTL(port));
892 return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP;
893}
894
895static void adlp_tc_phy_get_hw_state(struct intel_tc_port *tc)
896{
897 struct intel_display *display = to_intel_display(tc->dig_port);
898 enum intel_display_power_domain port_power_domain =
899 tc_port_power_domain(tc);
900 intel_wakeref_t port_wakeref;
901
902 port_wakeref = intel_display_power_get(display, domain: port_power_domain);
903
904 tc->mode = tc_phy_get_current_mode(tc);
905 if (tc->mode != TC_PORT_DISCONNECTED) {
906 tc->lock_wakeref = tc_cold_block(tc);
907
908 read_pin_configuration(tc);
909 }
910
911 intel_display_power_put(display, domain: port_power_domain, wakeref: port_wakeref);
912}
913
914static bool adlp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
915{
916 struct intel_display *display = to_intel_display(tc->dig_port);
917 enum intel_display_power_domain port_power_domain =
918 tc_port_power_domain(tc);
919 intel_wakeref_t port_wakeref;
920
921 if (tc->mode == TC_PORT_TBT_ALT) {
922 tc->lock_wakeref = tc_cold_block(tc);
923
924 read_pin_configuration(tc);
925
926 return true;
927 }
928
929 port_wakeref = intel_display_power_get(display, domain: port_power_domain);
930
931 if (!adlp_tc_phy_take_ownership(tc, take: true) &&
932 !drm_WARN_ON(display->drm, tc->mode == TC_PORT_LEGACY)) {
933 drm_dbg_kms(display->drm, "Port %s: can't take PHY ownership\n",
934 tc->port_name);
935 goto out_put_port_power;
936 }
937
938 if (!tc_phy_is_ready(tc) &&
939 !drm_WARN_ON(display->drm, tc->mode == TC_PORT_LEGACY)) {
940 drm_dbg_kms(display->drm, "Port %s: PHY not ready\n",
941 tc->port_name);
942 goto out_release_phy;
943 }
944
945 tc->lock_wakeref = tc_cold_block(tc);
946
947 read_pin_configuration(tc);
948
949 if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
950 goto out_unblock_tc_cold;
951
952 intel_display_power_put(display, domain: port_power_domain, wakeref: port_wakeref);
953
954 return true;
955
956out_unblock_tc_cold:
957 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
958out_release_phy:
959 adlp_tc_phy_take_ownership(tc, take: false);
960out_put_port_power:
961 intel_display_power_put(display, domain: port_power_domain, wakeref: port_wakeref);
962
963 return false;
964}
965
966static void adlp_tc_phy_disconnect(struct intel_tc_port *tc)
967{
968 struct intel_display *display = to_intel_display(tc->dig_port);
969 enum intel_display_power_domain port_power_domain =
970 tc_port_power_domain(tc);
971 intel_wakeref_t port_wakeref;
972
973 port_wakeref = intel_display_power_get(display, domain: port_power_domain);
974
975 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
976
977 switch (tc->mode) {
978 case TC_PORT_LEGACY:
979 case TC_PORT_DP_ALT:
980 adlp_tc_phy_take_ownership(tc, take: false);
981 fallthrough;
982 case TC_PORT_TBT_ALT:
983 break;
984 default:
985 MISSING_CASE(tc->mode);
986 }
987
988 intel_display_power_put(display, domain: port_power_domain, wakeref: port_wakeref);
989}
990
991static void adlp_tc_phy_init(struct intel_tc_port *tc)
992{
993 tc_phy_load_fia_params(tc, modular_fia: true);
994}
995
996static const struct intel_tc_phy_ops adlp_tc_phy_ops = {
997 .cold_off_domain = adlp_tc_phy_cold_off_domain,
998 .hpd_live_status = adlp_tc_phy_hpd_live_status,
999 .is_ready = adlp_tc_phy_is_ready,
1000 .is_owned = adlp_tc_phy_is_owned,
1001 .get_hw_state = adlp_tc_phy_get_hw_state,
1002 .connect = adlp_tc_phy_connect,
1003 .disconnect = adlp_tc_phy_disconnect,
1004 .init = adlp_tc_phy_init,
1005};
1006
1007/*
1008 * XELPDP TC PHY handlers
1009 * ----------------------
1010 */
1011static u32 xelpdp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
1012{
1013 struct intel_display *display = to_intel_display(tc->dig_port);
1014 struct intel_digital_port *dig_port = tc->dig_port;
1015 enum hpd_pin hpd_pin = dig_port->base.hpd_pin;
1016 u32 pica_isr_bits = display->hotplug.hpd[hpd_pin];
1017 u32 pch_isr_bit = display->hotplug.pch_hpd[hpd_pin];
1018 intel_wakeref_t wakeref;
1019 u32 pica_isr;
1020 u32 pch_isr;
1021 u32 mask = 0;
1022
1023 with_intel_display_power(display, POWER_DOMAIN_DISPLAY_CORE, wakeref) {
1024 pica_isr = intel_de_read(display, PICAINTERRUPT_ISR);
1025 pch_isr = intel_de_read(display, SDEISR);
1026 }
1027
1028 if (pica_isr & (pica_isr_bits & XELPDP_DP_ALT_HOTPLUG_MASK))
1029 mask |= BIT(TC_PORT_DP_ALT);
1030 if (pica_isr & (pica_isr_bits & XELPDP_TBT_HOTPLUG_MASK))
1031 mask |= BIT(TC_PORT_TBT_ALT);
1032
1033 if (tc->legacy_port && (pch_isr & pch_isr_bit))
1034 mask |= BIT(TC_PORT_LEGACY);
1035
1036 return mask;
1037}
1038
1039static bool
1040xelpdp_tc_phy_tcss_power_is_enabled(struct intel_tc_port *tc)
1041{
1042 struct intel_display *display = to_intel_display(tc->dig_port);
1043 enum port port = tc->dig_port->base.port;
1044 i915_reg_t reg = XELPDP_PORT_BUF_CTL1(display, port);
1045
1046 assert_tc_cold_blocked(tc);
1047
1048 return intel_de_read(display, reg) & XELPDP_TCSS_POWER_STATE;
1049}
1050
1051static bool
1052xelpdp_tc_phy_wait_for_tcss_power(struct intel_tc_port *tc, bool enabled)
1053{
1054 struct intel_display *display = to_intel_display(tc->dig_port);
1055 bool is_enabled;
1056 int ret;
1057
1058 ret = poll_timeout_us(is_enabled = xelpdp_tc_phy_tcss_power_is_enabled(tc),
1059 is_enabled == enabled,
1060 200, 5000, false);
1061 if (ret) {
1062 drm_dbg_kms(display->drm,
1063 "Port %s: timeout waiting for TCSS power to get %s\n",
1064 str_enabled_disabled(enabled),
1065 tc->port_name);
1066 return false;
1067 }
1068
1069 return true;
1070}
1071
1072/*
1073 * Gfx driver WA 14020908590 for PTL tcss_rxdetect_clkswb_req/ack
1074 * handshake violation when pwwreq= 0->1 during TC7/10 entry
1075 */
1076static void xelpdp_tc_power_request_wa(struct intel_display *display, bool enable)
1077{
1078 /* check if mailbox is running busy */
1079 if (intel_de_wait_for_clear(display, TCSS_DISP_MAILBOX_IN_CMD,
1080 TCSS_DISP_MAILBOX_IN_CMD_RUN_BUSY, timeout_ms: 10)) {
1081 drm_dbg_kms(display->drm,
1082 "Timeout waiting for TCSS mailbox run/busy bit to clear\n");
1083 return;
1084 }
1085
1086 intel_de_write(display, TCSS_DISP_MAILBOX_IN_DATA, val: enable ? 1 : 0);
1087 intel_de_write(display, TCSS_DISP_MAILBOX_IN_CMD,
1088 TCSS_DISP_MAILBOX_IN_CMD_RUN_BUSY |
1089 TCSS_DISP_MAILBOX_IN_CMD_DATA(0x1));
1090
1091 /* wait to clear mailbox running busy bit before continuing */
1092 if (intel_de_wait_for_clear(display, TCSS_DISP_MAILBOX_IN_CMD,
1093 TCSS_DISP_MAILBOX_IN_CMD_RUN_BUSY, timeout_ms: 10)) {
1094 drm_dbg_kms(display->drm,
1095 "Timeout after writing data to mailbox. Mailbox run/busy bit did not clear\n");
1096 return;
1097 }
1098}
1099
1100static void __xelpdp_tc_phy_enable_tcss_power(struct intel_tc_port *tc, bool enable)
1101{
1102 struct intel_display *display = to_intel_display(tc->dig_port);
1103 enum port port = tc->dig_port->base.port;
1104 i915_reg_t reg = XELPDP_PORT_BUF_CTL1(display, port);
1105 u32 val;
1106
1107 assert_tc_cold_blocked(tc);
1108
1109 if (DISPLAY_VER(display) == 30)
1110 xelpdp_tc_power_request_wa(display, enable);
1111
1112 val = intel_de_read(display, reg);
1113 if (enable)
1114 val |= XELPDP_TCSS_POWER_REQUEST;
1115 else
1116 val &= ~XELPDP_TCSS_POWER_REQUEST;
1117 intel_de_write(display, reg, val);
1118}
1119
1120static bool xelpdp_tc_phy_enable_tcss_power(struct intel_tc_port *tc, bool enable)
1121{
1122 struct intel_display *display = to_intel_display(tc->dig_port);
1123
1124 __xelpdp_tc_phy_enable_tcss_power(tc, enable);
1125
1126 if (enable && !tc_phy_wait_for_ready(tc))
1127 goto out_disable;
1128
1129 if (!xelpdp_tc_phy_wait_for_tcss_power(tc, enabled: enable))
1130 goto out_disable;
1131
1132 return true;
1133
1134out_disable:
1135 if (drm_WARN_ON(display->drm, tc->mode == TC_PORT_LEGACY))
1136 return false;
1137
1138 if (!enable)
1139 return false;
1140
1141 __xelpdp_tc_phy_enable_tcss_power(tc, enable: false);
1142 xelpdp_tc_phy_wait_for_tcss_power(tc, enabled: false);
1143
1144 return false;
1145}
1146
1147static void xelpdp_tc_phy_take_ownership(struct intel_tc_port *tc, bool take)
1148{
1149 struct intel_display *display = to_intel_display(tc->dig_port);
1150 enum port port = tc->dig_port->base.port;
1151 i915_reg_t reg = XELPDP_PORT_BUF_CTL1(display, port);
1152 u32 val;
1153
1154 assert_tc_cold_blocked(tc);
1155
1156 val = intel_de_read(display, reg);
1157 if (take)
1158 val |= XELPDP_TC_PHY_OWNERSHIP;
1159 else
1160 val &= ~XELPDP_TC_PHY_OWNERSHIP;
1161 intel_de_write(display, reg, val);
1162}
1163
1164static bool xelpdp_tc_phy_is_owned(struct intel_tc_port *tc)
1165{
1166 struct intel_display *display = to_intel_display(tc->dig_port);
1167 enum port port = tc->dig_port->base.port;
1168 i915_reg_t reg = XELPDP_PORT_BUF_CTL1(display, port);
1169
1170 assert_tc_cold_blocked(tc);
1171
1172 return intel_de_read(display, reg) & XELPDP_TC_PHY_OWNERSHIP;
1173}
1174
1175static void xelpdp_tc_phy_get_hw_state(struct intel_tc_port *tc)
1176{
1177 struct intel_display *display = to_intel_display(tc->dig_port);
1178 intel_wakeref_t tc_cold_wref;
1179 enum intel_display_power_domain domain;
1180
1181 tc_cold_wref = __tc_cold_block(tc, domain: &domain);
1182
1183 tc->mode = tc_phy_get_current_mode(tc);
1184 if (tc->mode != TC_PORT_DISCONNECTED) {
1185 tc->lock_wakeref = tc_cold_block(tc);
1186
1187 read_pin_configuration(tc);
1188 /*
1189 * Set a valid lane count value for a DP-alt sink which got
1190 * disconnected. The driver can only disable the output on this PHY.
1191 */
1192 if (tc->max_lane_count == 0)
1193 tc->max_lane_count = 4;
1194 }
1195
1196 drm_WARN_ON(display->drm,
1197 (tc->mode == TC_PORT_DP_ALT || tc->mode == TC_PORT_LEGACY) &&
1198 !xelpdp_tc_phy_tcss_power_is_enabled(tc));
1199
1200 __tc_cold_unblock(tc, domain, wakeref: tc_cold_wref);
1201}
1202
1203static bool xelpdp_tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
1204{
1205 tc->lock_wakeref = tc_cold_block(tc);
1206
1207 if (tc->mode == TC_PORT_TBT_ALT) {
1208 read_pin_configuration(tc);
1209
1210 return true;
1211 }
1212
1213 if (!xelpdp_tc_phy_enable_tcss_power(tc, enable: true))
1214 goto out_unblock_tccold;
1215
1216 xelpdp_tc_phy_take_ownership(tc, take: true);
1217
1218 read_pin_configuration(tc);
1219
1220 if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
1221 goto out_release_phy;
1222
1223 return true;
1224
1225out_release_phy:
1226 xelpdp_tc_phy_take_ownership(tc, take: false);
1227 xelpdp_tc_phy_wait_for_tcss_power(tc, enabled: false);
1228
1229out_unblock_tccold:
1230 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
1231
1232 return false;
1233}
1234
1235static void xelpdp_tc_phy_disconnect(struct intel_tc_port *tc)
1236{
1237 switch (tc->mode) {
1238 case TC_PORT_LEGACY:
1239 case TC_PORT_DP_ALT:
1240 xelpdp_tc_phy_take_ownership(tc, take: false);
1241 xelpdp_tc_phy_enable_tcss_power(tc, enable: false);
1242 fallthrough;
1243 case TC_PORT_TBT_ALT:
1244 tc_cold_unblock(tc, fetch_and_zero(&tc->lock_wakeref));
1245 break;
1246 default:
1247 MISSING_CASE(tc->mode);
1248 }
1249}
1250
1251static const struct intel_tc_phy_ops xelpdp_tc_phy_ops = {
1252 .cold_off_domain = tgl_tc_phy_cold_off_domain,
1253 .hpd_live_status = xelpdp_tc_phy_hpd_live_status,
1254 .is_ready = adlp_tc_phy_is_ready,
1255 .is_owned = xelpdp_tc_phy_is_owned,
1256 .get_hw_state = xelpdp_tc_phy_get_hw_state,
1257 .connect = xelpdp_tc_phy_connect,
1258 .disconnect = xelpdp_tc_phy_disconnect,
1259 .init = adlp_tc_phy_init,
1260};
1261
1262/*
1263 * Generic TC PHY handlers
1264 * -----------------------
1265 */
1266static enum intel_display_power_domain
1267tc_phy_cold_off_domain(struct intel_tc_port *tc)
1268{
1269 return tc->phy_ops->cold_off_domain(tc);
1270}
1271
1272static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc)
1273{
1274 struct intel_display *display = to_intel_display(tc->dig_port);
1275 u32 mask;
1276
1277 mask = tc->phy_ops->hpd_live_status(tc);
1278
1279 /* The sink can be connected only in a single mode. */
1280 drm_WARN_ON_ONCE(display->drm, hweight32(mask) > 1);
1281
1282 return mask;
1283}
1284
1285static bool tc_phy_is_ready(struct intel_tc_port *tc)
1286{
1287 return tc->phy_ops->is_ready(tc);
1288}
1289
1290static bool tc_phy_is_owned(struct intel_tc_port *tc)
1291{
1292 return tc->phy_ops->is_owned(tc);
1293}
1294
1295static void tc_phy_get_hw_state(struct intel_tc_port *tc)
1296{
1297 tc->phy_ops->get_hw_state(tc);
1298}
1299
1300/* Is the PHY owned by display i.e. is it in legacy or DP-alt mode? */
1301static bool tc_phy_owned_by_display(struct intel_tc_port *tc,
1302 bool phy_is_ready, bool phy_is_owned)
1303{
1304 struct intel_display *display = to_intel_display(tc->dig_port);
1305
1306 if (DISPLAY_VER(display) < 20) {
1307 drm_WARN_ON(display->drm, phy_is_owned && !phy_is_ready);
1308
1309 return phy_is_ready && phy_is_owned;
1310 } else {
1311 return phy_is_owned;
1312 }
1313}
1314
1315static bool tc_phy_is_connected(struct intel_tc_port *tc,
1316 enum icl_port_dpll_id port_pll_type)
1317{
1318 struct intel_display *display = to_intel_display(tc->dig_port);
1319 bool phy_is_ready = tc_phy_is_ready(tc);
1320 bool phy_is_owned = tc_phy_is_owned(tc);
1321 bool is_connected;
1322
1323 if (tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned))
1324 is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY;
1325 else
1326 is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT;
1327
1328 drm_dbg_kms(display->drm,
1329 "Port %s: PHY connected: %s (ready: %s, owned: %s, pll_type: %s)\n",
1330 tc->port_name,
1331 str_yes_no(is_connected),
1332 str_yes_no(phy_is_ready),
1333 str_yes_no(phy_is_owned),
1334 port_pll_type == ICL_PORT_DPLL_DEFAULT ? "tbt" : "non-tbt");
1335
1336 return is_connected;
1337}
1338
1339static bool tc_phy_wait_for_ready(struct intel_tc_port *tc)
1340{
1341 struct intel_display *display = to_intel_display(tc->dig_port);
1342 bool is_ready;
1343 int ret;
1344
1345 ret = poll_timeout_us(is_ready = tc_phy_is_ready(tc),
1346 is_ready,
1347 1000, 500 * 1000, false);
1348 if (ret) {
1349 drm_err(display->drm, "Port %s: timeout waiting for PHY ready\n",
1350 tc->port_name);
1351
1352 return false;
1353 }
1354
1355 return true;
1356}
1357
1358static enum tc_port_mode
1359hpd_mask_to_tc_mode(u32 live_status_mask)
1360{
1361 if (live_status_mask)
1362 return fls(x: live_status_mask) - 1;
1363
1364 return TC_PORT_DISCONNECTED;
1365}
1366
1367static enum tc_port_mode
1368tc_phy_hpd_live_mode(struct intel_tc_port *tc)
1369{
1370 u32 live_status_mask = tc_phy_hpd_live_status(tc);
1371
1372 return hpd_mask_to_tc_mode(live_status_mask);
1373}
1374
1375static enum tc_port_mode
1376get_tc_mode_in_phy_owned_state(struct intel_tc_port *tc,
1377 enum tc_port_mode live_mode)
1378{
1379 switch (live_mode) {
1380 case TC_PORT_LEGACY:
1381 case TC_PORT_DP_ALT:
1382 return live_mode;
1383 default:
1384 MISSING_CASE(live_mode);
1385 fallthrough;
1386 case TC_PORT_TBT_ALT:
1387 case TC_PORT_DISCONNECTED:
1388 if (tc->legacy_port)
1389 return TC_PORT_LEGACY;
1390 else
1391 return TC_PORT_DP_ALT;
1392 }
1393}
1394
1395static enum tc_port_mode
1396get_tc_mode_in_phy_not_owned_state(struct intel_tc_port *tc,
1397 enum tc_port_mode live_mode)
1398{
1399 switch (live_mode) {
1400 case TC_PORT_LEGACY:
1401 return TC_PORT_DISCONNECTED;
1402 case TC_PORT_DP_ALT:
1403 case TC_PORT_TBT_ALT:
1404 return TC_PORT_TBT_ALT;
1405 default:
1406 MISSING_CASE(live_mode);
1407 fallthrough;
1408 case TC_PORT_DISCONNECTED:
1409 if (tc->legacy_port)
1410 return TC_PORT_DISCONNECTED;
1411 else
1412 return TC_PORT_TBT_ALT;
1413 }
1414}
1415
1416static enum tc_port_mode
1417tc_phy_get_current_mode(struct intel_tc_port *tc)
1418{
1419 struct intel_display *display = to_intel_display(tc->dig_port);
1420 enum tc_port_mode live_mode = tc_phy_hpd_live_mode(tc);
1421 bool phy_is_ready;
1422 bool phy_is_owned;
1423 enum tc_port_mode mode;
1424
1425 /*
1426 * For legacy ports the IOM firmware initializes the PHY during boot-up
1427 * and system resume whether or not a sink is connected. Wait here for
1428 * the initialization to get ready.
1429 */
1430 if (tc->legacy_port)
1431 tc_phy_wait_for_ready(tc);
1432
1433 phy_is_ready = tc_phy_is_ready(tc);
1434 phy_is_owned = tc_phy_is_owned(tc);
1435
1436 if (!tc_phy_owned_by_display(tc, phy_is_ready, phy_is_owned)) {
1437 mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode);
1438 } else {
1439 drm_WARN_ON(display->drm, live_mode == TC_PORT_TBT_ALT);
1440 mode = get_tc_mode_in_phy_owned_state(tc, live_mode);
1441 }
1442
1443 drm_dbg_kms(display->drm,
1444 "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n",
1445 tc->port_name,
1446 tc_port_mode_name(mode),
1447 str_yes_no(phy_is_ready),
1448 str_yes_no(phy_is_owned),
1449 tc_port_mode_name(live_mode));
1450
1451 return mode;
1452}
1453
1454static enum tc_port_mode default_tc_mode(struct intel_tc_port *tc)
1455{
1456 if (tc->legacy_port)
1457 return TC_PORT_LEGACY;
1458
1459 return TC_PORT_TBT_ALT;
1460}
1461
1462static enum tc_port_mode
1463hpd_mask_to_target_mode(struct intel_tc_port *tc, u32 live_status_mask)
1464{
1465 enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask);
1466
1467 if (mode != TC_PORT_DISCONNECTED)
1468 return mode;
1469
1470 return default_tc_mode(tc);
1471}
1472
1473static enum tc_port_mode
1474tc_phy_get_target_mode(struct intel_tc_port *tc)
1475{
1476 u32 live_status_mask = tc_phy_hpd_live_status(tc);
1477
1478 return hpd_mask_to_target_mode(tc, live_status_mask);
1479}
1480
1481static void tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
1482{
1483 struct intel_display *display = to_intel_display(tc->dig_port);
1484 u32 live_status_mask = tc_phy_hpd_live_status(tc);
1485 bool connected;
1486
1487 tc_port_fixup_legacy_flag(tc, live_status_mask);
1488
1489 tc->mode = hpd_mask_to_target_mode(tc, live_status_mask);
1490
1491 connected = tc->phy_ops->connect(tc, required_lanes);
1492 if (!connected && tc->mode != default_tc_mode(tc)) {
1493 tc->mode = default_tc_mode(tc);
1494 connected = tc->phy_ops->connect(tc, required_lanes);
1495 }
1496
1497 drm_WARN_ON(display->drm, !connected);
1498}
1499
1500static void tc_phy_disconnect(struct intel_tc_port *tc)
1501{
1502 if (tc->mode != TC_PORT_DISCONNECTED) {
1503 tc->phy_ops->disconnect(tc);
1504 tc->mode = TC_PORT_DISCONNECTED;
1505 }
1506}
1507
1508static void tc_phy_init(struct intel_tc_port *tc)
1509{
1510 mutex_lock(lock: &tc->lock);
1511 tc->phy_ops->init(tc);
1512 mutex_unlock(lock: &tc->lock);
1513}
1514
1515static void intel_tc_port_reset_mode(struct intel_tc_port *tc,
1516 int required_lanes, bool force_disconnect)
1517{
1518 struct intel_display *display = to_intel_display(tc->dig_port);
1519 struct intel_digital_port *dig_port = tc->dig_port;
1520 enum tc_port_mode old_tc_mode = tc->mode;
1521
1522 intel_display_power_flush_work(display);
1523 if (!intel_tc_cold_requires_aux_pw(dig_port)) {
1524 enum intel_display_power_domain aux_domain;
1525
1526 aux_domain = intel_aux_power_domain(dig_port);
1527 if (intel_display_power_is_enabled(display, domain: aux_domain))
1528 drm_dbg_kms(display->drm, "Port %s: AUX unexpectedly powered\n",
1529 tc->port_name);
1530 }
1531
1532 tc_phy_disconnect(tc);
1533 if (!force_disconnect)
1534 tc_phy_connect(tc, required_lanes);
1535
1536 drm_dbg_kms(display->drm,
1537 "Port %s: TC port mode reset (%s -> %s) pin assignment: %c max lanes: %d\n",
1538 tc->port_name,
1539 tc_port_mode_name(old_tc_mode),
1540 tc_port_mode_name(tc->mode),
1541 pin_assignment_name(tc->pin_assignment),
1542 tc->max_lane_count);
1543}
1544
1545static bool intel_tc_port_needs_reset(struct intel_tc_port *tc)
1546{
1547 return tc_phy_get_target_mode(tc) != tc->mode;
1548}
1549
1550static void intel_tc_port_update_mode(struct intel_tc_port *tc,
1551 int required_lanes, bool force_disconnect)
1552{
1553 if (force_disconnect ||
1554 intel_tc_port_needs_reset(tc))
1555 intel_tc_port_reset_mode(tc, required_lanes, force_disconnect);
1556}
1557
1558static void __intel_tc_port_get_link(struct intel_tc_port *tc)
1559{
1560 tc->link_refcount++;
1561}
1562
1563static void __intel_tc_port_put_link(struct intel_tc_port *tc)
1564{
1565 tc->link_refcount--;
1566}
1567
1568static bool tc_port_is_enabled(struct intel_tc_port *tc)
1569{
1570 struct intel_display *display = to_intel_display(tc->dig_port);
1571 struct intel_digital_port *dig_port = tc->dig_port;
1572
1573 assert_tc_port_power_enabled(tc);
1574
1575 return intel_de_read(display, DDI_BUF_CTL(dig_port->base.port)) &
1576 DDI_BUF_CTL_ENABLE;
1577}
1578
1579/**
1580 * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
1581 * @dig_port: digital port
1582 *
1583 * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
1584 * will be locked until intel_tc_port_sanitize_mode() is called.
1585 */
1586void intel_tc_port_init_mode(struct intel_digital_port *dig_port)
1587{
1588 struct intel_display *display = to_intel_display(dig_port);
1589 struct intel_tc_port *tc = to_tc_port(dig_port);
1590 bool update_mode = false;
1591
1592 mutex_lock(lock: &tc->lock);
1593
1594 drm_WARN_ON(display->drm, tc->mode != TC_PORT_DISCONNECTED);
1595 drm_WARN_ON(display->drm, tc->lock_wakeref);
1596 drm_WARN_ON(display->drm, tc->link_refcount);
1597
1598 tc_phy_get_hw_state(tc);
1599 /*
1600 * Save the initial mode for the state check in
1601 * intel_tc_port_sanitize_mode().
1602 */
1603 tc->init_mode = tc->mode;
1604
1605 /*
1606 * The PHY needs to be connected for AUX to work during HW readout and
1607 * MST topology resume, but the PHY mode can only be changed if the
1608 * port is disabled.
1609 *
1610 * An exception is the case where BIOS leaves the PHY incorrectly
1611 * disconnected on an enabled legacy port. Work around that by
1612 * connecting the PHY even though the port is enabled. This doesn't
1613 * cause a problem as the PHY ownership state is ignored by the
1614 * IOM/TCSS firmware (only display can own the PHY in that case).
1615 */
1616 if (!tc_port_is_enabled(tc)) {
1617 update_mode = true;
1618 } else if (tc->mode == TC_PORT_DISCONNECTED) {
1619 drm_WARN_ON(display->drm, !tc->legacy_port);
1620 drm_err(display->drm,
1621 "Port %s: PHY disconnected on enabled port, connecting it\n",
1622 tc->port_name);
1623 update_mode = true;
1624 }
1625
1626 if (update_mode)
1627 intel_tc_port_update_mode(tc, required_lanes: 1, force_disconnect: false);
1628
1629 /* Prevent changing tc->mode until intel_tc_port_sanitize_mode() is called. */
1630 __intel_tc_port_get_link(tc);
1631
1632 mutex_unlock(lock: &tc->lock);
1633}
1634
1635static bool tc_port_has_active_streams(struct intel_tc_port *tc,
1636 const struct intel_crtc_state *crtc_state)
1637{
1638 struct intel_display *display = to_intel_display(tc->dig_port);
1639 struct intel_digital_port *dig_port = tc->dig_port;
1640 enum icl_port_dpll_id pll_type = ICL_PORT_DPLL_DEFAULT;
1641 int active_streams = 0;
1642
1643 if (dig_port->dp.is_mst) {
1644 /* TODO: get the PLL type for MST, once HW readout is done for it. */
1645 active_streams = intel_dp_mst_active_streams(intel_dp: &dig_port->dp);
1646 } else if (crtc_state && crtc_state->hw.active) {
1647 pll_type = intel_ddi_port_pll_type(encoder: &dig_port->base, crtc_state);
1648 active_streams = 1;
1649 }
1650
1651 if (active_streams && !tc_phy_is_connected(tc, port_pll_type: pll_type))
1652 drm_err(display->drm,
1653 "Port %s: PHY disconnected with %d active stream(s)\n",
1654 tc->port_name, active_streams);
1655
1656 return active_streams;
1657}
1658
1659/**
1660 * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
1661 * @dig_port: digital port
1662 * @crtc_state: atomic state of CRTC connected to @dig_port
1663 *
1664 * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
1665 * loading and system resume:
1666 * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
1667 * the encoder is disabled.
1668 * If the encoder is disabled make sure the PHY is disconnected.
1669 * @crtc_state is valid if @dig_port is enabled, NULL otherwise.
1670 */
1671void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port,
1672 const struct intel_crtc_state *crtc_state)
1673{
1674 struct intel_display *display = to_intel_display(dig_port);
1675 struct intel_tc_port *tc = to_tc_port(dig_port);
1676
1677 mutex_lock(lock: &tc->lock);
1678
1679 drm_WARN_ON(display->drm, tc->link_refcount != 1);
1680 if (!tc_port_has_active_streams(tc, crtc_state)) {
1681 /*
1682 * TBT-alt is the default mode in any case the PHY ownership is not
1683 * held (regardless of the sink's connected live state), so
1684 * we'll just switch to disconnected mode from it here without
1685 * a note.
1686 */
1687 if (tc->init_mode != TC_PORT_TBT_ALT &&
1688 tc->init_mode != TC_PORT_DISCONNECTED)
1689 drm_dbg_kms(display->drm,
1690 "Port %s: PHY left in %s mode on disabled port, disconnecting it\n",
1691 tc->port_name,
1692 tc_port_mode_name(tc->init_mode));
1693 tc_phy_disconnect(tc);
1694 __intel_tc_port_put_link(tc);
1695 }
1696
1697 drm_dbg_kms(display->drm, "Port %s: sanitize mode (%s) pin assignment: %c max lanes: %d\n",
1698 tc->port_name,
1699 tc_port_mode_name(tc->mode),
1700 pin_assignment_name(tc->pin_assignment),
1701 tc->max_lane_count);
1702
1703 mutex_unlock(lock: &tc->lock);
1704}
1705
1706/*
1707 * The type-C ports are different because even when they are connected, they may
1708 * not be available/usable by the graphics driver: see the comment on
1709 * icl_tc_phy_connect(). So in our driver instead of adding the additional
1710 * concept of "usable" and make everything check for "connected and usable" we
1711 * define a port as "connected" when it is not only connected, but also when it
1712 * is usable by the rest of the driver. That maintains the old assumption that
1713 * connected ports are usable, and avoids exposing to the users objects they
1714 * can't really use.
1715 */
1716bool intel_tc_port_connected(struct intel_encoder *encoder)
1717{
1718 struct intel_display *display = to_intel_display(encoder);
1719 struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1720 struct intel_tc_port *tc = to_tc_port(dig_port);
1721 u32 mask = ~0;
1722
1723 drm_WARN_ON(display->drm, !intel_tc_port_ref_held(dig_port));
1724
1725 if (tc->mode != TC_PORT_DISCONNECTED)
1726 mask = BIT(tc->mode);
1727
1728 return tc_phy_hpd_live_status(tc) & mask;
1729}
1730
1731static bool __intel_tc_port_link_needs_reset(struct intel_tc_port *tc)
1732{
1733 bool ret;
1734
1735 mutex_lock(lock: &tc->lock);
1736
1737 ret = tc->link_refcount &&
1738 tc->mode == TC_PORT_DP_ALT &&
1739 intel_tc_port_needs_reset(tc);
1740
1741 mutex_unlock(lock: &tc->lock);
1742
1743 return ret;
1744}
1745
1746bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port)
1747{
1748 if (!intel_encoder_is_tc(encoder: &dig_port->base))
1749 return false;
1750
1751 return __intel_tc_port_link_needs_reset(tc: to_tc_port(dig_port));
1752}
1753
1754static int reset_link_commit(struct intel_tc_port *tc,
1755 struct intel_atomic_state *state,
1756 struct drm_modeset_acquire_ctx *ctx)
1757{
1758 struct intel_display *display = to_intel_display(tc->dig_port);
1759 struct intel_digital_port *dig_port = tc->dig_port;
1760 struct intel_dp *intel_dp = enc_to_intel_dp(encoder: &dig_port->base);
1761 struct intel_crtc *crtc;
1762 u8 pipe_mask;
1763 int ret;
1764
1765 ret = drm_modeset_lock(lock: &display->drm->mode_config.connection_mutex, ctx);
1766 if (ret)
1767 return ret;
1768
1769 ret = intel_dp_get_active_pipes(intel_dp, ctx, pipe_mask: &pipe_mask);
1770 if (ret)
1771 return ret;
1772
1773 if (!pipe_mask)
1774 return 0;
1775
1776 for_each_intel_crtc_in_pipe_mask(display->drm, crtc, pipe_mask) {
1777 struct intel_crtc_state *crtc_state;
1778
1779 crtc_state = intel_atomic_get_crtc_state(state: &state->base, crtc);
1780 if (IS_ERR(ptr: crtc_state))
1781 return PTR_ERR(ptr: crtc_state);
1782
1783 crtc_state->uapi.connectors_changed = true;
1784 }
1785
1786 if (!__intel_tc_port_link_needs_reset(tc))
1787 return 0;
1788
1789 return drm_atomic_commit(state: &state->base);
1790}
1791
1792static int reset_link(struct intel_tc_port *tc)
1793{
1794 struct intel_display *display = to_intel_display(tc->dig_port);
1795 struct drm_modeset_acquire_ctx ctx;
1796 struct drm_atomic_state *_state;
1797 struct intel_atomic_state *state;
1798 int ret;
1799
1800 _state = drm_atomic_state_alloc(dev: display->drm);
1801 if (!_state)
1802 return -ENOMEM;
1803
1804 state = to_intel_atomic_state(_state);
1805 state->internal = true;
1806
1807 intel_modeset_lock_ctx_retry(&ctx, state, 0, ret)
1808 ret = reset_link_commit(tc, state, ctx: &ctx);
1809
1810 drm_atomic_state_put(state: &state->base);
1811
1812 return ret;
1813}
1814
1815static void intel_tc_port_link_reset_work(struct work_struct *work)
1816{
1817 struct intel_tc_port *tc =
1818 container_of(work, struct intel_tc_port, link_reset_work.work);
1819 struct intel_display *display = to_intel_display(tc->dig_port);
1820 int ret;
1821
1822 if (!__intel_tc_port_link_needs_reset(tc))
1823 return;
1824
1825 mutex_lock(lock: &display->drm->mode_config.mutex);
1826
1827 drm_dbg_kms(display->drm,
1828 "Port %s: TypeC DP-alt sink disconnected, resetting link\n",
1829 tc->port_name);
1830 ret = reset_link(tc);
1831 drm_WARN_ON(display->drm, ret);
1832
1833 mutex_unlock(lock: &display->drm->mode_config.mutex);
1834}
1835
1836bool intel_tc_port_link_reset(struct intel_digital_port *dig_port)
1837{
1838 if (!intel_tc_port_link_needs_reset(dig_port))
1839 return false;
1840
1841 queue_delayed_work(wq: system_unbound_wq,
1842 dwork: &to_tc_port(dig_port)->link_reset_work,
1843 delay: msecs_to_jiffies(m: 2000));
1844
1845 return true;
1846}
1847
1848void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port)
1849{
1850 struct intel_tc_port *tc = to_tc_port(dig_port);
1851
1852 if (!intel_encoder_is_tc(encoder: &dig_port->base))
1853 return;
1854
1855 cancel_delayed_work(dwork: &tc->link_reset_work);
1856}
1857
1858static void __intel_tc_port_lock(struct intel_tc_port *tc,
1859 int required_lanes)
1860{
1861 struct intel_display *display = to_intel_display(tc->dig_port);
1862
1863 mutex_lock(lock: &tc->lock);
1864
1865 cancel_delayed_work(dwork: &tc->disconnect_phy_work);
1866
1867 if (!tc->link_refcount)
1868 intel_tc_port_update_mode(tc, required_lanes,
1869 force_disconnect: false);
1870
1871 drm_WARN_ON(display->drm, tc->mode == TC_PORT_DISCONNECTED);
1872 drm_WARN_ON(display->drm, tc->mode != TC_PORT_TBT_ALT && !tc_phy_is_owned(tc));
1873}
1874
1875void intel_tc_port_lock(struct intel_digital_port *dig_port)
1876{
1877 __intel_tc_port_lock(tc: to_tc_port(dig_port), required_lanes: 1);
1878}
1879
1880/*
1881 * Disconnect the given digital port from its TypeC PHY (handing back the
1882 * control of the PHY to the TypeC subsystem). This will happen in a delayed
1883 * manner after each aux transactions and modeset disables.
1884 */
1885static void intel_tc_port_disconnect_phy_work(struct work_struct *work)
1886{
1887 struct intel_tc_port *tc =
1888 container_of(work, struct intel_tc_port, disconnect_phy_work.work);
1889
1890 mutex_lock(lock: &tc->lock);
1891
1892 if (!tc->link_refcount)
1893 intel_tc_port_update_mode(tc, required_lanes: 1, force_disconnect: true);
1894
1895 mutex_unlock(lock: &tc->lock);
1896}
1897
1898/**
1899 * intel_tc_port_flush_work: flush the work disconnecting the PHY
1900 * @dig_port: digital port
1901 *
1902 * Flush the delayed work disconnecting an idle PHY.
1903 */
1904static void intel_tc_port_flush_work(struct intel_digital_port *dig_port)
1905{
1906 flush_delayed_work(dwork: &to_tc_port(dig_port)->disconnect_phy_work);
1907}
1908
1909void intel_tc_port_suspend(struct intel_digital_port *dig_port)
1910{
1911 struct intel_tc_port *tc = to_tc_port(dig_port);
1912
1913 cancel_delayed_work_sync(dwork: &tc->link_reset_work);
1914 intel_tc_port_flush_work(dig_port);
1915}
1916
1917void intel_tc_port_unlock(struct intel_digital_port *dig_port)
1918{
1919 struct intel_tc_port *tc = to_tc_port(dig_port);
1920
1921 if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED)
1922 queue_delayed_work(wq: system_unbound_wq, dwork: &tc->disconnect_phy_work,
1923 delay: msecs_to_jiffies(m: 1000));
1924
1925 mutex_unlock(lock: &tc->lock);
1926}
1927
1928bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
1929{
1930 struct intel_tc_port *tc = to_tc_port(dig_port);
1931
1932 return mutex_is_locked(lock: &tc->lock) ||
1933 tc->link_refcount;
1934}
1935
1936void intel_tc_port_get_link(struct intel_digital_port *dig_port,
1937 int required_lanes)
1938{
1939 struct intel_tc_port *tc = to_tc_port(dig_port);
1940
1941 __intel_tc_port_lock(tc, required_lanes);
1942 __intel_tc_port_get_link(tc);
1943 intel_tc_port_unlock(dig_port);
1944}
1945
1946void intel_tc_port_put_link(struct intel_digital_port *dig_port)
1947{
1948 struct intel_tc_port *tc = to_tc_port(dig_port);
1949
1950 intel_tc_port_lock(dig_port);
1951 __intel_tc_port_put_link(tc);
1952 intel_tc_port_unlock(dig_port);
1953
1954 /*
1955 * The firmware will not update the HPD status of other TypeC ports
1956 * that are active in DP-alt mode with their sink disconnected, until
1957 * this port is disabled and its PHY gets disconnected. Make sure this
1958 * happens in a timely manner by disconnecting the PHY synchronously.
1959 */
1960 intel_tc_port_flush_work(dig_port);
1961}
1962
1963int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
1964{
1965 struct intel_display *display = to_intel_display(dig_port);
1966 struct intel_tc_port *tc;
1967 enum port port = dig_port->base.port;
1968 enum tc_port tc_port = intel_encoder_to_tc(encoder: &dig_port->base);
1969
1970 if (drm_WARN_ON(display->drm, tc_port == TC_PORT_NONE))
1971 return -EINVAL;
1972
1973 tc = kzalloc(sizeof(*tc), GFP_KERNEL);
1974 if (!tc)
1975 return -ENOMEM;
1976
1977 dig_port->tc = tc;
1978 tc->dig_port = dig_port;
1979
1980 if (DISPLAY_VER(display) >= 14)
1981 tc->phy_ops = &xelpdp_tc_phy_ops;
1982 else if (DISPLAY_VER(display) >= 13)
1983 tc->phy_ops = &adlp_tc_phy_ops;
1984 else if (DISPLAY_VER(display) >= 12)
1985 tc->phy_ops = &tgl_tc_phy_ops;
1986 else
1987 tc->phy_ops = &icl_tc_phy_ops;
1988
1989 tc->port_name = kasprintf(GFP_KERNEL, fmt: "%c/TC#%d", port_name(port),
1990 tc_port + 1);
1991 if (!tc->port_name) {
1992 kfree(objp: tc);
1993 return -ENOMEM;
1994 }
1995
1996 mutex_init(&tc->lock);
1997 /* TODO: Combine the two works */
1998 INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work);
1999 INIT_DELAYED_WORK(&tc->link_reset_work, intel_tc_port_link_reset_work);
2000 tc->legacy_port = is_legacy;
2001 tc->mode = TC_PORT_DISCONNECTED;
2002 tc->link_refcount = 0;
2003
2004 tc_phy_init(tc);
2005
2006 intel_tc_port_init_mode(dig_port);
2007
2008 return 0;
2009}
2010
2011void intel_tc_port_cleanup(struct intel_digital_port *dig_port)
2012{
2013 intel_tc_port_suspend(dig_port);
2014
2015 kfree(objp: dig_port->tc->port_name);
2016 kfree(objp: dig_port->tc);
2017 dig_port->tc = NULL;
2018}
2019