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