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