8cae650d2880d3f29b881a150c4aa6179eca0a04
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / i915 / display / intel_tc.c
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2019 Intel Corporation
4  */
5
6 #include "i915_drv.h"
7 #include "i915_reg.h"
8 #include "intel_ddi.h"
9 #include "intel_de.h"
10 #include "intel_display.h"
11 #include "intel_display_power_map.h"
12 #include "intel_display_types.h"
13 #include "intel_dkl_phy_regs.h"
14 #include "intel_dp_mst.h"
15 #include "intel_mg_phy_regs.h"
16 #include "intel_tc.h"
17
18 enum tc_port_mode {
19         TC_PORT_DISCONNECTED,
20         TC_PORT_TBT_ALT,
21         TC_PORT_DP_ALT,
22         TC_PORT_LEGACY,
23 };
24
25 struct intel_tc_port;
26
27 struct intel_tc_phy_ops {
28         u32 (*hpd_live_status)(struct intel_tc_port *tc);
29         bool (*is_ready)(struct intel_tc_port *tc);
30         bool (*is_owned)(struct intel_tc_port *tc);
31         void (*get_hw_state)(struct intel_tc_port *tc);
32         bool (*connect)(struct intel_tc_port *tc, int required_lanes);
33         void (*disconnect)(struct intel_tc_port *tc);
34 };
35
36 struct intel_tc_port {
37         struct intel_digital_port *dig_port;
38
39         const struct intel_tc_phy_ops *phy_ops;
40
41         struct mutex lock;      /* protects the TypeC port mode */
42         intel_wakeref_t lock_wakeref;
43         enum intel_display_power_domain lock_power_domain;
44         struct delayed_work disconnect_phy_work;
45         int link_refcount;
46         bool legacy_port:1;
47         char port_name[8];
48         enum tc_port_mode mode;
49         enum tc_port_mode init_mode;
50         enum phy_fia phy_fia;
51         u8 phy_fia_idx;
52 };
53
54 static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc);
55 static bool tc_phy_is_ready(struct intel_tc_port *tc);
56 static bool tc_phy_take_ownership(struct intel_tc_port *tc, bool take);
57 static enum tc_port_mode tc_phy_get_current_mode(struct intel_tc_port *tc);
58
59 static const char *tc_port_mode_name(enum tc_port_mode mode)
60 {
61         static const char * const names[] = {
62                 [TC_PORT_DISCONNECTED] = "disconnected",
63                 [TC_PORT_TBT_ALT] = "tbt-alt",
64                 [TC_PORT_DP_ALT] = "dp-alt",
65                 [TC_PORT_LEGACY] = "legacy",
66         };
67
68         if (WARN_ON(mode >= ARRAY_SIZE(names)))
69                 mode = TC_PORT_DISCONNECTED;
70
71         return names[mode];
72 }
73
74 static struct intel_tc_port *to_tc_port(struct intel_digital_port *dig_port)
75 {
76         return dig_port->tc;
77 }
78
79 static struct drm_i915_private *tc_to_i915(struct intel_tc_port *tc)
80 {
81         return to_i915(tc->dig_port->base.base.dev);
82 }
83
84 static bool intel_tc_port_in_mode(struct intel_digital_port *dig_port,
85                                   enum tc_port_mode mode)
86 {
87         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
88         enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
89         struct intel_tc_port *tc = to_tc_port(dig_port);
90
91         return intel_phy_is_tc(i915, phy) && tc->mode == mode;
92 }
93
94 bool intel_tc_port_in_tbt_alt_mode(struct intel_digital_port *dig_port)
95 {
96         return intel_tc_port_in_mode(dig_port, TC_PORT_TBT_ALT);
97 }
98
99 bool intel_tc_port_in_dp_alt_mode(struct intel_digital_port *dig_port)
100 {
101         return intel_tc_port_in_mode(dig_port, TC_PORT_DP_ALT);
102 }
103
104 bool intel_tc_port_in_legacy_mode(struct intel_digital_port *dig_port)
105 {
106         return intel_tc_port_in_mode(dig_port, TC_PORT_LEGACY);
107 }
108
109 bool intel_tc_cold_requires_aux_pw(struct intel_digital_port *dig_port)
110 {
111         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
112         struct intel_tc_port *tc = to_tc_port(dig_port);
113
114         return (DISPLAY_VER(i915) == 11 && tc->legacy_port) ||
115                 IS_ALDERLAKE_P(i915);
116 }
117
118 static enum intel_display_power_domain
119 tc_cold_get_power_domain(struct intel_tc_port *tc, enum tc_port_mode mode)
120 {
121         struct drm_i915_private *i915 = tc_to_i915(tc);
122         struct intel_digital_port *dig_port = tc->dig_port;
123
124         if (mode == TC_PORT_TBT_ALT || !intel_tc_cold_requires_aux_pw(dig_port))
125                 return POWER_DOMAIN_TC_COLD_OFF;
126
127         return intel_display_power_legacy_aux_domain(i915, dig_port->aux_ch);
128 }
129
130 static intel_wakeref_t
131 tc_cold_block_in_mode(struct intel_tc_port *tc, enum tc_port_mode mode,
132                       enum intel_display_power_domain *domain)
133 {
134         struct drm_i915_private *i915 = tc_to_i915(tc);
135
136         *domain = tc_cold_get_power_domain(tc, mode);
137
138         return intel_display_power_get(i915, *domain);
139 }
140
141 static intel_wakeref_t
142 tc_cold_block(struct intel_tc_port *tc, enum intel_display_power_domain *domain)
143 {
144         return tc_cold_block_in_mode(tc, tc->mode, domain);
145 }
146
147 static void
148 tc_cold_unblock(struct intel_tc_port *tc, enum intel_display_power_domain domain,
149                 intel_wakeref_t wakeref)
150 {
151         struct drm_i915_private *i915 = tc_to_i915(tc);
152
153         /*
154          * wakeref == -1, means some error happened saving save_depot_stack but
155          * power should still be put down and 0 is a invalid save_depot_stack
156          * id so can be used to skip it for non TC legacy ports.
157          */
158         if (wakeref == 0)
159                 return;
160
161         intel_display_power_put(i915, domain, wakeref);
162 }
163
164 static void
165 assert_tc_cold_blocked(struct intel_tc_port *tc)
166 {
167         struct drm_i915_private *i915 = tc_to_i915(tc);
168         bool enabled;
169
170         enabled = intel_display_power_is_enabled(i915,
171                                                  tc_cold_get_power_domain(tc,
172                                                                           tc->mode));
173         drm_WARN_ON(&i915->drm, !enabled);
174 }
175
176 static enum intel_display_power_domain
177 tc_port_power_domain(struct intel_tc_port *tc)
178 {
179         struct drm_i915_private *i915 = tc_to_i915(tc);
180         enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port);
181
182         return POWER_DOMAIN_PORT_DDI_LANES_TC1 + tc_port - TC_PORT_1;
183 }
184
185 static void
186 assert_tc_port_power_enabled(struct intel_tc_port *tc)
187 {
188         struct drm_i915_private *i915 = tc_to_i915(tc);
189
190         drm_WARN_ON(&i915->drm,
191                     !intel_display_power_is_enabled(i915, tc_port_power_domain(tc)));
192 }
193
194 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
195 {
196         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
197         struct intel_tc_port *tc = to_tc_port(dig_port);
198         u32 lane_mask;
199
200         lane_mask = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia));
201
202         drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff);
203         assert_tc_cold_blocked(tc);
204
205         lane_mask &= DP_LANE_ASSIGNMENT_MASK(tc->phy_fia_idx);
206         return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
207 }
208
209 u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
210 {
211         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
212         struct intel_tc_port *tc = to_tc_port(dig_port);
213         u32 pin_mask;
214
215         pin_mask = intel_de_read(i915, PORT_TX_DFLEXPA1(tc->phy_fia));
216
217         drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff);
218         assert_tc_cold_blocked(tc);
219
220         return (pin_mask & DP_PIN_ASSIGNMENT_MASK(tc->phy_fia_idx)) >>
221                DP_PIN_ASSIGNMENT_SHIFT(tc->phy_fia_idx);
222 }
223
224 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
225 {
226         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
227         struct intel_tc_port *tc = to_tc_port(dig_port);
228         enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
229         intel_wakeref_t wakeref;
230         u32 lane_mask;
231
232         if (!intel_phy_is_tc(i915, phy) || tc->mode != TC_PORT_DP_ALT)
233                 return 4;
234
235         assert_tc_cold_blocked(tc);
236
237         lane_mask = 0;
238         with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
239                 lane_mask = intel_tc_port_get_lane_mask(dig_port);
240
241         switch (lane_mask) {
242         default:
243                 MISSING_CASE(lane_mask);
244                 fallthrough;
245         case 0x1:
246         case 0x2:
247         case 0x4:
248         case 0x8:
249                 return 1;
250         case 0x3:
251         case 0xc:
252                 return 2;
253         case 0xf:
254                 return 4;
255         }
256 }
257
258 void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
259                                       int required_lanes)
260 {
261         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
262         struct intel_tc_port *tc = to_tc_port(dig_port);
263         bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
264         u32 val;
265
266         drm_WARN_ON(&i915->drm,
267                     lane_reversal && tc->mode != TC_PORT_LEGACY);
268
269         assert_tc_cold_blocked(tc);
270
271         val = intel_de_read(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia));
272         val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc->phy_fia_idx);
273
274         switch (required_lanes) {
275         case 1:
276                 val |= lane_reversal ?
277                         DFLEXDPMLE1_DPMLETC_ML3(tc->phy_fia_idx) :
278                         DFLEXDPMLE1_DPMLETC_ML0(tc->phy_fia_idx);
279                 break;
280         case 2:
281                 val |= lane_reversal ?
282                         DFLEXDPMLE1_DPMLETC_ML3_2(tc->phy_fia_idx) :
283                         DFLEXDPMLE1_DPMLETC_ML1_0(tc->phy_fia_idx);
284                 break;
285         case 4:
286                 val |= DFLEXDPMLE1_DPMLETC_ML3_0(tc->phy_fia_idx);
287                 break;
288         default:
289                 MISSING_CASE(required_lanes);
290         }
291
292         intel_de_write(i915, PORT_TX_DFLEXDPMLE1(tc->phy_fia), val);
293 }
294
295 static void tc_port_fixup_legacy_flag(struct intel_tc_port *tc,
296                                       u32 live_status_mask)
297 {
298         struct drm_i915_private *i915 = tc_to_i915(tc);
299         u32 valid_hpd_mask;
300
301         drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED);
302
303         if (hweight32(live_status_mask) != 1)
304                 return;
305
306         if (tc->legacy_port)
307                 valid_hpd_mask = BIT(TC_PORT_LEGACY);
308         else
309                 valid_hpd_mask = BIT(TC_PORT_DP_ALT) |
310                                  BIT(TC_PORT_TBT_ALT);
311
312         if (!(live_status_mask & ~valid_hpd_mask))
313                 return;
314
315         /* If live status mismatches the VBT flag, trust the live status. */
316         drm_dbg_kms(&i915->drm,
317                     "Port %s: live status %08x mismatches the legacy port flag %08x, fixing flag\n",
318                     tc->port_name, live_status_mask, valid_hpd_mask);
319
320         tc->legacy_port = !tc->legacy_port;
321 }
322
323 /*
324  * ICL TC PHY handlers
325  * -------------------
326  */
327 static u32 icl_tc_phy_hpd_live_status(struct intel_tc_port *tc)
328 {
329         struct drm_i915_private *i915 = tc_to_i915(tc);
330         struct intel_digital_port *dig_port = tc->dig_port;
331         u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin];
332         u32 mask = 0;
333         u32 val;
334
335         val = intel_de_read(i915, PORT_TX_DFLEXDPSP(tc->phy_fia));
336
337         if (val == 0xffffffff) {
338                 drm_dbg_kms(&i915->drm,
339                             "Port %s: PHY in TCCOLD, nothing connected\n",
340                             tc->port_name);
341                 return mask;
342         }
343
344         if (val & TC_LIVE_STATE_TBT(tc->phy_fia_idx))
345                 mask |= BIT(TC_PORT_TBT_ALT);
346         if (val & TC_LIVE_STATE_TC(tc->phy_fia_idx))
347                 mask |= BIT(TC_PORT_DP_ALT);
348
349         if (intel_de_read(i915, SDEISR) & isr_bit)
350                 mask |= BIT(TC_PORT_LEGACY);
351
352         return mask;
353 }
354
355 /*
356  * Return the PHY status complete flag indicating that display can acquire the
357  * PHY ownership. The IOM firmware sets this flag when a DP-alt or legacy sink
358  * is connected and it's ready to switch the ownership to display. The flag
359  * will be left cleared when a TBT-alt sink is connected, where the PHY is
360  * owned by the TBT subsystem and so switching the ownership to display is not
361  * required.
362  */
363 static bool icl_tc_phy_is_ready(struct intel_tc_port *tc)
364 {
365         struct drm_i915_private *i915 = tc_to_i915(tc);
366         u32 val;
367
368         val = intel_de_read(i915, PORT_TX_DFLEXDPPMS(tc->phy_fia));
369         if (val == 0xffffffff) {
370                 drm_dbg_kms(&i915->drm,
371                             "Port %s: PHY in TCCOLD, assuming not ready\n",
372                             tc->port_name);
373                 return false;
374         }
375
376         return val & DP_PHY_MODE_STATUS_COMPLETED(tc->phy_fia_idx);
377 }
378
379 static bool icl_tc_phy_take_ownership(struct intel_tc_port *tc,
380                                       bool take)
381 {
382         struct drm_i915_private *i915 = tc_to_i915(tc);
383         u32 val;
384
385         val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia));
386         if (val == 0xffffffff) {
387                 drm_dbg_kms(&i915->drm,
388                             "Port %s: PHY in TCCOLD, can't %s ownership\n",
389                             tc->port_name, take ? "take" : "release");
390
391                 return false;
392         }
393
394         val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx);
395         if (take)
396                 val |= DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx);
397
398         intel_de_write(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia), val);
399
400         return true;
401 }
402
403 static bool icl_tc_phy_is_owned(struct intel_tc_port *tc)
404 {
405         struct drm_i915_private *i915 = tc_to_i915(tc);
406         u32 val;
407
408         val = intel_de_read(i915, PORT_TX_DFLEXDPCSSS(tc->phy_fia));
409         if (val == 0xffffffff) {
410                 drm_dbg_kms(&i915->drm,
411                             "Port %s: PHY in TCCOLD, assume not owned\n",
412                             tc->port_name);
413                 return false;
414         }
415
416         return val & DP_PHY_MODE_STATUS_NOT_SAFE(tc->phy_fia_idx);
417 }
418
419 static void icl_tc_phy_get_hw_state(struct intel_tc_port *tc)
420 {
421         enum intel_display_power_domain domain;
422         intel_wakeref_t tc_cold_wref;
423
424         tc_cold_wref = tc_cold_block(tc, &domain);
425
426         tc->mode = tc_phy_get_current_mode(tc);
427         if (tc->mode != TC_PORT_DISCONNECTED)
428                 tc->lock_wakeref = tc_cold_block(tc, &tc->lock_power_domain);
429
430         tc_cold_unblock(tc, domain, tc_cold_wref);
431 }
432
433 /*
434  * This function implements the first part of the Connect Flow described by our
435  * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
436  * lanes, EDID, etc) is done as needed in the typical places.
437  *
438  * Unlike the other ports, type-C ports are not available to use as soon as we
439  * get a hotplug. The type-C PHYs can be shared between multiple controllers:
440  * display, USB, etc. As a result, handshaking through FIA is required around
441  * connect and disconnect to cleanly transfer ownership with the controller and
442  * set the type-C power state.
443  */
444 static bool tc_phy_verify_legacy_or_dp_alt_mode(struct intel_tc_port *tc,
445                                                 int required_lanes)
446 {
447         struct drm_i915_private *i915 = tc_to_i915(tc);
448         struct intel_digital_port *dig_port = tc->dig_port;
449         int max_lanes;
450
451         max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
452         if (tc->mode == TC_PORT_LEGACY) {
453                 drm_WARN_ON(&i915->drm, max_lanes != 4);
454                 return true;
455         }
456
457         drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DP_ALT);
458
459         /*
460          * Now we have to re-check the live state, in case the port recently
461          * became disconnected. Not necessary for legacy mode.
462          */
463         if (!(tc_phy_hpd_live_status(tc) & BIT(TC_PORT_DP_ALT))) {
464                 drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n",
465                             tc->port_name);
466                 return false;
467         }
468
469         if (max_lanes < required_lanes) {
470                 drm_dbg_kms(&i915->drm,
471                             "Port %s: PHY max lanes %d < required lanes %d\n",
472                             tc->port_name,
473                             max_lanes, required_lanes);
474                 return false;
475         }
476
477         return true;
478 }
479
480 static bool icl_tc_phy_connect(struct intel_tc_port *tc,
481                                int required_lanes)
482 {
483         struct drm_i915_private *i915 = tc_to_i915(tc);
484
485         if (tc->mode == TC_PORT_TBT_ALT)
486                 return true;
487
488         if ((!tc_phy_is_ready(tc) ||
489              !tc_phy_take_ownership(tc, true)) &&
490             !drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_LEGACY)) {
491                 drm_dbg_kms(&i915->drm, "Port %s: can't take PHY ownership (ready %s)\n",
492                             tc->port_name,
493                             str_yes_no(tc_phy_is_ready(tc)));
494                 return false;
495         }
496
497
498         if (!tc_phy_verify_legacy_or_dp_alt_mode(tc, required_lanes))
499                 goto out_release_phy;
500
501         return true;
502
503 out_release_phy:
504         tc_phy_take_ownership(tc, false);
505
506         return false;
507 }
508
509 /*
510  * See the comment at the connect function. This implements the Disconnect
511  * Flow.
512  */
513 static void icl_tc_phy_disconnect(struct intel_tc_port *tc)
514 {
515         switch (tc->mode) {
516         case TC_PORT_LEGACY:
517         case TC_PORT_DP_ALT:
518                 tc_phy_take_ownership(tc, false);
519                 fallthrough;
520         case TC_PORT_TBT_ALT:
521                 break;
522         default:
523                 MISSING_CASE(tc->mode);
524         }
525 }
526
527 static const struct intel_tc_phy_ops icl_tc_phy_ops = {
528         .hpd_live_status = icl_tc_phy_hpd_live_status,
529         .is_ready = icl_tc_phy_is_ready,
530         .is_owned = icl_tc_phy_is_owned,
531         .get_hw_state = icl_tc_phy_get_hw_state,
532         .connect = icl_tc_phy_connect,
533         .disconnect = icl_tc_phy_disconnect,
534 };
535
536 /*
537  * ADLP TC PHY handlers
538  * --------------------
539  */
540 static u32 adlp_tc_phy_hpd_live_status(struct intel_tc_port *tc)
541 {
542         struct drm_i915_private *i915 = tc_to_i915(tc);
543         struct intel_digital_port *dig_port = tc->dig_port;
544         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
545         u32 isr_bit = i915->display.hotplug.pch_hpd[dig_port->base.hpd_pin];
546         u32 val, mask = 0;
547
548         /*
549          * On ADL-P HW/FW will wake from TCCOLD to complete the read access of
550          * registers in IOM. Note that this doesn't apply to PHY and FIA
551          * registers.
552          */
553         val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port));
554         if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_ALT)
555                 mask |= BIT(TC_PORT_DP_ALT);
556         if (val & TCSS_DDI_STATUS_HPD_LIVE_STATUS_TBT)
557                 mask |= BIT(TC_PORT_TBT_ALT);
558
559         if (intel_de_read(i915, SDEISR) & isr_bit)
560                 mask |= BIT(TC_PORT_LEGACY);
561
562         return mask;
563 }
564
565 /*
566  * Return the PHY status complete flag indicating that display can acquire the
567  * PHY ownership. The IOM firmware sets this flag when it's ready to switch
568  * the ownership to display, regardless of what sink is connected (TBT-alt,
569  * DP-alt, legacy or nothing). For TBT-alt sinks the PHY is owned by the TBT
570  * subsystem and so switching the ownership to display is not required.
571  */
572 static bool adlp_tc_phy_is_ready(struct intel_tc_port *tc)
573 {
574         struct drm_i915_private *i915 = tc_to_i915(tc);
575         enum tc_port tc_port = intel_port_to_tc(i915, tc->dig_port->base.port);
576         u32 val;
577
578         val = intel_de_read(i915, TCSS_DDI_STATUS(tc_port));
579         if (val == 0xffffffff) {
580                 drm_dbg_kms(&i915->drm,
581                             "Port %s: PHY in TCCOLD, assuming not ready\n",
582                             tc->port_name);
583                 return false;
584         }
585
586         return val & TCSS_DDI_STATUS_READY;
587 }
588
589 static bool adlp_tc_phy_take_ownership(struct intel_tc_port *tc,
590                                        bool take)
591 {
592         struct drm_i915_private *i915 = tc_to_i915(tc);
593         enum port port = tc->dig_port->base.port;
594
595         intel_de_rmw(i915, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP,
596                      take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0);
597
598         return true;
599 }
600
601 static bool adlp_tc_phy_is_owned(struct intel_tc_port *tc)
602 {
603         struct drm_i915_private *i915 = tc_to_i915(tc);
604         enum port port = tc->dig_port->base.port;
605         u32 val;
606
607         val = intel_de_read(i915, DDI_BUF_CTL(port));
608         return val & DDI_BUF_CTL_TC_PHY_OWNERSHIP;
609 }
610
611 static const struct intel_tc_phy_ops adlp_tc_phy_ops = {
612         .hpd_live_status = adlp_tc_phy_hpd_live_status,
613         .is_ready = adlp_tc_phy_is_ready,
614         .is_owned = adlp_tc_phy_is_owned,
615         .get_hw_state = icl_tc_phy_get_hw_state,
616         .connect = icl_tc_phy_connect,
617         .disconnect = icl_tc_phy_disconnect,
618 };
619
620 /*
621  * Generic TC PHY handlers
622  * -----------------------
623  */
624 static u32 tc_phy_hpd_live_status(struct intel_tc_port *tc)
625 {
626         struct drm_i915_private *i915 = tc_to_i915(tc);
627         u32 mask;
628
629         mask = tc->phy_ops->hpd_live_status(tc);
630
631         /* The sink can be connected only in a single mode. */
632         drm_WARN_ON_ONCE(&i915->drm, hweight32(mask) > 1);
633
634         return mask;
635 }
636
637 static bool tc_phy_is_ready(struct intel_tc_port *tc)
638 {
639         return tc->phy_ops->is_ready(tc);
640 }
641
642 static bool tc_phy_is_owned(struct intel_tc_port *tc)
643 {
644         return tc->phy_ops->is_owned(tc);
645 }
646
647 static void tc_phy_get_hw_state(struct intel_tc_port *tc)
648 {
649         tc->phy_ops->get_hw_state(tc);
650 }
651
652 static bool tc_phy_take_ownership(struct intel_tc_port *tc, bool take)
653 {
654         struct drm_i915_private *i915 = tc_to_i915(tc);
655
656         if (IS_ALDERLAKE_P(i915))
657                 return adlp_tc_phy_take_ownership(tc, take);
658
659         return icl_tc_phy_take_ownership(tc, take);
660 }
661
662 static bool tc_phy_is_ready_and_owned(struct intel_tc_port *tc,
663                                       bool phy_is_ready, bool phy_is_owned)
664 {
665         struct drm_i915_private *i915 = tc_to_i915(tc);
666
667         drm_WARN_ON(&i915->drm, phy_is_owned && !phy_is_ready);
668
669         return phy_is_ready && phy_is_owned;
670 }
671
672 static bool tc_phy_is_connected(struct intel_tc_port *tc,
673                                 enum icl_port_dpll_id port_pll_type)
674 {
675         struct intel_encoder *encoder = &tc->dig_port->base;
676         struct drm_i915_private *i915 = to_i915(encoder->base.dev);
677         bool phy_is_ready = tc_phy_is_ready(tc);
678         bool phy_is_owned = tc_phy_is_owned(tc);
679         bool is_connected;
680
681         if (tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned))
682                 is_connected = port_pll_type == ICL_PORT_DPLL_MG_PHY;
683         else
684                 is_connected = port_pll_type == ICL_PORT_DPLL_DEFAULT;
685
686         drm_dbg_kms(&i915->drm,
687                     "Port %s: PHY connected: %s (ready: %s, owned: %s, pll_type: %s)\n",
688                     tc->port_name,
689                     str_yes_no(is_connected),
690                     str_yes_no(phy_is_ready),
691                     str_yes_no(phy_is_owned),
692                     port_pll_type == ICL_PORT_DPLL_DEFAULT ? "tbt" : "non-tbt");
693
694         return is_connected;
695 }
696
697 static void tc_phy_wait_for_ready(struct intel_tc_port *tc)
698 {
699         struct drm_i915_private *i915 = tc_to_i915(tc);
700
701         if (wait_for(tc_phy_is_ready(tc), 100))
702                 drm_err(&i915->drm, "Port %s: timeout waiting for PHY ready\n",
703                         tc->port_name);
704 }
705
706 static enum tc_port_mode
707 hpd_mask_to_tc_mode(u32 live_status_mask)
708 {
709         if (live_status_mask)
710                 return fls(live_status_mask) - 1;
711
712         return TC_PORT_DISCONNECTED;
713 }
714
715 static enum tc_port_mode
716 tc_phy_hpd_live_mode(struct intel_tc_port *tc)
717 {
718         u32 live_status_mask = tc_phy_hpd_live_status(tc);
719
720         return hpd_mask_to_tc_mode(live_status_mask);
721 }
722
723 static enum tc_port_mode
724 get_tc_mode_in_phy_owned_state(struct intel_tc_port *tc,
725                                enum tc_port_mode live_mode)
726 {
727         switch (live_mode) {
728         case TC_PORT_LEGACY:
729         case TC_PORT_DP_ALT:
730                 return live_mode;
731         default:
732                 MISSING_CASE(live_mode);
733                 fallthrough;
734         case TC_PORT_TBT_ALT:
735         case TC_PORT_DISCONNECTED:
736                 if (tc->legacy_port)
737                         return TC_PORT_LEGACY;
738                 else
739                         return TC_PORT_DP_ALT;
740         }
741 }
742
743 static enum tc_port_mode
744 get_tc_mode_in_phy_not_owned_state(struct intel_tc_port *tc,
745                                    enum tc_port_mode live_mode)
746 {
747         switch (live_mode) {
748         case TC_PORT_LEGACY:
749                 return TC_PORT_DISCONNECTED;
750         case TC_PORT_DP_ALT:
751         case TC_PORT_TBT_ALT:
752                 return TC_PORT_TBT_ALT;
753         default:
754                 MISSING_CASE(live_mode);
755                 fallthrough;
756         case TC_PORT_DISCONNECTED:
757                 if (tc->legacy_port)
758                         return TC_PORT_DISCONNECTED;
759                 else
760                         return TC_PORT_TBT_ALT;
761         }
762 }
763
764 static enum tc_port_mode
765 tc_phy_get_current_mode(struct intel_tc_port *tc)
766 {
767         struct drm_i915_private *i915 = tc_to_i915(tc);
768         enum tc_port_mode live_mode = tc_phy_hpd_live_mode(tc);
769         bool phy_is_ready;
770         bool phy_is_owned;
771         enum tc_port_mode mode;
772
773         /*
774          * For legacy ports the IOM firmware initializes the PHY during boot-up
775          * and system resume whether or not a sink is connected. Wait here for
776          * the initialization to get ready.
777          */
778         if (tc->legacy_port)
779                 tc_phy_wait_for_ready(tc);
780
781         phy_is_ready = tc_phy_is_ready(tc);
782         phy_is_owned = tc_phy_is_owned(tc);
783
784         if (!tc_phy_is_ready_and_owned(tc, phy_is_ready, phy_is_owned)) {
785                 mode = get_tc_mode_in_phy_not_owned_state(tc, live_mode);
786         } else {
787                 drm_WARN_ON(&i915->drm, live_mode == TC_PORT_TBT_ALT);
788                 mode = get_tc_mode_in_phy_owned_state(tc, live_mode);
789         }
790
791         drm_dbg_kms(&i915->drm,
792                     "Port %s: PHY mode: %s (ready: %s, owned: %s, HPD: %s)\n",
793                     tc->port_name,
794                     tc_port_mode_name(mode),
795                     str_yes_no(phy_is_ready),
796                     str_yes_no(phy_is_owned),
797                     tc_port_mode_name(live_mode));
798
799         return mode;
800 }
801
802 static enum tc_port_mode default_tc_mode(struct intel_tc_port *tc)
803 {
804         if (tc->legacy_port)
805                 return TC_PORT_LEGACY;
806
807         return TC_PORT_TBT_ALT;
808 }
809
810 static enum tc_port_mode
811 hpd_mask_to_target_mode(struct intel_tc_port *tc, u32 live_status_mask)
812 {
813         enum tc_port_mode mode = hpd_mask_to_tc_mode(live_status_mask);
814
815         if (mode != TC_PORT_DISCONNECTED)
816                 return mode;
817
818         return default_tc_mode(tc);
819 }
820
821 static enum tc_port_mode
822 tc_phy_get_target_mode(struct intel_tc_port *tc)
823 {
824         u32 live_status_mask = tc_phy_hpd_live_status(tc);
825
826         return hpd_mask_to_target_mode(tc, live_status_mask);
827 }
828
829 static void tc_phy_connect(struct intel_tc_port *tc, int required_lanes)
830 {
831         struct drm_i915_private *i915 = tc_to_i915(tc);
832         u32 live_status_mask = tc_phy_hpd_live_status(tc);
833         bool connected;
834
835         tc_port_fixup_legacy_flag(tc, live_status_mask);
836
837         tc->mode = hpd_mask_to_target_mode(tc, live_status_mask);
838
839         connected = tc->phy_ops->connect(tc, required_lanes);
840         if (!connected && tc->mode != default_tc_mode(tc)) {
841                 tc->mode = default_tc_mode(tc);
842                 connected = tc->phy_ops->connect(tc, required_lanes);
843         }
844
845         drm_WARN_ON(&i915->drm, !connected);
846 }
847
848 static void tc_phy_disconnect(struct intel_tc_port *tc)
849 {
850         if (tc->mode != TC_PORT_DISCONNECTED) {
851                 tc->phy_ops->disconnect(tc);
852                 tc->mode = TC_PORT_DISCONNECTED;
853         }
854 }
855
856 static void intel_tc_port_reset_mode(struct intel_tc_port *tc,
857                                      int required_lanes, bool force_disconnect)
858 {
859         struct drm_i915_private *i915 = tc_to_i915(tc);
860         struct intel_digital_port *dig_port = tc->dig_port;
861         enum tc_port_mode old_tc_mode = tc->mode;
862
863         intel_display_power_flush_work(i915);
864         if (!intel_tc_cold_requires_aux_pw(dig_port)) {
865                 enum intel_display_power_domain aux_domain;
866                 bool aux_powered;
867
868                 aux_domain = intel_aux_power_domain(dig_port);
869                 aux_powered = intel_display_power_is_enabled(i915, aux_domain);
870                 drm_WARN_ON(&i915->drm, aux_powered);
871         }
872
873         tc_phy_disconnect(tc);
874         if (!force_disconnect)
875                 tc_phy_connect(tc, required_lanes);
876
877         drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n",
878                     tc->port_name,
879                     tc_port_mode_name(old_tc_mode),
880                     tc_port_mode_name(tc->mode));
881 }
882
883 static bool intel_tc_port_needs_reset(struct intel_tc_port *tc)
884 {
885         return tc_phy_get_target_mode(tc) != tc->mode;
886 }
887
888 static void intel_tc_port_update_mode(struct intel_tc_port *tc,
889                                       int required_lanes, bool force_disconnect)
890 {
891         enum intel_display_power_domain domain;
892         intel_wakeref_t wref;
893         bool needs_reset = force_disconnect;
894
895         if (!needs_reset) {
896                 /* Get power domain required to check the hotplug live status. */
897                 wref = tc_cold_block(tc, &domain);
898                 needs_reset = intel_tc_port_needs_reset(tc);
899                 tc_cold_unblock(tc, domain, wref);
900         }
901
902         if (!needs_reset)
903                 return;
904
905         /* Get power domain required for resetting the mode. */
906         wref = tc_cold_block_in_mode(tc, TC_PORT_DISCONNECTED, &domain);
907
908         intel_tc_port_reset_mode(tc, required_lanes, force_disconnect);
909
910         /* Get power domain matching the new mode after reset. */
911         tc_cold_unblock(tc, tc->lock_power_domain,
912                         fetch_and_zero(&tc->lock_wakeref));
913         if (tc->mode != TC_PORT_DISCONNECTED)
914                 tc->lock_wakeref = tc_cold_block(tc, &tc->lock_power_domain);
915
916         tc_cold_unblock(tc, domain, wref);
917 }
918
919 static void __intel_tc_port_get_link(struct intel_tc_port *tc)
920 {
921         tc->link_refcount++;
922 }
923
924 static void __intel_tc_port_put_link(struct intel_tc_port *tc)
925 {
926         tc->link_refcount--;
927 }
928
929 static bool tc_port_is_enabled(struct intel_tc_port *tc)
930 {
931         struct drm_i915_private *i915 = tc_to_i915(tc);
932         struct intel_digital_port *dig_port = tc->dig_port;
933
934         assert_tc_port_power_enabled(tc);
935
936         return intel_de_read(i915, DDI_BUF_CTL(dig_port->base.port)) &
937                DDI_BUF_CTL_ENABLE;
938 }
939
940 /**
941  * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
942  * @dig_port: digital port
943  *
944  * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
945  * will be locked until intel_tc_port_sanitize_mode() is called.
946  */
947 void intel_tc_port_init_mode(struct intel_digital_port *dig_port)
948 {
949         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
950         struct intel_tc_port *tc = to_tc_port(dig_port);
951         bool update_mode = false;
952
953         mutex_lock(&tc->lock);
954
955         drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_DISCONNECTED);
956         drm_WARN_ON(&i915->drm, tc->lock_wakeref);
957         drm_WARN_ON(&i915->drm, tc->link_refcount);
958
959         tc_phy_get_hw_state(tc);
960         /*
961          * Save the initial mode for the state check in
962          * intel_tc_port_sanitize_mode().
963          */
964         tc->init_mode = tc->mode;
965
966         /*
967          * The PHY needs to be connected for AUX to work during HW readout and
968          * MST topology resume, but the PHY mode can only be changed if the
969          * port is disabled.
970          *
971          * An exception is the case where BIOS leaves the PHY incorrectly
972          * disconnected on an enabled legacy port. Work around that by
973          * connecting the PHY even though the port is enabled. This doesn't
974          * cause a problem as the PHY ownership state is ignored by the
975          * IOM/TCSS firmware (only display can own the PHY in that case).
976          */
977         if (!tc_port_is_enabled(tc)) {
978                 update_mode = true;
979         } else if (tc->mode == TC_PORT_DISCONNECTED) {
980                 drm_WARN_ON(&i915->drm, !tc->legacy_port);
981                 drm_err(&i915->drm,
982                         "Port %s: PHY disconnected on enabled port, connecting it\n",
983                         tc->port_name);
984                 update_mode = true;
985         }
986
987         if (update_mode)
988                 intel_tc_port_update_mode(tc, 1, false);
989
990         /* Prevent changing tc->mode until intel_tc_port_sanitize_mode() is called. */
991         __intel_tc_port_get_link(tc);
992
993         mutex_unlock(&tc->lock);
994 }
995
996 static bool tc_port_has_active_links(struct intel_tc_port *tc,
997                                      const struct intel_crtc_state *crtc_state)
998 {
999         struct drm_i915_private *i915 = tc_to_i915(tc);
1000         struct intel_digital_port *dig_port = tc->dig_port;
1001         enum icl_port_dpll_id pll_type = ICL_PORT_DPLL_DEFAULT;
1002         int active_links = 0;
1003
1004         if (dig_port->dp.is_mst) {
1005                 /* TODO: get the PLL type for MST, once HW readout is done for it. */
1006                 active_links = intel_dp_mst_encoder_active_links(dig_port);
1007         } else if (crtc_state && crtc_state->hw.active) {
1008                 pll_type = intel_ddi_port_pll_type(&dig_port->base, crtc_state);
1009                 active_links = 1;
1010         }
1011
1012         if (active_links && !tc_phy_is_connected(tc, pll_type))
1013                 drm_err(&i915->drm,
1014                         "Port %s: PHY disconnected with %d active link(s)\n",
1015                         tc->port_name, active_links);
1016
1017         return active_links;
1018 }
1019
1020 /**
1021  * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
1022  * @dig_port: digital port
1023  * @crtc_state: atomic state of CRTC connected to @dig_port
1024  *
1025  * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
1026  * loading and system resume:
1027  * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
1028  * the encoder is disabled.
1029  * If the encoder is disabled make sure the PHY is disconnected.
1030  * @crtc_state is valid if @dig_port is enabled, NULL otherwise.
1031  */
1032 void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port,
1033                                  const struct intel_crtc_state *crtc_state)
1034 {
1035         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
1036         struct intel_tc_port *tc = to_tc_port(dig_port);
1037
1038         mutex_lock(&tc->lock);
1039
1040         drm_WARN_ON(&i915->drm, tc->link_refcount != 1);
1041         if (!tc_port_has_active_links(tc, crtc_state)) {
1042                 /*
1043                  * TBT-alt is the default mode in any case the PHY ownership is not
1044                  * held (regardless of the sink's connected live state), so
1045                  * we'll just switch to disconnected mode from it here without
1046                  * a note.
1047                  */
1048                 if (tc->init_mode != TC_PORT_TBT_ALT &&
1049                     tc->init_mode != TC_PORT_DISCONNECTED)
1050                         drm_dbg_kms(&i915->drm,
1051                                     "Port %s: PHY left in %s mode on disabled port, disconnecting it\n",
1052                                     tc->port_name,
1053                                     tc_port_mode_name(tc->init_mode));
1054                 tc_phy_disconnect(tc);
1055                 __intel_tc_port_put_link(tc);
1056
1057                 tc_cold_unblock(tc, tc->lock_power_domain,
1058                                 fetch_and_zero(&tc->lock_wakeref));
1059         }
1060
1061         drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n",
1062                     tc->port_name,
1063                     tc_port_mode_name(tc->mode));
1064
1065         mutex_unlock(&tc->lock);
1066 }
1067
1068 /*
1069  * The type-C ports are different because even when they are connected, they may
1070  * not be available/usable by the graphics driver: see the comment on
1071  * icl_tc_phy_connect(). So in our driver instead of adding the additional
1072  * concept of "usable" and make everything check for "connected and usable" we
1073  * define a port as "connected" when it is not only connected, but also when it
1074  * is usable by the rest of the driver. That maintains the old assumption that
1075  * connected ports are usable, and avoids exposing to the users objects they
1076  * can't really use.
1077  */
1078 bool intel_tc_port_connected_locked(struct intel_encoder *encoder)
1079 {
1080         struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1081         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
1082         struct intel_tc_port *tc = to_tc_port(dig_port);
1083
1084         drm_WARN_ON(&i915->drm, !intel_tc_port_ref_held(dig_port));
1085
1086         return tc_phy_hpd_live_status(tc) & BIT(tc->mode);
1087 }
1088
1089 bool intel_tc_port_connected(struct intel_encoder *encoder)
1090 {
1091         struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1092         bool is_connected;
1093
1094         intel_tc_port_lock(dig_port);
1095         is_connected = intel_tc_port_connected_locked(encoder);
1096         intel_tc_port_unlock(dig_port);
1097
1098         return is_connected;
1099 }
1100
1101 static void __intel_tc_port_lock(struct intel_tc_port *tc,
1102                                  int required_lanes)
1103 {
1104         struct drm_i915_private *i915 = tc_to_i915(tc);
1105
1106         mutex_lock(&tc->lock);
1107
1108         cancel_delayed_work(&tc->disconnect_phy_work);
1109
1110         if (!tc->link_refcount)
1111                 intel_tc_port_update_mode(tc, required_lanes,
1112                                           false);
1113
1114         drm_WARN_ON(&i915->drm, tc->mode == TC_PORT_DISCONNECTED);
1115         drm_WARN_ON(&i915->drm, tc->mode != TC_PORT_TBT_ALT &&
1116                                 !tc_phy_is_owned(tc));
1117 }
1118
1119 void intel_tc_port_lock(struct intel_digital_port *dig_port)
1120 {
1121         __intel_tc_port_lock(to_tc_port(dig_port), 1);
1122 }
1123
1124 /**
1125  * intel_tc_port_disconnect_phy_work: disconnect TypeC PHY from display port
1126  * @dig_port: digital port
1127  *
1128  * Disconnect the given digital port from its TypeC PHY (handing back the
1129  * control of the PHY to the TypeC subsystem). This will happen in a delayed
1130  * manner after each aux transactions and modeset disables.
1131  */
1132 static void intel_tc_port_disconnect_phy_work(struct work_struct *work)
1133 {
1134         struct intel_tc_port *tc =
1135                 container_of(work, struct intel_tc_port, disconnect_phy_work.work);
1136
1137         mutex_lock(&tc->lock);
1138
1139         if (!tc->link_refcount)
1140                 intel_tc_port_update_mode(tc, 1, true);
1141
1142         mutex_unlock(&tc->lock);
1143 }
1144
1145 /**
1146  * intel_tc_port_flush_work: flush the work disconnecting the PHY
1147  * @dig_port: digital port
1148  *
1149  * Flush the delayed work disconnecting an idle PHY.
1150  */
1151 void intel_tc_port_flush_work(struct intel_digital_port *dig_port)
1152 {
1153         flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work);
1154 }
1155
1156 void intel_tc_port_unlock(struct intel_digital_port *dig_port)
1157 {
1158         struct intel_tc_port *tc = to_tc_port(dig_port);
1159
1160         if (!tc->link_refcount && tc->mode != TC_PORT_DISCONNECTED)
1161                 queue_delayed_work(system_unbound_wq, &tc->disconnect_phy_work,
1162                                    msecs_to_jiffies(1000));
1163
1164         mutex_unlock(&tc->lock);
1165 }
1166
1167 bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
1168 {
1169         struct intel_tc_port *tc = to_tc_port(dig_port);
1170
1171         return mutex_is_locked(&tc->lock) ||
1172                tc->link_refcount;
1173 }
1174
1175 void intel_tc_port_get_link(struct intel_digital_port *dig_port,
1176                             int required_lanes)
1177 {
1178         struct intel_tc_port *tc = to_tc_port(dig_port);
1179
1180         __intel_tc_port_lock(tc, required_lanes);
1181         __intel_tc_port_get_link(tc);
1182         intel_tc_port_unlock(dig_port);
1183 }
1184
1185 void intel_tc_port_put_link(struct intel_digital_port *dig_port)
1186 {
1187         struct intel_tc_port *tc = to_tc_port(dig_port);
1188
1189         intel_tc_port_lock(dig_port);
1190         __intel_tc_port_put_link(tc);
1191         intel_tc_port_unlock(dig_port);
1192
1193         /*
1194          * Disconnecting the PHY after the PHY's PLL gets disabled may
1195          * hang the system on ADL-P, so disconnect the PHY here synchronously.
1196          * TODO: remove this once the root cause of the ordering requirement
1197          * is found/fixed.
1198          */
1199         intel_tc_port_flush_work(dig_port);
1200 }
1201
1202 static bool
1203 tc_has_modular_fia(struct drm_i915_private *i915, struct intel_tc_port *tc)
1204 {
1205         enum intel_display_power_domain domain;
1206         intel_wakeref_t wakeref;
1207         u32 val;
1208
1209         if (!INTEL_INFO(i915)->display.has_modular_fia)
1210                 return false;
1211
1212         mutex_lock(&tc->lock);
1213         wakeref = tc_cold_block(tc, &domain);
1214         val = intel_de_read(i915, PORT_TX_DFLEXDPSP(FIA1));
1215         tc_cold_unblock(tc, domain, wakeref);
1216         mutex_unlock(&tc->lock);
1217
1218         drm_WARN_ON(&i915->drm, val == 0xffffffff);
1219
1220         return val & MODULAR_FIA_MASK;
1221 }
1222
1223 static void
1224 tc_port_load_fia_params(struct drm_i915_private *i915, struct intel_tc_port *tc)
1225 {
1226         enum port port = tc->dig_port->base.port;
1227         enum tc_port tc_port = intel_port_to_tc(i915, port);
1228
1229         /*
1230          * Each Modular FIA instance houses 2 TC ports. In SOC that has more
1231          * than two TC ports, there are multiple instances of Modular FIA.
1232          */
1233         if (tc_has_modular_fia(i915, tc)) {
1234                 tc->phy_fia = tc_port / 2;
1235                 tc->phy_fia_idx = tc_port % 2;
1236         } else {
1237                 tc->phy_fia = FIA1;
1238                 tc->phy_fia_idx = tc_port;
1239         }
1240 }
1241
1242 int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
1243 {
1244         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
1245         struct intel_tc_port *tc;
1246         enum port port = dig_port->base.port;
1247         enum tc_port tc_port = intel_port_to_tc(i915, port);
1248
1249         if (drm_WARN_ON(&i915->drm, tc_port == TC_PORT_NONE))
1250                 return -EINVAL;
1251
1252         tc = kzalloc(sizeof(*tc), GFP_KERNEL);
1253         if (!tc)
1254                 return -ENOMEM;
1255
1256         dig_port->tc = tc;
1257         tc->dig_port = dig_port;
1258
1259         if (DISPLAY_VER(i915) >= 13)
1260                 tc->phy_ops = &adlp_tc_phy_ops;
1261         else
1262                 tc->phy_ops = &icl_tc_phy_ops;
1263
1264         snprintf(tc->port_name, sizeof(tc->port_name),
1265                  "%c/TC#%d", port_name(port), tc_port + 1);
1266
1267         mutex_init(&tc->lock);
1268         INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work);
1269         tc->legacy_port = is_legacy;
1270         tc->mode = TC_PORT_DISCONNECTED;
1271         tc->link_refcount = 0;
1272         tc_port_load_fia_params(i915, tc);
1273
1274         intel_tc_port_init_mode(dig_port);
1275
1276         return 0;
1277 }
1278
1279 void intel_tc_port_cleanup(struct intel_digital_port *dig_port)
1280 {
1281         intel_tc_port_flush_work(dig_port);
1282
1283         kfree(dig_port->tc);
1284         dig_port->tc = NULL;
1285 }