drm/i915/tc/tgl: Implement TC cold sequences
[linux-2.6-microblaze.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 "intel_display.h"
8 #include "intel_display_types.h"
9 #include "intel_dp_mst.h"
10 #include "intel_tc.h"
11
12 static const char *tc_port_mode_name(enum tc_port_mode mode)
13 {
14         static const char * const names[] = {
15                 [TC_PORT_TBT_ALT] = "tbt-alt",
16                 [TC_PORT_DP_ALT] = "dp-alt",
17                 [TC_PORT_LEGACY] = "legacy",
18         };
19
20         if (WARN_ON(mode >= ARRAY_SIZE(names)))
21                 mode = TC_PORT_TBT_ALT;
22
23         return names[mode];
24 }
25
26 static void
27 tc_port_load_fia_params(struct drm_i915_private *i915,
28                         struct intel_digital_port *dig_port)
29 {
30         enum port port = dig_port->base.port;
31         enum tc_port tc_port = intel_port_to_tc(i915, port);
32         u32 modular_fia;
33
34         if (INTEL_INFO(i915)->display.has_modular_fia) {
35                 modular_fia = intel_uncore_read(&i915->uncore,
36                                                 PORT_TX_DFLEXDPSP(FIA1));
37                 drm_WARN_ON(&i915->drm, modular_fia == 0xffffffff);
38                 modular_fia &= MODULAR_FIA_MASK;
39         } else {
40                 modular_fia = 0;
41         }
42
43         /*
44          * Each Modular FIA instance houses 2 TC ports. In SOC that has more
45          * than two TC ports, there are multiple instances of Modular FIA.
46          */
47         if (modular_fia) {
48                 dig_port->tc_phy_fia = tc_port / 2;
49                 dig_port->tc_phy_fia_idx = tc_port % 2;
50         } else {
51                 dig_port->tc_phy_fia = FIA1;
52                 dig_port->tc_phy_fia_idx = tc_port;
53         }
54 }
55
56 static enum intel_display_power_domain
57 tc_cold_get_power_domain(struct intel_digital_port *dig_port)
58 {
59         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
60
61         if (INTEL_GEN(i915) == 11)
62                 return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
63         else
64                 return POWER_DOMAIN_TC_COLD_OFF;
65 }
66
67 static intel_wakeref_t
68 tc_cold_block(struct intel_digital_port *dig_port)
69 {
70         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
71         enum intel_display_power_domain domain;
72
73         if (INTEL_GEN(i915) == 11 && !dig_port->tc_legacy_port)
74                 return 0;
75
76         domain = tc_cold_get_power_domain(dig_port);
77         return intel_display_power_get(i915, domain);
78 }
79
80 static void
81 tc_cold_unblock(struct intel_digital_port *dig_port, intel_wakeref_t wakeref)
82 {
83         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
84         enum intel_display_power_domain domain;
85
86         /*
87          * wakeref == -1, means some error happened saving save_depot_stack but
88          * power should still be put down and 0 is a invalid save_depot_stack
89          * id so can be used to skip it for non TC legacy ports.
90          */
91         if (wakeref == 0)
92                 return;
93
94         domain = tc_cold_get_power_domain(dig_port);
95         intel_display_power_put_async(i915, domain, wakeref);
96 }
97
98 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
99 {
100         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
101         struct intel_uncore *uncore = &i915->uncore;
102         u32 lane_mask;
103
104         lane_mask = intel_uncore_read(uncore,
105                                       PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
106
107         drm_WARN_ON(&i915->drm, lane_mask == 0xffffffff);
108
109         lane_mask &= DP_LANE_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx);
110         return lane_mask >> DP_LANE_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx);
111 }
112
113 u32 intel_tc_port_get_pin_assignment_mask(struct intel_digital_port *dig_port)
114 {
115         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
116         struct intel_uncore *uncore = &i915->uncore;
117         u32 pin_mask;
118
119         pin_mask = intel_uncore_read(uncore,
120                                      PORT_TX_DFLEXPA1(dig_port->tc_phy_fia));
121
122         drm_WARN_ON(&i915->drm, pin_mask == 0xffffffff);
123
124         return (pin_mask & DP_PIN_ASSIGNMENT_MASK(dig_port->tc_phy_fia_idx)) >>
125                DP_PIN_ASSIGNMENT_SHIFT(dig_port->tc_phy_fia_idx);
126 }
127
128 int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port)
129 {
130         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
131         intel_wakeref_t wakeref;
132         u32 lane_mask;
133
134         if (dig_port->tc_mode != TC_PORT_DP_ALT)
135                 return 4;
136
137         lane_mask = 0;
138         with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
139                 lane_mask = intel_tc_port_get_lane_mask(dig_port);
140
141         switch (lane_mask) {
142         default:
143                 MISSING_CASE(lane_mask);
144                 /* fall-through */
145         case 0x1:
146         case 0x2:
147         case 0x4:
148         case 0x8:
149                 return 1;
150         case 0x3:
151         case 0xc:
152                 return 2;
153         case 0xf:
154                 return 4;
155         }
156 }
157
158 void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
159                                       int required_lanes)
160 {
161         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
162         bool lane_reversal = dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
163         struct intel_uncore *uncore = &i915->uncore;
164         u32 val;
165
166         drm_WARN_ON(&i915->drm,
167                     lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
168
169         val = intel_uncore_read(uncore,
170                                 PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
171         val &= ~DFLEXDPMLE1_DPMLETC_MASK(dig_port->tc_phy_fia_idx);
172
173         switch (required_lanes) {
174         case 1:
175                 val |= lane_reversal ?
176                         DFLEXDPMLE1_DPMLETC_ML3(dig_port->tc_phy_fia_idx) :
177                         DFLEXDPMLE1_DPMLETC_ML0(dig_port->tc_phy_fia_idx);
178                 break;
179         case 2:
180                 val |= lane_reversal ?
181                         DFLEXDPMLE1_DPMLETC_ML3_2(dig_port->tc_phy_fia_idx) :
182                         DFLEXDPMLE1_DPMLETC_ML1_0(dig_port->tc_phy_fia_idx);
183                 break;
184         case 4:
185                 val |= DFLEXDPMLE1_DPMLETC_ML3_0(dig_port->tc_phy_fia_idx);
186                 break;
187         default:
188                 MISSING_CASE(required_lanes);
189         }
190
191         intel_uncore_write(uncore,
192                            PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia), val);
193 }
194
195 static void tc_port_fixup_legacy_flag(struct intel_digital_port *dig_port,
196                                       u32 live_status_mask)
197 {
198         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
199         u32 valid_hpd_mask;
200
201         if (dig_port->tc_legacy_port)
202                 valid_hpd_mask = BIT(TC_PORT_LEGACY);
203         else
204                 valid_hpd_mask = BIT(TC_PORT_DP_ALT) |
205                                  BIT(TC_PORT_TBT_ALT);
206
207         if (!(live_status_mask & ~valid_hpd_mask))
208                 return;
209
210         /* If live status mismatches the VBT flag, trust the live status. */
211         drm_err(&i915->drm,
212                 "Port %s: live status %08x mismatches the legacy port flag, fix flag\n",
213                 dig_port->tc_port_name, live_status_mask);
214
215         dig_port->tc_legacy_port = !dig_port->tc_legacy_port;
216 }
217
218 static u32 tc_port_live_status_mask(struct intel_digital_port *dig_port)
219 {
220         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
221         enum tc_port tc_port = intel_port_to_tc(i915, dig_port->base.port);
222         struct intel_uncore *uncore = &i915->uncore;
223         u32 mask = 0;
224         u32 val;
225
226         val = intel_uncore_read(uncore,
227                                 PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
228
229         if (val == 0xffffffff) {
230                 drm_dbg_kms(&i915->drm,
231                             "Port %s: PHY in TCCOLD, nothing connected\n",
232                             dig_port->tc_port_name);
233                 return mask;
234         }
235
236         if (val & TC_LIVE_STATE_TBT(dig_port->tc_phy_fia_idx))
237                 mask |= BIT(TC_PORT_TBT_ALT);
238         if (val & TC_LIVE_STATE_TC(dig_port->tc_phy_fia_idx))
239                 mask |= BIT(TC_PORT_DP_ALT);
240
241         if (intel_uncore_read(uncore, SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port))
242                 mask |= BIT(TC_PORT_LEGACY);
243
244         /* The sink can be connected only in a single mode. */
245         if (!drm_WARN_ON(&i915->drm, hweight32(mask) > 1))
246                 tc_port_fixup_legacy_flag(dig_port, mask);
247
248         return mask;
249 }
250
251 static bool icl_tc_phy_status_complete(struct intel_digital_port *dig_port)
252 {
253         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
254         struct intel_uncore *uncore = &i915->uncore;
255         u32 val;
256
257         val = intel_uncore_read(uncore,
258                                 PORT_TX_DFLEXDPPMS(dig_port->tc_phy_fia));
259         if (val == 0xffffffff) {
260                 drm_dbg_kms(&i915->drm,
261                             "Port %s: PHY in TCCOLD, assuming not complete\n",
262                             dig_port->tc_port_name);
263                 return false;
264         }
265
266         return val & DP_PHY_MODE_STATUS_COMPLETED(dig_port->tc_phy_fia_idx);
267 }
268
269 static bool icl_tc_phy_set_safe_mode(struct intel_digital_port *dig_port,
270                                      bool enable)
271 {
272         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
273         struct intel_uncore *uncore = &i915->uncore;
274         u32 val;
275
276         val = intel_uncore_read(uncore,
277                                 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
278         if (val == 0xffffffff) {
279                 drm_dbg_kms(&i915->drm,
280                             "Port %s: PHY in TCCOLD, can't set safe-mode to %s\n",
281                             dig_port->tc_port_name, enableddisabled(enable));
282
283                 return false;
284         }
285
286         val &= ~DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
287         if (!enable)
288                 val |= DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx);
289
290         intel_uncore_write(uncore,
291                            PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia), val);
292
293         if (enable && wait_for(!icl_tc_phy_status_complete(dig_port), 10))
294                 drm_dbg_kms(&i915->drm,
295                             "Port %s: PHY complete clear timed out\n",
296                             dig_port->tc_port_name);
297
298         return true;
299 }
300
301 static bool icl_tc_phy_is_in_safe_mode(struct intel_digital_port *dig_port)
302 {
303         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
304         struct intel_uncore *uncore = &i915->uncore;
305         u32 val;
306
307         val = intel_uncore_read(uncore,
308                                 PORT_TX_DFLEXDPCSSS(dig_port->tc_phy_fia));
309         if (val == 0xffffffff) {
310                 drm_dbg_kms(&i915->drm,
311                             "Port %s: PHY in TCCOLD, assume safe mode\n",
312                             dig_port->tc_port_name);
313                 return true;
314         }
315
316         return !(val & DP_PHY_MODE_STATUS_NOT_SAFE(dig_port->tc_phy_fia_idx));
317 }
318
319 /*
320  * This function implements the first part of the Connect Flow described by our
321  * specification, Gen11 TypeC Programming chapter. The rest of the flow (reading
322  * lanes, EDID, etc) is done as needed in the typical places.
323  *
324  * Unlike the other ports, type-C ports are not available to use as soon as we
325  * get a hotplug. The type-C PHYs can be shared between multiple controllers:
326  * display, USB, etc. As a result, handshaking through FIA is required around
327  * connect and disconnect to cleanly transfer ownership with the controller and
328  * set the type-C power state.
329  */
330 static void icl_tc_phy_connect(struct intel_digital_port *dig_port,
331                                int required_lanes)
332 {
333         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
334         int max_lanes;
335
336         if (!icl_tc_phy_status_complete(dig_port)) {
337                 drm_dbg_kms(&i915->drm, "Port %s: PHY not ready\n",
338                             dig_port->tc_port_name);
339                 goto out_set_tbt_alt_mode;
340         }
341
342         if (!icl_tc_phy_set_safe_mode(dig_port, false) &&
343             !WARN_ON(dig_port->tc_legacy_port))
344                 goto out_set_tbt_alt_mode;
345
346         max_lanes = intel_tc_port_fia_max_lane_count(dig_port);
347         if (dig_port->tc_legacy_port) {
348                 WARN_ON(max_lanes != 4);
349                 dig_port->tc_mode = TC_PORT_LEGACY;
350
351                 return;
352         }
353
354         /*
355          * Now we have to re-check the live state, in case the port recently
356          * became disconnected. Not necessary for legacy mode.
357          */
358         if (!(tc_port_live_status_mask(dig_port) & BIT(TC_PORT_DP_ALT))) {
359                 drm_dbg_kms(&i915->drm, "Port %s: PHY sudden disconnect\n",
360                             dig_port->tc_port_name);
361                 goto out_set_safe_mode;
362         }
363
364         if (max_lanes < required_lanes) {
365                 drm_dbg_kms(&i915->drm,
366                             "Port %s: PHY max lanes %d < required lanes %d\n",
367                             dig_port->tc_port_name,
368                             max_lanes, required_lanes);
369                 goto out_set_safe_mode;
370         }
371
372         dig_port->tc_mode = TC_PORT_DP_ALT;
373
374         return;
375
376 out_set_safe_mode:
377         icl_tc_phy_set_safe_mode(dig_port, true);
378 out_set_tbt_alt_mode:
379         dig_port->tc_mode = TC_PORT_TBT_ALT;
380 }
381
382 /*
383  * See the comment at the connect function. This implements the Disconnect
384  * Flow.
385  */
386 static void icl_tc_phy_disconnect(struct intel_digital_port *dig_port)
387 {
388         switch (dig_port->tc_mode) {
389         case TC_PORT_LEGACY:
390                 /* Nothing to do, we never disconnect from legacy mode */
391                 break;
392         case TC_PORT_DP_ALT:
393                 icl_tc_phy_set_safe_mode(dig_port, true);
394                 dig_port->tc_mode = TC_PORT_TBT_ALT;
395                 break;
396         case TC_PORT_TBT_ALT:
397                 /* Nothing to do, we stay in TBT-alt mode */
398                 break;
399         default:
400                 MISSING_CASE(dig_port->tc_mode);
401         }
402 }
403
404 static bool icl_tc_phy_is_connected(struct intel_digital_port *dig_port)
405 {
406         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
407
408         if (!icl_tc_phy_status_complete(dig_port)) {
409                 drm_dbg_kms(&i915->drm, "Port %s: PHY status not complete\n",
410                             dig_port->tc_port_name);
411                 return dig_port->tc_mode == TC_PORT_TBT_ALT;
412         }
413
414         if (icl_tc_phy_is_in_safe_mode(dig_port)) {
415                 drm_dbg_kms(&i915->drm, "Port %s: PHY still in safe mode\n",
416                             dig_port->tc_port_name);
417
418                 return false;
419         }
420
421         return dig_port->tc_mode == TC_PORT_DP_ALT ||
422                dig_port->tc_mode == TC_PORT_LEGACY;
423 }
424
425 static enum tc_port_mode
426 intel_tc_port_get_current_mode(struct intel_digital_port *dig_port)
427 {
428         u32 live_status_mask = tc_port_live_status_mask(dig_port);
429         bool in_safe_mode = icl_tc_phy_is_in_safe_mode(dig_port);
430         enum tc_port_mode mode;
431
432         if (in_safe_mode || WARN_ON(!icl_tc_phy_status_complete(dig_port)))
433                 return TC_PORT_TBT_ALT;
434
435         mode = dig_port->tc_legacy_port ? TC_PORT_LEGACY : TC_PORT_DP_ALT;
436         if (live_status_mask) {
437                 enum tc_port_mode live_mode = fls(live_status_mask) - 1;
438
439                 if (!WARN_ON(live_mode == TC_PORT_TBT_ALT))
440                         mode = live_mode;
441         }
442
443         return mode;
444 }
445
446 static enum tc_port_mode
447 intel_tc_port_get_target_mode(struct intel_digital_port *dig_port)
448 {
449         u32 live_status_mask = tc_port_live_status_mask(dig_port);
450
451         if (live_status_mask)
452                 return fls(live_status_mask) - 1;
453
454         return icl_tc_phy_status_complete(dig_port) &&
455                dig_port->tc_legacy_port ? TC_PORT_LEGACY :
456                                           TC_PORT_TBT_ALT;
457 }
458
459 static void intel_tc_port_reset_mode(struct intel_digital_port *dig_port,
460                                      int required_lanes)
461 {
462         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
463         enum tc_port_mode old_tc_mode = dig_port->tc_mode;
464
465         intel_display_power_flush_work(i915);
466         if (INTEL_GEN(i915) != 11 || !dig_port->tc_legacy_port) {
467                 enum intel_display_power_domain aux_domain;
468                 bool aux_powered;
469
470                 aux_domain = intel_aux_power_domain(dig_port);
471                 aux_powered = intel_display_power_is_enabled(i915, aux_domain);
472                 drm_WARN_ON(&i915->drm, aux_powered);
473         }
474
475         icl_tc_phy_disconnect(dig_port);
476         icl_tc_phy_connect(dig_port, required_lanes);
477
478         drm_dbg_kms(&i915->drm, "Port %s: TC port mode reset (%s -> %s)\n",
479                     dig_port->tc_port_name,
480                     tc_port_mode_name(old_tc_mode),
481                     tc_port_mode_name(dig_port->tc_mode));
482 }
483
484 static void
485 intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
486                                  int refcount)
487 {
488         WARN_ON(dig_port->tc_link_refcount);
489         dig_port->tc_link_refcount = refcount;
490 }
491
492 void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
493 {
494         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
495         struct intel_encoder *encoder = &dig_port->base;
496         intel_wakeref_t tc_cold_wref;
497         int active_links = 0;
498
499         mutex_lock(&dig_port->tc_lock);
500         tc_cold_wref = tc_cold_block(dig_port);
501
502         dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
503         if (dig_port->dp.is_mst)
504                 active_links = intel_dp_mst_encoder_active_links(dig_port);
505         else if (encoder->base.crtc)
506                 active_links = to_intel_crtc(encoder->base.crtc)->active;
507
508         if (active_links) {
509                 if (!icl_tc_phy_is_connected(dig_port))
510                         drm_dbg_kms(&i915->drm,
511                                     "Port %s: PHY disconnected with %d active link(s)\n",
512                                     dig_port->tc_port_name, active_links);
513                 intel_tc_port_link_init_refcount(dig_port, active_links);
514
515                 goto out;
516         }
517
518         if (dig_port->tc_legacy_port)
519                 icl_tc_phy_connect(dig_port, 1);
520
521 out:
522         drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n",
523                     dig_port->tc_port_name,
524                     tc_port_mode_name(dig_port->tc_mode));
525
526         tc_cold_unblock(dig_port, tc_cold_wref);
527         mutex_unlock(&dig_port->tc_lock);
528 }
529
530 static bool intel_tc_port_needs_reset(struct intel_digital_port *dig_port)
531 {
532         return intel_tc_port_get_target_mode(dig_port) != dig_port->tc_mode;
533 }
534
535 /*
536  * The type-C ports are different because even when they are connected, they may
537  * not be available/usable by the graphics driver: see the comment on
538  * icl_tc_phy_connect(). So in our driver instead of adding the additional
539  * concept of "usable" and make everything check for "connected and usable" we
540  * define a port as "connected" when it is not only connected, but also when it
541  * is usable by the rest of the driver. That maintains the old assumption that
542  * connected ports are usable, and avoids exposing to the users objects they
543  * can't really use.
544  */
545 bool intel_tc_port_connected(struct intel_digital_port *dig_port)
546 {
547         bool is_connected;
548         intel_wakeref_t tc_cold_wref;
549
550         intel_tc_port_lock(dig_port);
551         tc_cold_wref = tc_cold_block(dig_port);
552
553         is_connected = tc_port_live_status_mask(dig_port) &
554                        BIT(dig_port->tc_mode);
555
556         tc_cold_unblock(dig_port, tc_cold_wref);
557         intel_tc_port_unlock(dig_port);
558
559         return is_connected;
560 }
561
562 static void __intel_tc_port_lock(struct intel_digital_port *dig_port,
563                                  int required_lanes)
564 {
565         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
566         intel_wakeref_t wakeref;
567
568         wakeref = intel_display_power_get(i915, POWER_DOMAIN_DISPLAY_CORE);
569
570         mutex_lock(&dig_port->tc_lock);
571
572         if (!dig_port->tc_link_refcount) {
573                 intel_wakeref_t tc_cold_wref;
574
575                 tc_cold_wref = tc_cold_block(dig_port);
576
577                 if (intel_tc_port_needs_reset(dig_port))
578                         intel_tc_port_reset_mode(dig_port, required_lanes);
579
580                 tc_cold_unblock(dig_port, tc_cold_wref);
581         }
582
583         drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref);
584         dig_port->tc_lock_wakeref = wakeref;
585 }
586
587 void intel_tc_port_lock(struct intel_digital_port *dig_port)
588 {
589         __intel_tc_port_lock(dig_port, 1);
590 }
591
592 void intel_tc_port_unlock(struct intel_digital_port *dig_port)
593 {
594         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
595         intel_wakeref_t wakeref = fetch_and_zero(&dig_port->tc_lock_wakeref);
596
597         mutex_unlock(&dig_port->tc_lock);
598
599         intel_display_power_put_async(i915, POWER_DOMAIN_DISPLAY_CORE,
600                                       wakeref);
601 }
602
603 bool intel_tc_port_ref_held(struct intel_digital_port *dig_port)
604 {
605         return mutex_is_locked(&dig_port->tc_lock) ||
606                dig_port->tc_link_refcount;
607 }
608
609 void intel_tc_port_get_link(struct intel_digital_port *dig_port,
610                             int required_lanes)
611 {
612         __intel_tc_port_lock(dig_port, required_lanes);
613         dig_port->tc_link_refcount++;
614         intel_tc_port_unlock(dig_port);
615 }
616
617 void intel_tc_port_put_link(struct intel_digital_port *dig_port)
618 {
619         mutex_lock(&dig_port->tc_lock);
620         dig_port->tc_link_refcount--;
621         mutex_unlock(&dig_port->tc_lock);
622 }
623
624 void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
625 {
626         struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
627         enum port port = dig_port->base.port;
628         enum tc_port tc_port = intel_port_to_tc(i915, port);
629
630         if (drm_WARN_ON(&i915->drm, tc_port == PORT_TC_NONE))
631                 return;
632
633         snprintf(dig_port->tc_port_name, sizeof(dig_port->tc_port_name),
634                  "%c/TC#%d", port_name(port), tc_port + 1);
635
636         mutex_init(&dig_port->tc_lock);
637         dig_port->tc_legacy_port = is_legacy;
638         dig_port->tc_link_refcount = 0;
639         tc_port_load_fia_params(i915, dig_port);
640 }