xref: /linux/drivers/gpu/drm/i915/display/intel_ddi.c (revision 4c4279a8d58d146dc39b150226ee974652de4eef)
1379bc100SJani Nikula /*
2379bc100SJani Nikula  * Copyright © 2012 Intel Corporation
3379bc100SJani Nikula  *
4379bc100SJani Nikula  * Permission is hereby granted, free of charge, to any person obtaining a
5379bc100SJani Nikula  * copy of this software and associated documentation files (the "Software"),
6379bc100SJani Nikula  * to deal in the Software without restriction, including without limitation
7379bc100SJani Nikula  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8379bc100SJani Nikula  * and/or sell copies of the Software, and to permit persons to whom the
9379bc100SJani Nikula  * Software is furnished to do so, subject to the following conditions:
10379bc100SJani Nikula  *
11379bc100SJani Nikula  * The above copyright notice and this permission notice (including the next
12379bc100SJani Nikula  * paragraph) shall be included in all copies or substantial portions of the
13379bc100SJani Nikula  * Software.
14379bc100SJani Nikula  *
15379bc100SJani Nikula  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16379bc100SJani Nikula  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17379bc100SJani Nikula  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18379bc100SJani Nikula  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19379bc100SJani Nikula  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20379bc100SJani Nikula  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21379bc100SJani Nikula  * IN THE SOFTWARE.
22379bc100SJani Nikula  *
23379bc100SJani Nikula  * Authors:
24379bc100SJani Nikula  *    Eugeni Dodonov <eugeni.dodonov@intel.com>
25379bc100SJani Nikula  *
26379bc100SJani Nikula  */
27379bc100SJani Nikula 
28707c3a7dSLucas De Marchi #include <linux/string_helpers.h>
29707c3a7dSLucas De Marchi 
30644edf52SThomas Zimmermann #include <drm/display/drm_scdc_helper.h>
316306d8dbSHans de Goede #include <drm/drm_privacy_screen_consumer.h>
32379bc100SJani Nikula 
33379bc100SJani Nikula #include "i915_drv.h"
34801543b2SJani Nikula #include "i915_reg.h"
35379bc100SJani Nikula #include "intel_audio.h"
36b43edc50SJani Nikula #include "intel_audio_regs.h"
376cc42fbeSJani Nikula #include "intel_backlight.h"
38379bc100SJani Nikula #include "intel_combo_phy.h"
39d0864ee4SMatt Roper #include "intel_combo_phy_regs.h"
40379bc100SJani Nikula #include "intel_connector.h"
417c53e628SJani Nikula #include "intel_crtc.h"
4251390cc0SRadhakrishna Sripada #include "intel_cx0_phy.h"
4323ef6194SJosé Roberto de Souza #include "intel_cx0_phy_regs.h"
44379bc100SJani Nikula #include "intel_ddi.h"
4599092a97SDave Airlie #include "intel_ddi_buf_trans.h"
467785ae0bSVille Syrjälä #include "intel_de.h"
47979e1b32SImre Deak #include "intel_display_power.h"
481d455f8dSJani Nikula #include "intel_display_types.h"
4989cb0ba4SImre Deak #include "intel_dkl_phy.h"
50d69813c7SImre Deak #include "intel_dkl_phy_regs.h"
51379bc100SJani Nikula #include "intel_dp.h"
52bb45217fSVille Syrjälä #include "intel_dp_aux.h"
53379bc100SJani Nikula #include "intel_dp_link_training.h"
54dcb38f79SDave Airlie #include "intel_dp_mst.h"
55379bc100SJani Nikula #include "intel_dpio_phy.h"
56379bc100SJani Nikula #include "intel_dsi.h"
57dcb38f79SDave Airlie #include "intel_fdi.h"
58379bc100SJani Nikula #include "intel_fifo_underrun.h"
59379bc100SJani Nikula #include "intel_gmbus.h"
60379bc100SJani Nikula #include "intel_hdcp.h"
61379bc100SJani Nikula #include "intel_hdmi.h"
62379bc100SJani Nikula #include "intel_hotplug.h"
6303120fefSJani Nikula #include "intel_hti.h"
64379bc100SJani Nikula #include "intel_lspcon.h"
65589ebefdSImre Deak #include "intel_mg_phy_regs.h"
66abad6805SJani Nikula #include "intel_pps.h"
67379bc100SJani Nikula #include "intel_psr.h"
680c82118bSJani Nikula #include "intel_quirks.h"
69865b73eaSMatt Roper #include "intel_snps_phy.h"
70bc85328fSImre Deak #include "intel_tc.h"
71379bc100SJani Nikula #include "intel_vdsc.h"
72c3f05948SJani Nikula #include "intel_vdsc_regs.h"
73714b1cdbSDave Airlie #include "skl_scaler.h"
7446d12f91SDave Airlie #include "skl_universal_plane.h"
75379bc100SJani Nikula 
76379bc100SJani Nikula static const u8 index_to_dp_signal_levels[] = {
77379bc100SJani Nikula 	[0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
78379bc100SJani Nikula 	[1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1,
79379bc100SJani Nikula 	[2] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2,
80379bc100SJani Nikula 	[3] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3,
81379bc100SJani Nikula 	[4] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0,
82379bc100SJani Nikula 	[5] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1,
83379bc100SJani Nikula 	[6] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2,
84379bc100SJani Nikula 	[7] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0,
85379bc100SJani Nikula 	[8] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1,
86379bc100SJani Nikula 	[9] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0,
87379bc100SJani Nikula };
88379bc100SJani Nikula 
89a621860aSVille Syrjälä static int intel_ddi_hdmi_level(struct intel_encoder *encoder,
903e022c1fSVille Syrjälä 				const struct intel_ddi_buf_trans *trans)
91379bc100SJani Nikula {
923e022c1fSVille Syrjälä 	int level;
93379bc100SJani Nikula 
9402107ef1SVille Syrjälä 	level = intel_bios_hdmi_level_shift(encoder->devdata);
950aed3bdeSJani Nikula 	if (level < 0)
963e022c1fSVille Syrjälä 		level = trans->hdmi_default_entry;
97379bc100SJani Nikula 
98379bc100SJani Nikula 	return level;
99379bc100SJani Nikula }
100379bc100SJani Nikula 
1015bafd85dSVille Syrjälä static bool has_buf_trans_select(struct drm_i915_private *i915)
1025bafd85dSVille Syrjälä {
1035bafd85dSVille Syrjälä 	return DISPLAY_VER(i915) < 10 && !IS_BROXTON(i915);
1045bafd85dSVille Syrjälä }
1055bafd85dSVille Syrjälä 
106f820693bSVille Syrjälä static bool has_iboost(struct drm_i915_private *i915)
107f820693bSVille Syrjälä {
108f820693bSVille Syrjälä 	return DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915);
109f820693bSVille Syrjälä }
110f820693bSVille Syrjälä 
111379bc100SJani Nikula /*
112379bc100SJani Nikula  * Starting with Haswell, DDI port buffers must be programmed with correct
113379bc100SJani Nikula  * values in advance. This function programs the correct values for
114379bc100SJani Nikula  * DP/eDP/FDI use cases.
115379bc100SJani Nikula  */
116266152aeSVille Syrjälä void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
117379bc100SJani Nikula 				const struct intel_crtc_state *crtc_state)
118379bc100SJani Nikula {
119379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
120379bc100SJani Nikula 	u32 iboost_bit = 0;
121379bc100SJani Nikula 	int i, n_entries;
122379bc100SJani Nikula 	enum port port = encoder->port;
123e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
124379bc100SJani Nikula 
125e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
126e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
127d6b10b1aSVille Syrjälä 		return;
128379bc100SJani Nikula 
129379bc100SJani Nikula 	/* If we're boosting the current, set bit 31 of trans1 */
130f820693bSVille Syrjälä 	if (has_iboost(dev_priv) &&
13102107ef1SVille Syrjälä 	    intel_bios_dp_boost_level(encoder->devdata))
132379bc100SJani Nikula 		iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
133379bc100SJani Nikula 
134379bc100SJani Nikula 	for (i = 0; i < n_entries; i++) {
135f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, i),
136e505d764SVille Syrjälä 			       trans->entries[i].hsw.trans1 | iboost_bit);
137f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, i),
138e505d764SVille Syrjälä 			       trans->entries[i].hsw.trans2);
139379bc100SJani Nikula 	}
140379bc100SJani Nikula }
141379bc100SJani Nikula 
142379bc100SJani Nikula /*
143379bc100SJani Nikula  * Starting with Haswell, DDI port buffers must be programmed with correct
144379bc100SJani Nikula  * values in advance. This function programs the correct values for
145379bc100SJani Nikula  * HDMI/DVI use cases.
146379bc100SJani Nikula  */
147266152aeSVille Syrjälä static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
148e722ab8bSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
149379bc100SJani Nikula {
150379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
151d0920a45SVille Syrjälä 	int level = intel_ddi_level(encoder, crtc_state, 0);
152379bc100SJani Nikula 	u32 iboost_bit = 0;
153379bc100SJani Nikula 	int n_entries;
154379bc100SJani Nikula 	enum port port = encoder->port;
155e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
156379bc100SJani Nikula 
157e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
158e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
159379bc100SJani Nikula 		return;
160379bc100SJani Nikula 
161379bc100SJani Nikula 	/* If we're boosting the current, set bit 31 of trans1 */
162f820693bSVille Syrjälä 	if (has_iboost(dev_priv) &&
16302107ef1SVille Syrjälä 	    intel_bios_hdmi_boost_level(encoder->devdata))
164379bc100SJani Nikula 		iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
165379bc100SJani Nikula 
166379bc100SJani Nikula 	/* Entry 9 is for HDMI: */
167f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, 9),
168e505d764SVille Syrjälä 		       trans->entries[level].hsw.trans1 | iboost_bit);
169f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, 9),
170e505d764SVille Syrjälä 		       trans->entries[level].hsw.trans2);
171379bc100SJani Nikula }
172379bc100SJani Nikula 
17323ef6194SJosé Roberto de Souza static void mtl_wait_ddi_buf_idle(struct drm_i915_private *i915, enum port port)
17423ef6194SJosé Roberto de Souza {
17523ef6194SJosé Roberto de Souza 	int ret;
17623ef6194SJosé Roberto de Souza 
17723ef6194SJosé Roberto de Souza 	/* FIXME: find out why Bspec's 100us timeout is too short */
17823ef6194SJosé Roberto de Souza 	ret = wait_for_us((intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port)) &
17923ef6194SJosé Roberto de Souza 			   XELPDP_PORT_BUF_PHY_IDLE), 10000);
18023ef6194SJosé Roberto de Souza 	if (ret)
18123ef6194SJosé Roberto de Souza 		drm_err(&i915->drm, "Timeout waiting for DDI BUF %c to get idle\n",
18223ef6194SJosé Roberto de Souza 			port_name(port));
18323ef6194SJosé Roberto de Souza }
18423ef6194SJosé Roberto de Souza 
185dcb38f79SDave Airlie void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
186379bc100SJani Nikula 			     enum port port)
187379bc100SJani Nikula {
1885a2ad99bSManasi Navare 	if (IS_BROXTON(dev_priv)) {
1895a2ad99bSManasi Navare 		udelay(16);
190379bc100SJani Nikula 		return;
191379bc100SJani Nikula 	}
1925a2ad99bSManasi Navare 
1935a2ad99bSManasi Navare 	if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
1945a2ad99bSManasi Navare 			 DDI_BUF_IS_IDLE), 8))
1955a2ad99bSManasi Navare 		drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get idle\n",
19647bdb1caSJani Nikula 			port_name(port));
197379bc100SJani Nikula }
198379bc100SJani Nikula 
199e828da30SManasi Navare static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
200e828da30SManasi Navare 				      enum port port)
201e828da30SManasi Navare {
2025add4575SAnkit Nautiyal 	enum phy phy = intel_port_to_phy(dev_priv, port);
2035add4575SAnkit Nautiyal 	int timeout_us;
204f82f2563SMatt Roper 	int ret;
205f82f2563SMatt Roper 
206e828da30SManasi Navare 	/* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
207ad314fecSVille Syrjälä 	if (DISPLAY_VER(dev_priv) < 10) {
208e828da30SManasi Navare 		usleep_range(518, 1000);
209e828da30SManasi Navare 		return;
210e828da30SManasi Navare 	}
211e828da30SManasi Navare 
21223ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14) {
21323ef6194SJosé Roberto de Souza 		timeout_us = 10000;
21423ef6194SJosé Roberto de Souza 	} else if (IS_DG2(dev_priv)) {
2155add4575SAnkit Nautiyal 		timeout_us = 1200;
2165add4575SAnkit Nautiyal 	} else if (DISPLAY_VER(dev_priv) >= 12) {
2175add4575SAnkit Nautiyal 		if (intel_phy_is_tc(dev_priv, phy))
2185add4575SAnkit Nautiyal 			timeout_us = 3000;
2195add4575SAnkit Nautiyal 		else
2205add4575SAnkit Nautiyal 			timeout_us = 1000;
2215add4575SAnkit Nautiyal 	} else {
2225add4575SAnkit Nautiyal 		timeout_us = 500;
2235add4575SAnkit Nautiyal 	}
2245add4575SAnkit Nautiyal 
22523ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14)
22623ef6194SJosé Roberto de Souza 		ret = _wait_for(!(intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) & XELPDP_PORT_BUF_PHY_IDLE),
22723ef6194SJosé Roberto de Souza 				timeout_us, 10, 10);
22823ef6194SJosé Roberto de Souza 	else
22923ef6194SJosé Roberto de Souza 		ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & DDI_BUF_IS_IDLE),
23023ef6194SJosé Roberto de Souza 				timeout_us, 10, 10);
231f82f2563SMatt Roper 
232f82f2563SMatt Roper 	if (ret)
233e828da30SManasi Navare 		drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
234e828da30SManasi Navare 			port_name(port));
235e828da30SManasi Navare }
236e828da30SManasi Navare 
237ad952982SVille Syrjälä static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
238379bc100SJani Nikula {
239379bc100SJani Nikula 	switch (pll->info->id) {
240379bc100SJani Nikula 	case DPLL_ID_WRPLL1:
241379bc100SJani Nikula 		return PORT_CLK_SEL_WRPLL1;
242379bc100SJani Nikula 	case DPLL_ID_WRPLL2:
243379bc100SJani Nikula 		return PORT_CLK_SEL_WRPLL2;
244379bc100SJani Nikula 	case DPLL_ID_SPLL:
245379bc100SJani Nikula 		return PORT_CLK_SEL_SPLL;
246379bc100SJani Nikula 	case DPLL_ID_LCPLL_810:
247379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_810;
248379bc100SJani Nikula 	case DPLL_ID_LCPLL_1350:
249379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_1350;
250379bc100SJani Nikula 	case DPLL_ID_LCPLL_2700:
251379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_2700;
252379bc100SJani Nikula 	default:
253379bc100SJani Nikula 		MISSING_CASE(pll->info->id);
254379bc100SJani Nikula 		return PORT_CLK_SEL_NONE;
255379bc100SJani Nikula 	}
256379bc100SJani Nikula }
257379bc100SJani Nikula 
258379bc100SJani Nikula static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
259379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state)
260379bc100SJani Nikula {
261379bc100SJani Nikula 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
262379bc100SJani Nikula 	int clock = crtc_state->port_clock;
263379bc100SJani Nikula 	const enum intel_dpll_id id = pll->info->id;
264379bc100SJani Nikula 
265379bc100SJani Nikula 	switch (id) {
266379bc100SJani Nikula 	default:
267379bc100SJani Nikula 		/*
268379bc100SJani Nikula 		 * DPLL_ID_ICL_DPLL0 and DPLL_ID_ICL_DPLL1 should not be used
269379bc100SJani Nikula 		 * here, so do warn if this get passed in
270379bc100SJani Nikula 		 */
271379bc100SJani Nikula 		MISSING_CASE(id);
272379bc100SJani Nikula 		return DDI_CLK_SEL_NONE;
273379bc100SJani Nikula 	case DPLL_ID_ICL_TBTPLL:
274379bc100SJani Nikula 		switch (clock) {
275379bc100SJani Nikula 		case 162000:
276379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_162;
277379bc100SJani Nikula 		case 270000:
278379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_270;
279379bc100SJani Nikula 		case 540000:
280379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_540;
281379bc100SJani Nikula 		case 810000:
282379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_810;
283379bc100SJani Nikula 		default:
284379bc100SJani Nikula 			MISSING_CASE(clock);
285379bc100SJani Nikula 			return DDI_CLK_SEL_NONE;
286379bc100SJani Nikula 		}
287379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL1:
288379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL2:
289379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL3:
290379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL4:
2916677c3b1SJosé Roberto de Souza 	case DPLL_ID_TGL_MGPLL5:
2926677c3b1SJosé Roberto de Souza 	case DPLL_ID_TGL_MGPLL6:
293379bc100SJani Nikula 		return DDI_CLK_SEL_MG;
294379bc100SJani Nikula 	}
295379bc100SJani Nikula }
296379bc100SJani Nikula 
297414002f1SImre Deak static u32 ddi_buf_phy_link_rate(int port_clock)
298414002f1SImre Deak {
299414002f1SImre Deak 	switch (port_clock) {
300414002f1SImre Deak 	case 162000:
301414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(0);
302414002f1SImre Deak 	case 216000:
303414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(4);
304414002f1SImre Deak 	case 243000:
305414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(5);
306414002f1SImre Deak 	case 270000:
307414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(1);
308414002f1SImre Deak 	case 324000:
309414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(6);
310414002f1SImre Deak 	case 432000:
311414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(7);
312414002f1SImre Deak 	case 540000:
313414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(2);
314414002f1SImre Deak 	case 810000:
315414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(3);
316414002f1SImre Deak 	default:
317414002f1SImre Deak 		MISSING_CASE(port_clock);
318414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(0);
319414002f1SImre Deak 	}
320414002f1SImre Deak }
321414002f1SImre Deak 
322a621860aSVille Syrjälä static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
323a621860aSVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
324379bc100SJani Nikula {
32555ce306cSJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
326b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3277801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
32855ce306cSJosé Roberto de Souza 	enum phy phy = intel_port_to_phy(i915, encoder->port);
329379bc100SJani Nikula 
3309f620f1dSVille Syrjälä 	/* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */
3317801f3b7SLucas De Marchi 	intel_dp->DP = dig_port->saved_port_bits |
3329f620f1dSVille Syrjälä 		DDI_PORT_WIDTH(crtc_state->lane_count) |
3339f620f1dSVille Syrjälä 		DDI_BUF_TRANS_SELECT(0);
33455ce306cSJosé Roberto de Souza 
33523ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(i915) >= 14) {
33623ef6194SJosé Roberto de Souza 		if (intel_dp_is_uhbr(crtc_state))
33723ef6194SJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_PORT_DATA_40BIT;
33823ef6194SJosé Roberto de Souza 		else
33923ef6194SJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_PORT_DATA_10BIT;
34023ef6194SJosé Roberto de Souza 	}
34123ef6194SJosé Roberto de Souza 
342414002f1SImre Deak 	if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) {
343414002f1SImre Deak 		intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock);
34411a89708SImre Deak 		if (!intel_tc_port_in_tbt_alt_mode(dig_port))
34555ce306cSJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
346379bc100SJani Nikula 	}
347414002f1SImre Deak }
348379bc100SJani Nikula 
349379bc100SJani Nikula static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
350379bc100SJani Nikula 				 enum port port)
351379bc100SJani Nikula {
352f7960e7fSJani Nikula 	u32 val = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK;
353379bc100SJani Nikula 
354379bc100SJani Nikula 	switch (val) {
355379bc100SJani Nikula 	case DDI_CLK_SEL_NONE:
356379bc100SJani Nikula 		return 0;
357379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_162:
358379bc100SJani Nikula 		return 162000;
359379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_270:
360379bc100SJani Nikula 		return 270000;
361379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_540:
362379bc100SJani Nikula 		return 540000;
363379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_810:
364379bc100SJani Nikula 		return 810000;
365379bc100SJani Nikula 	default:
366379bc100SJani Nikula 		MISSING_CASE(val);
367379bc100SJani Nikula 		return 0;
368379bc100SJani Nikula 	}
369379bc100SJani Nikula }
370379bc100SJani Nikula 
371623411c2SVille Syrjälä static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
372623411c2SVille Syrjälä {
373623411c2SVille Syrjälä 	/* CRT dotclock is determined via other means */
374623411c2SVille Syrjälä 	if (pipe_config->has_pch_encoder)
375623411c2SVille Syrjälä 		return;
376623411c2SVille Syrjälä 
377623411c2SVille Syrjälä 	pipe_config->hw.adjusted_mode.crtc_clock =
378623411c2SVille Syrjälä 		intel_crtc_dotclock(pipe_config);
379379bc100SJani Nikula }
380379bc100SJani Nikula 
3810c06fa15SGwan-gyeong Mun void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
3820c06fa15SGwan-gyeong Mun 			  const struct drm_connector_state *conn_state)
383379bc100SJani Nikula {
3842225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
385379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
386379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
387379bc100SJani Nikula 	u32 temp;
388379bc100SJani Nikula 
389379bc100SJani Nikula 	if (!intel_crtc_has_dp_encoder(crtc_state))
390379bc100SJani Nikula 		return;
391379bc100SJani Nikula 
3921de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder));
393379bc100SJani Nikula 
3943e706dffSVille Syrjälä 	temp = DP_MSA_MISC_SYNC_CLOCK;
395379bc100SJani Nikula 
396379bc100SJani Nikula 	switch (crtc_state->pipe_bpp) {
397379bc100SJani Nikula 	case 18:
3983e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_6_BPC;
399379bc100SJani Nikula 		break;
400379bc100SJani Nikula 	case 24:
4013e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_8_BPC;
402379bc100SJani Nikula 		break;
403379bc100SJani Nikula 	case 30:
4043e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_10_BPC;
405379bc100SJani Nikula 		break;
406379bc100SJani Nikula 	case 36:
4073e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_12_BPC;
408379bc100SJani Nikula 		break;
409379bc100SJani Nikula 	default:
410379bc100SJani Nikula 		MISSING_CASE(crtc_state->pipe_bpp);
411379bc100SJani Nikula 		break;
412379bc100SJani Nikula 	}
413379bc100SJani Nikula 
414cae154fcSVille Syrjälä 	/* nonsense combination */
4151de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, crtc_state->limited_color_range &&
416cae154fcSVille Syrjälä 		    crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
417cae154fcSVille Syrjälä 
418cae154fcSVille Syrjälä 	if (crtc_state->limited_color_range)
4193e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_CEA_RGB;
420cae154fcSVille Syrjälä 
421379bc100SJani Nikula 	/*
422379bc100SJani Nikula 	 * As per DP 1.2 spec section 2.3.4.3 while sending
423379bc100SJani Nikula 	 * YCBCR 444 signals we should program MSA MISC1/0 fields with
424646d3dc8SVille Syrjälä 	 * colorspace information.
425379bc100SJani Nikula 	 */
426379bc100SJani Nikula 	if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
4273e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
428646d3dc8SVille Syrjälä 
429379bc100SJani Nikula 	/*
430379bc100SJani Nikula 	 * As per DP 1.4a spec section 2.2.4.3 [MSA Field for Indication
431379bc100SJani Nikula 	 * of Color Encoding Format and Content Color Gamut] while sending
4320c06fa15SGwan-gyeong Mun 	 * YCBCR 420, HDR BT.2020 signals we should program MSA MISC1 fields
4330c06fa15SGwan-gyeong Mun 	 * which indicate VSC SDP for the Pixel Encoding/Colorimetry Format.
434379bc100SJani Nikula 	 */
435bd8c9ccaSGwan-gyeong Mun 	if (intel_dp_needs_vsc_sdp(crtc_state, conn_state))
4363e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_VSC_SDP;
4370c06fa15SGwan-gyeong Mun 
438f7960e7fSJani Nikula 	intel_de_write(dev_priv, TRANS_MSA_MISC(cpu_transcoder), temp);
439379bc100SJani Nikula }
440379bc100SJani Nikula 
441dc5b8ed5SVille Syrjälä static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder)
442dc5b8ed5SVille Syrjälä {
443dc5b8ed5SVille Syrjälä 	if (master_transcoder == TRANSCODER_EDP)
444dc5b8ed5SVille Syrjälä 		return 0;
445dc5b8ed5SVille Syrjälä 	else
446dc5b8ed5SVille Syrjälä 		return master_transcoder + 1;
447dc5b8ed5SVille Syrjälä }
448dc5b8ed5SVille Syrjälä 
44979ac2b1bSJani Nikula static void
45079ac2b1bSJani Nikula intel_ddi_config_transcoder_dp2(struct intel_encoder *encoder,
45179ac2b1bSJani Nikula 				const struct intel_crtc_state *crtc_state)
45279ac2b1bSJani Nikula {
45379ac2b1bSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
45479ac2b1bSJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
45579ac2b1bSJani Nikula 	u32 val = 0;
45679ac2b1bSJani Nikula 
45779ac2b1bSJani Nikula 	if (intel_dp_is_uhbr(crtc_state))
45879ac2b1bSJani Nikula 		val = TRANS_DP2_128B132B_CHANNEL_CODING;
45979ac2b1bSJani Nikula 
46079ac2b1bSJani Nikula 	intel_de_write(i915, TRANS_DP2_CTL(cpu_transcoder), val);
46179ac2b1bSJani Nikula }
46279ac2b1bSJani Nikula 
46399389390SJosé Roberto de Souza /*
46499389390SJosé Roberto de Souza  * Returns the TRANS_DDI_FUNC_CTL value based on CRTC state.
46599389390SJosé Roberto de Souza  *
46699389390SJosé Roberto de Souza  * Only intended to be used by intel_ddi_enable_transcoder_func() and
46799389390SJosé Roberto de Souza  * intel_ddi_config_transcoder_func().
46899389390SJosé Roberto de Souza  */
46999389390SJosé Roberto de Souza static u32
470eed22a46SVille Syrjälä intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
471eed22a46SVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
472379bc100SJani Nikula {
4732225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
474379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
475379bc100SJani Nikula 	enum pipe pipe = crtc->pipe;
476379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
477379bc100SJani Nikula 	enum port port = encoder->port;
478379bc100SJani Nikula 	u32 temp;
479379bc100SJani Nikula 
480379bc100SJani Nikula 	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
481379bc100SJani Nikula 	temp = TRANS_DDI_FUNC_ENABLE;
482005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
483df16b636SMahesh Kumar 		temp |= TGL_TRANS_DDI_SELECT_PORT(port);
484df16b636SMahesh Kumar 	else
485379bc100SJani Nikula 		temp |= TRANS_DDI_SELECT_PORT(port);
486379bc100SJani Nikula 
487379bc100SJani Nikula 	switch (crtc_state->pipe_bpp) {
48804514c14SJani Nikula 	default:
48904514c14SJani Nikula 		MISSING_CASE(crtc_state->pipe_bpp);
49004514c14SJani Nikula 		fallthrough;
491379bc100SJani Nikula 	case 18:
492379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_6;
493379bc100SJani Nikula 		break;
494379bc100SJani Nikula 	case 24:
495379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_8;
496379bc100SJani Nikula 		break;
497379bc100SJani Nikula 	case 30:
498379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_10;
499379bc100SJani Nikula 		break;
500379bc100SJani Nikula 	case 36:
501379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_12;
502379bc100SJani Nikula 		break;
503379bc100SJani Nikula 	}
504379bc100SJani Nikula 
5051326a92cSMaarten Lankhorst 	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
506379bc100SJani Nikula 		temp |= TRANS_DDI_PVSYNC;
5071326a92cSMaarten Lankhorst 	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
508379bc100SJani Nikula 		temp |= TRANS_DDI_PHSYNC;
509379bc100SJani Nikula 
510379bc100SJani Nikula 	if (cpu_transcoder == TRANSCODER_EDP) {
511379bc100SJani Nikula 		switch (pipe) {
51204514c14SJani Nikula 		default:
51304514c14SJani Nikula 			MISSING_CASE(pipe);
51404514c14SJani Nikula 			fallthrough;
515379bc100SJani Nikula 		case PIPE_A:
516379bc100SJani Nikula 			/* On Haswell, can only use the always-on power well for
517379bc100SJani Nikula 			 * eDP when not using the panel fitter, and when not
518379bc100SJani Nikula 			 * using motion blur mitigation (which we don't
519379bc100SJani Nikula 			 * support). */
520379bc100SJani Nikula 			if (crtc_state->pch_pfit.force_thru)
521379bc100SJani Nikula 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
522379bc100SJani Nikula 			else
523379bc100SJani Nikula 				temp |= TRANS_DDI_EDP_INPUT_A_ON;
524379bc100SJani Nikula 			break;
525379bc100SJani Nikula 		case PIPE_B:
526379bc100SJani Nikula 			temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
527379bc100SJani Nikula 			break;
528379bc100SJani Nikula 		case PIPE_C:
529379bc100SJani Nikula 			temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
530379bc100SJani Nikula 			break;
531379bc100SJani Nikula 		}
532379bc100SJani Nikula 	}
533379bc100SJani Nikula 
534379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
535379bc100SJani Nikula 		if (crtc_state->has_hdmi_sink)
536379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_HDMI;
537379bc100SJani Nikula 		else
538379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_DVI;
539379bc100SJani Nikula 
540379bc100SJani Nikula 		if (crtc_state->hdmi_scrambling)
541379bc100SJani Nikula 			temp |= TRANS_DDI_HDMI_SCRAMBLING;
542379bc100SJani Nikula 		if (crtc_state->hdmi_high_tmds_clock_ratio)
543379bc100SJani Nikula 			temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
544b66a8abaSAnkit Nautiyal 		if (DISPLAY_VER(dev_priv) >= 14)
545b66a8abaSAnkit Nautiyal 			temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
546379bc100SJani Nikula 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
5477bb97db8SJani Nikula 		temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
548379bc100SJani Nikula 		temp |= (crtc_state->fdi_lanes - 1) << 1;
549379bc100SJani Nikula 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
55065213594SJani Nikula 		if (intel_dp_is_uhbr(crtc_state))
55165213594SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
55265213594SJani Nikula 		else
553379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
554379bc100SJani Nikula 		temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
555b3545e08SLucas De Marchi 
556005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
5576671c367SJosé Roberto de Souza 			enum transcoder master;
5586671c367SJosé Roberto de Souza 
5596671c367SJosé Roberto de Souza 			master = crtc_state->mst_master_transcoder;
5601de143ccSPankaj Bharadiya 			drm_WARN_ON(&dev_priv->drm,
5611de143ccSPankaj Bharadiya 				    master == INVALID_TRANSCODER);
5626671c367SJosé Roberto de Souza 			temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master);
5636671c367SJosé Roberto de Souza 		}
564379bc100SJani Nikula 	} else {
565379bc100SJani Nikula 		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
566379bc100SJani Nikula 		temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
567379bc100SJani Nikula 	}
568379bc100SJani Nikula 
56993e7e61eSLucas De Marchi 	if (IS_DISPLAY_VER(dev_priv, 8, 10) &&
570dc5b8ed5SVille Syrjälä 	    crtc_state->master_transcoder != INVALID_TRANSCODER) {
571dc5b8ed5SVille Syrjälä 		u8 master_select =
572dc5b8ed5SVille Syrjälä 			bdw_trans_port_sync_master_select(crtc_state->master_transcoder);
573dc5b8ed5SVille Syrjälä 
574dc5b8ed5SVille Syrjälä 		temp |= TRANS_DDI_PORT_SYNC_ENABLE |
575dc5b8ed5SVille Syrjälä 			TRANS_DDI_PORT_SYNC_MASTER_SELECT(master_select);
576dc5b8ed5SVille Syrjälä 	}
577dc5b8ed5SVille Syrjälä 
57899389390SJosé Roberto de Souza 	return temp;
57999389390SJosé Roberto de Souza }
58099389390SJosé Roberto de Souza 
581eed22a46SVille Syrjälä void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
582eed22a46SVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
58399389390SJosé Roberto de Souza {
5842225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
58599389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
58699389390SJosé Roberto de Souza 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
58799389390SJosé Roberto de Souza 
588005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
589589a4cd6SVille Syrjälä 		enum transcoder master_transcoder = crtc_state->master_transcoder;
590589a4cd6SVille Syrjälä 		u32 ctl2 = 0;
591589a4cd6SVille Syrjälä 
592589a4cd6SVille Syrjälä 		if (master_transcoder != INVALID_TRANSCODER) {
593dc5b8ed5SVille Syrjälä 			u8 master_select =
594dc5b8ed5SVille Syrjälä 				bdw_trans_port_sync_master_select(master_transcoder);
595589a4cd6SVille Syrjälä 
596589a4cd6SVille Syrjälä 			ctl2 |= PORT_SYNC_MODE_ENABLE |
597d4d7d9caSVille Syrjälä 				PORT_SYNC_MODE_MASTER_SELECT(master_select);
598589a4cd6SVille Syrjälä 		}
599589a4cd6SVille Syrjälä 
600589a4cd6SVille Syrjälä 		intel_de_write(dev_priv,
601589a4cd6SVille Syrjälä 			       TRANS_DDI_FUNC_CTL2(cpu_transcoder), ctl2);
602589a4cd6SVille Syrjälä 	}
603589a4cd6SVille Syrjälä 
604580fbdc5SImre Deak 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
605580fbdc5SImre Deak 		       intel_ddi_transcoder_func_reg_val_get(encoder,
606580fbdc5SImre Deak 							     crtc_state));
60799389390SJosé Roberto de Souza }
60899389390SJosé Roberto de Souza 
60999389390SJosé Roberto de Souza /*
61099389390SJosé Roberto de Souza  * Same as intel_ddi_enable_transcoder_func(), but it does not set the enable
61199389390SJosé Roberto de Souza  * bit.
61299389390SJosé Roberto de Souza  */
61399389390SJosé Roberto de Souza static void
614eed22a46SVille Syrjälä intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
615eed22a46SVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
61699389390SJosé Roberto de Souza {
6172225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
61899389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
61999389390SJosé Roberto de Souza 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
620589a4cd6SVille Syrjälä 	u32 ctl;
62199389390SJosé Roberto de Souza 
622eed22a46SVille Syrjälä 	ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state);
623589a4cd6SVille Syrjälä 	ctl &= ~TRANS_DDI_FUNC_ENABLE;
624589a4cd6SVille Syrjälä 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl);
625379bc100SJani Nikula }
626379bc100SJani Nikula 
627379bc100SJani Nikula void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
628379bc100SJani Nikula {
6292225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
630379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
631379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
632589a4cd6SVille Syrjälä 	u32 ctl;
633c59053dcSJosé Roberto de Souza 
634005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
635589a4cd6SVille Syrjälä 		intel_de_write(dev_priv,
636589a4cd6SVille Syrjälä 			       TRANS_DDI_FUNC_CTL2(cpu_transcoder), 0);
637589a4cd6SVille Syrjälä 
638589a4cd6SVille Syrjälä 	ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
639dc5b8ed5SVille Syrjälä 
6401cfcdbf3SSean Paul 	drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING);
6411cfcdbf3SSean Paul 
642589a4cd6SVille Syrjälä 	ctl &= ~TRANS_DDI_FUNC_ENABLE;
643379bc100SJani Nikula 
64493e7e61eSLucas De Marchi 	if (IS_DISPLAY_VER(dev_priv, 8, 10))
645dc5b8ed5SVille Syrjälä 		ctl &= ~(TRANS_DDI_PORT_SYNC_ENABLE |
646dc5b8ed5SVille Syrjälä 			 TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK);
647dc5b8ed5SVille Syrjälä 
648005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
649919e4f07SJosé Roberto de Souza 		if (!intel_dp_mst_is_master_trans(crtc_state)) {
650589a4cd6SVille Syrjälä 			ctl &= ~(TGL_TRANS_DDI_PORT_MASK |
651919e4f07SJosé Roberto de Souza 				 TRANS_DDI_MODE_SELECT_MASK);
652919e4f07SJosé Roberto de Souza 		}
653df16b636SMahesh Kumar 	} else {
654589a4cd6SVille Syrjälä 		ctl &= ~(TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK);
655df16b636SMahesh Kumar 	}
656dc5b8ed5SVille Syrjälä 
657589a4cd6SVille Syrjälä 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl);
658379bc100SJani Nikula 
6590c82118bSJani Nikula 	if (intel_has_quirk(dev_priv, QUIRK_INCREASE_DDI_DISABLED_TIME) &&
660379bc100SJani Nikula 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
66147bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
66247bdb1caSJani Nikula 			    "Quirk Increase DDI disabled time\n");
663379bc100SJani Nikula 		/* Quirk time at 100ms for reliable operation */
664379bc100SJani Nikula 		msleep(100);
665379bc100SJani Nikula 	}
666379bc100SJani Nikula }
667379bc100SJani Nikula 
6681a67a168SAnshuman Gupta int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
6690b9c9290SSean Paul 			       enum transcoder cpu_transcoder,
6701a67a168SAnshuman Gupta 			       bool enable, u32 hdcp_mask)
671379bc100SJani Nikula {
672379bc100SJani Nikula 	struct drm_device *dev = intel_encoder->base.dev;
673379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
674379bc100SJani Nikula 	intel_wakeref_t wakeref;
675379bc100SJani Nikula 	int ret = 0;
676379bc100SJani Nikula 
677379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
678379bc100SJani Nikula 						     intel_encoder->power_domain);
6791de143ccSPankaj Bharadiya 	if (drm_WARN_ON(dev, !wakeref))
680379bc100SJani Nikula 		return -ENXIO;
681379bc100SJani Nikula 
6828910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
6838910d8b7SAndrzej Hajda 		     hdcp_mask, enable ? hdcp_mask : 0);
684379bc100SJani Nikula 	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
685379bc100SJani Nikula 	return ret;
686379bc100SJani Nikula }
687379bc100SJani Nikula 
688379bc100SJani Nikula bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
689379bc100SJani Nikula {
690379bc100SJani Nikula 	struct drm_device *dev = intel_connector->base.dev;
691379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
692fa7edcd2SVille Syrjälä 	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
693379bc100SJani Nikula 	int type = intel_connector->base.connector_type;
694379bc100SJani Nikula 	enum port port = encoder->port;
695379bc100SJani Nikula 	enum transcoder cpu_transcoder;
696379bc100SJani Nikula 	intel_wakeref_t wakeref;
697379bc100SJani Nikula 	enum pipe pipe = 0;
698379bc100SJani Nikula 	u32 tmp;
699379bc100SJani Nikula 	bool ret;
700379bc100SJani Nikula 
701379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
702379bc100SJani Nikula 						     encoder->power_domain);
703379bc100SJani Nikula 	if (!wakeref)
704379bc100SJani Nikula 		return false;
705379bc100SJani Nikula 
706379bc100SJani Nikula 	if (!encoder->get_hw_state(encoder, &pipe)) {
707379bc100SJani Nikula 		ret = false;
708379bc100SJani Nikula 		goto out;
709379bc100SJani Nikula 	}
710379bc100SJani Nikula 
71110cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
712379bc100SJani Nikula 		cpu_transcoder = TRANSCODER_EDP;
713379bc100SJani Nikula 	else
714379bc100SJani Nikula 		cpu_transcoder = (enum transcoder) pipe;
715379bc100SJani Nikula 
716f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
717379bc100SJani Nikula 
718379bc100SJani Nikula 	switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
719379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_HDMI:
720379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DVI:
721379bc100SJani Nikula 		ret = type == DRM_MODE_CONNECTOR_HDMIA;
722379bc100SJani Nikula 		break;
723379bc100SJani Nikula 
724379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_SST:
725379bc100SJani Nikula 		ret = type == DRM_MODE_CONNECTOR_eDP ||
726379bc100SJani Nikula 		      type == DRM_MODE_CONNECTOR_DisplayPort;
727379bc100SJani Nikula 		break;
728379bc100SJani Nikula 
729379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_MST:
730379bc100SJani Nikula 		/* if the transcoder is in MST state then
731379bc100SJani Nikula 		 * connector isn't connected */
732379bc100SJani Nikula 		ret = false;
733379bc100SJani Nikula 		break;
734379bc100SJani Nikula 
7357bb97db8SJani Nikula 	case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
73665213594SJani Nikula 		if (HAS_DP20(dev_priv))
73765213594SJani Nikula 			/* 128b/132b */
73865213594SJani Nikula 			ret = false;
73965213594SJani Nikula 		else
74065213594SJani Nikula 			/* FDI */
741379bc100SJani Nikula 			ret = type == DRM_MODE_CONNECTOR_VGA;
742379bc100SJani Nikula 		break;
743379bc100SJani Nikula 
744379bc100SJani Nikula 	default:
745379bc100SJani Nikula 		ret = false;
746379bc100SJani Nikula 		break;
747379bc100SJani Nikula 	}
748379bc100SJani Nikula 
749379bc100SJani Nikula out:
750379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
751379bc100SJani Nikula 
752379bc100SJani Nikula 	return ret;
753379bc100SJani Nikula }
754379bc100SJani Nikula 
755379bc100SJani Nikula static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
756379bc100SJani Nikula 					u8 *pipe_mask, bool *is_dp_mst)
757379bc100SJani Nikula {
758379bc100SJani Nikula 	struct drm_device *dev = encoder->base.dev;
759379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
760379bc100SJani Nikula 	enum port port = encoder->port;
761379bc100SJani Nikula 	intel_wakeref_t wakeref;
762379bc100SJani Nikula 	enum pipe p;
763379bc100SJani Nikula 	u32 tmp;
764379bc100SJani Nikula 	u8 mst_pipe_mask;
765379bc100SJani Nikula 
766379bc100SJani Nikula 	*pipe_mask = 0;
767379bc100SJani Nikula 	*is_dp_mst = false;
768379bc100SJani Nikula 
769379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
770379bc100SJani Nikula 						     encoder->power_domain);
771379bc100SJani Nikula 	if (!wakeref)
772379bc100SJani Nikula 		return;
773379bc100SJani Nikula 
774f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, DDI_BUF_CTL(port));
775379bc100SJani Nikula 	if (!(tmp & DDI_BUF_CTL_ENABLE))
776379bc100SJani Nikula 		goto out;
777379bc100SJani Nikula 
77810cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A) {
779f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv,
780f7960e7fSJani Nikula 				    TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
781379bc100SJani Nikula 
782379bc100SJani Nikula 		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
783379bc100SJani Nikula 		default:
784379bc100SJani Nikula 			MISSING_CASE(tmp & TRANS_DDI_EDP_INPUT_MASK);
785df561f66SGustavo A. R. Silva 			fallthrough;
786379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ON:
787379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ONOFF:
788379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_A);
789379bc100SJani Nikula 			break;
790379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_B_ONOFF:
791379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_B);
792379bc100SJani Nikula 			break;
793379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_C_ONOFF:
794379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_C);
795379bc100SJani Nikula 			break;
796379bc100SJani Nikula 		}
797379bc100SJani Nikula 
798379bc100SJani Nikula 		goto out;
799379bc100SJani Nikula 	}
800379bc100SJani Nikula 
801379bc100SJani Nikula 	mst_pipe_mask = 0;
802379bc100SJani Nikula 	for_each_pipe(dev_priv, p) {
803379bc100SJani Nikula 		enum transcoder cpu_transcoder = (enum transcoder)p;
804df16b636SMahesh Kumar 		unsigned int port_mask, ddi_select;
8056aa3bef1SJosé Roberto de Souza 		intel_wakeref_t trans_wakeref;
8066aa3bef1SJosé Roberto de Souza 
8076aa3bef1SJosé Roberto de Souza 		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
8086aa3bef1SJosé Roberto de Souza 								   POWER_DOMAIN_TRANSCODER(cpu_transcoder));
8096aa3bef1SJosé Roberto de Souza 		if (!trans_wakeref)
8106aa3bef1SJosé Roberto de Souza 			continue;
811df16b636SMahesh Kumar 
812005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
813df16b636SMahesh Kumar 			port_mask = TGL_TRANS_DDI_PORT_MASK;
814df16b636SMahesh Kumar 			ddi_select = TGL_TRANS_DDI_SELECT_PORT(port);
815df16b636SMahesh Kumar 		} else {
816df16b636SMahesh Kumar 			port_mask = TRANS_DDI_PORT_MASK;
817df16b636SMahesh Kumar 			ddi_select = TRANS_DDI_SELECT_PORT(port);
818df16b636SMahesh Kumar 		}
819379bc100SJani Nikula 
820f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv,
821f7960e7fSJani Nikula 				    TRANS_DDI_FUNC_CTL(cpu_transcoder));
8226aa3bef1SJosé Roberto de Souza 		intel_display_power_put(dev_priv, POWER_DOMAIN_TRANSCODER(cpu_transcoder),
8236aa3bef1SJosé Roberto de Souza 					trans_wakeref);
824379bc100SJani Nikula 
825df16b636SMahesh Kumar 		if ((tmp & port_mask) != ddi_select)
826379bc100SJani Nikula 			continue;
827379bc100SJani Nikula 
82865213594SJani Nikula 		if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST ||
82965213594SJani Nikula 		    (HAS_DP20(dev_priv) &&
83065213594SJani Nikula 		     (tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B))
831379bc100SJani Nikula 			mst_pipe_mask |= BIT(p);
832379bc100SJani Nikula 
833379bc100SJani Nikula 		*pipe_mask |= BIT(p);
834379bc100SJani Nikula 	}
835379bc100SJani Nikula 
836379bc100SJani Nikula 	if (!*pipe_mask)
83747bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
83847bdb1caSJani Nikula 			    "No pipe for [ENCODER:%d:%s] found\n",
83966a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name);
840379bc100SJani Nikula 
841379bc100SJani Nikula 	if (!mst_pipe_mask && hweight8(*pipe_mask) > 1) {
84247bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
84347bdb1caSJani Nikula 			    "Multiple pipes for [ENCODER:%d:%s] (pipe_mask %02x)\n",
84466a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name,
84566a990ddSVille Syrjälä 			    *pipe_mask);
846379bc100SJani Nikula 		*pipe_mask = BIT(ffs(*pipe_mask) - 1);
847379bc100SJani Nikula 	}
848379bc100SJani Nikula 
849379bc100SJani Nikula 	if (mst_pipe_mask && mst_pipe_mask != *pipe_mask)
85047bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
85147bdb1caSJani Nikula 			    "Conflicting MST and non-MST state for [ENCODER:%d:%s] (pipe_mask %02x mst_pipe_mask %02x)\n",
85266a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name,
85366a990ddSVille Syrjälä 			    *pipe_mask, mst_pipe_mask);
854379bc100SJani Nikula 	else
855379bc100SJani Nikula 		*is_dp_mst = mst_pipe_mask;
856379bc100SJani Nikula 
857379bc100SJani Nikula out:
8582446e1d6SMatt Roper 	if (*pipe_mask && (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))) {
859f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv, BXT_PHY_CTL(port));
860379bc100SJani Nikula 		if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
861379bc100SJani Nikula 			    BXT_PHY_LANE_POWERDOWN_ACK |
862379bc100SJani Nikula 			    BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED)
86347bdb1caSJani Nikula 			drm_err(&dev_priv->drm,
86447bdb1caSJani Nikula 				"[ENCODER:%d:%s] enabled but PHY powered down? (PHY_CTL %08x)\n",
86547bdb1caSJani Nikula 				encoder->base.base.id, encoder->base.name, tmp);
866379bc100SJani Nikula 	}
867379bc100SJani Nikula 
868379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
869379bc100SJani Nikula }
870379bc100SJani Nikula 
871379bc100SJani Nikula bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
872379bc100SJani Nikula 			    enum pipe *pipe)
873379bc100SJani Nikula {
874379bc100SJani Nikula 	u8 pipe_mask;
875379bc100SJani Nikula 	bool is_mst;
876379bc100SJani Nikula 
877379bc100SJani Nikula 	intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
878379bc100SJani Nikula 
879379bc100SJani Nikula 	if (is_mst || !pipe_mask)
880379bc100SJani Nikula 		return false;
881379bc100SJani Nikula 
882379bc100SJani Nikula 	*pipe = ffs(pipe_mask) - 1;
883379bc100SJani Nikula 
884379bc100SJani Nikula 	return true;
885379bc100SJani Nikula }
886379bc100SJani Nikula 
88781b55ef1SJani Nikula static enum intel_display_power_domain
888637c7aa2SImre Deak intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port,
889637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
890379bc100SJani Nikula {
891f645cbdaSImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
892637c7aa2SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
893f645cbdaSImre Deak 
894637c7aa2SImre Deak 	/*
895637c7aa2SImre Deak 	 * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
896379bc100SJani Nikula 	 * DC states enabled at the same time, while for driver initiated AUX
897379bc100SJani Nikula 	 * transfers we need the same AUX IOs to be powered but with DC states
898637c7aa2SImre Deak 	 * disabled. Accordingly use the AUX_IO_<port> power domain here which
899637c7aa2SImre Deak 	 * leaves DC states enabled.
900637c7aa2SImre Deak 	 *
901637c7aa2SImre Deak 	 * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require
902637c7aa2SImre Deak 	 * AUX IO to be enabled, but all these require DC_OFF to be enabled as
903637c7aa2SImre Deak 	 * well, so we can acquire a wider AUX_<port> power domain reference
904637c7aa2SImre Deak 	 * instead of a specific AUX_IO_<port> reference without powering up any
905637c7aa2SImre Deak 	 * extra wells.
906379bc100SJani Nikula 	 */
907f645cbdaSImre Deak 	if (intel_encoder_can_psr(&dig_port->base))
908f645cbdaSImre Deak 		return intel_display_power_aux_io_domain(i915, dig_port->aux_ch);
9091acefacaSImre Deak 	else if (DISPLAY_VER(i915) < 14 &&
9101acefacaSImre Deak 		 (intel_crtc_has_dp_encoder(crtc_state) ||
9111acefacaSImre Deak 		  intel_phy_is_tc(i915, phy)))
912b2e00dd3SImre Deak 		return intel_aux_power_domain(dig_port);
913637c7aa2SImre Deak 	else
914637c7aa2SImre Deak 		return POWER_DOMAIN_INVALID;
915637c7aa2SImre Deak }
916637c7aa2SImre Deak 
917637c7aa2SImre Deak static void
918637c7aa2SImre Deak main_link_aux_power_domain_get(struct intel_digital_port *dig_port,
919637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
920637c7aa2SImre Deak {
921637c7aa2SImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
922637c7aa2SImre Deak 	enum intel_display_power_domain domain =
923637c7aa2SImre Deak 		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
924637c7aa2SImre Deak 
925637c7aa2SImre Deak 	drm_WARN_ON(&i915->drm, dig_port->aux_wakeref);
926637c7aa2SImre Deak 
927637c7aa2SImre Deak 	if (domain == POWER_DOMAIN_INVALID)
928637c7aa2SImre Deak 		return;
929637c7aa2SImre Deak 
930637c7aa2SImre Deak 	dig_port->aux_wakeref = intel_display_power_get(i915, domain);
931637c7aa2SImre Deak }
932637c7aa2SImre Deak 
933637c7aa2SImre Deak static void
934637c7aa2SImre Deak main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
935637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
936637c7aa2SImre Deak {
937637c7aa2SImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
938637c7aa2SImre Deak 	enum intel_display_power_domain domain =
939637c7aa2SImre Deak 		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
940637c7aa2SImre Deak 	intel_wakeref_t wf;
941637c7aa2SImre Deak 
942637c7aa2SImre Deak 	wf = fetch_and_zero(&dig_port->aux_wakeref);
943637c7aa2SImre Deak 	if (!wf)
944637c7aa2SImre Deak 		return;
945637c7aa2SImre Deak 
946637c7aa2SImre Deak 	intel_display_power_put(i915, domain, wf);
947379bc100SJani Nikula }
948379bc100SJani Nikula 
949379bc100SJani Nikula static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
950379bc100SJani Nikula 					struct intel_crtc_state *crtc_state)
951379bc100SJani Nikula {
952379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
953379bc100SJani Nikula 	struct intel_digital_port *dig_port;
954379bc100SJani Nikula 
955379bc100SJani Nikula 	/*
956379bc100SJani Nikula 	 * TODO: Add support for MST encoders. Atm, the following should never
957379bc100SJani Nikula 	 * happen since fake-MST encoders don't set their get_power_domains()
958379bc100SJani Nikula 	 * hook.
959379bc100SJani Nikula 	 */
9601de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
9611de143ccSPankaj Bharadiya 			intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
962379bc100SJani Nikula 		return;
963379bc100SJani Nikula 
964b7d02c3aSVille Syrjälä 	dig_port = enc_to_dig_port(encoder);
965f77a2db2SImre Deak 
96611a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
967a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
968a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
969f77a2db2SImre Deak 								   dig_port->ddi_io_power_domain);
970a4550977SImre Deak 	}
971379bc100SJani Nikula 
972637c7aa2SImre Deak 	main_link_aux_power_domain_get(dig_port, crtc_state);
973162e68e1SImre Deak }
974379bc100SJani Nikula 
97555a4679eSVille Syrjälä void intel_ddi_enable_transcoder_clock(struct intel_encoder *encoder,
97602a715c3SVille Syrjälä 				       const struct intel_crtc_state *crtc_state)
977379bc100SJani Nikula {
9782225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
979379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
980379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
981ed2615a8SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
982ed2615a8SMatt Roper 	u32 val;
983379bc100SJani Nikula 
98448630a31SVille Syrjälä 	if (cpu_transcoder == TRANSCODER_EDP)
98548630a31SVille Syrjälä 		return;
98648630a31SVille Syrjälä 
987ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
988ed2615a8SMatt Roper 		val = TGL_TRANS_CLK_SEL_PORT(phy);
989ed2615a8SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
990ed2615a8SMatt Roper 		val = TGL_TRANS_CLK_SEL_PORT(encoder->port);
991df16b636SMahesh Kumar 	else
992ed2615a8SMatt Roper 		val = TRANS_CLK_SEL_PORT(encoder->port);
993ed2615a8SMatt Roper 
994ed2615a8SMatt Roper 	intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
995379bc100SJani Nikula }
996379bc100SJani Nikula 
99755a4679eSVille Syrjälä void intel_ddi_disable_transcoder_clock(const struct intel_crtc_state *crtc_state)
998379bc100SJani Nikula {
9992225f3c6SMaarten Lankhorst 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1000379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
100148630a31SVille Syrjälä 	u32 val;
1002379bc100SJani Nikula 
100348630a31SVille Syrjälä 	if (cpu_transcoder == TRANSCODER_EDP)
100448630a31SVille Syrjälä 		return;
100548630a31SVille Syrjälä 
1006005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
100748630a31SVille Syrjälä 		val = TGL_TRANS_CLK_SEL_DISABLED;
1008df16b636SMahesh Kumar 	else
100948630a31SVille Syrjälä 		val = TRANS_CLK_SEL_DISABLED;
101048630a31SVille Syrjälä 
101148630a31SVille Syrjälä 	intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
1012df16b636SMahesh Kumar }
1013379bc100SJani Nikula 
1014379bc100SJani Nikula static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
1015379bc100SJani Nikula 				enum port port, u8 iboost)
1016379bc100SJani Nikula {
1017379bc100SJani Nikula 	u32 tmp;
1018379bc100SJani Nikula 
1019f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, DISPIO_CR_TX_BMU_CR0);
1020379bc100SJani Nikula 	tmp &= ~(BALANCE_LEG_MASK(port) | BALANCE_LEG_DISABLE(port));
1021379bc100SJani Nikula 	if (iboost)
1022379bc100SJani Nikula 		tmp |= iboost << BALANCE_LEG_SHIFT(port);
1023379bc100SJani Nikula 	else
1024379bc100SJani Nikula 		tmp |= BALANCE_LEG_DISABLE(port);
1025f7960e7fSJani Nikula 	intel_de_write(dev_priv, DISPIO_CR_TX_BMU_CR0, tmp);
1026379bc100SJani Nikula }
1027379bc100SJani Nikula 
1028379bc100SJani Nikula static void skl_ddi_set_iboost(struct intel_encoder *encoder,
1029a621860aSVille Syrjälä 			       const struct intel_crtc_state *crtc_state,
1030a621860aSVille Syrjälä 			       int level)
1031379bc100SJani Nikula {
10327801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1033379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1034379bc100SJani Nikula 	u8 iboost;
1035379bc100SJani Nikula 
1036a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
103702107ef1SVille Syrjälä 		iboost = intel_bios_hdmi_boost_level(encoder->devdata);
1038379bc100SJani Nikula 	else
103902107ef1SVille Syrjälä 		iboost = intel_bios_dp_boost_level(encoder->devdata);
1040379bc100SJani Nikula 
1041379bc100SJani Nikula 	if (iboost == 0) {
1042e505d764SVille Syrjälä 		const struct intel_ddi_buf_trans *trans;
1043379bc100SJani Nikula 		int n_entries;
1044379bc100SJani Nikula 
1045e505d764SVille Syrjälä 		trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1046e505d764SVille Syrjälä 		if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
1047379bc100SJani Nikula 			return;
1048379bc100SJani Nikula 
1049e505d764SVille Syrjälä 		iboost = trans->entries[level].hsw.i_boost;
1050379bc100SJani Nikula 	}
1051379bc100SJani Nikula 
1052379bc100SJani Nikula 	/* Make sure that the requested I_boost is valid */
1053379bc100SJani Nikula 	if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) {
105447bdb1caSJani Nikula 		drm_err(&dev_priv->drm, "Invalid I_boost value %u\n", iboost);
1055379bc100SJani Nikula 		return;
1056379bc100SJani Nikula 	}
1057379bc100SJani Nikula 
1058f0e86e05SJosé Roberto de Souza 	_skl_ddi_set_iboost(dev_priv, encoder->port, iboost);
1059379bc100SJani Nikula 
1060f0e86e05SJosé Roberto de Souza 	if (encoder->port == PORT_A && dig_port->max_lanes == 4)
1061379bc100SJani Nikula 		_skl_ddi_set_iboost(dev_priv, PORT_E, iboost);
1062379bc100SJani Nikula }
1063379bc100SJani Nikula 
1064a621860aSVille Syrjälä static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
1065a621860aSVille Syrjälä 				   const struct intel_crtc_state *crtc_state)
1066379bc100SJani Nikula {
106753de0a20SVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
1068379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1069379bc100SJani Nikula 	int n_entries;
1070379bc100SJani Nikula 
1071c40a253bSVille Syrjälä 	encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1072379bc100SJani Nikula 
10731de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, n_entries < 1))
1074379bc100SJani Nikula 		n_entries = 1;
10751de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
10761de143ccSPankaj Bharadiya 			n_entries > ARRAY_SIZE(index_to_dp_signal_levels)))
1077379bc100SJani Nikula 		n_entries = ARRAY_SIZE(index_to_dp_signal_levels);
1078379bc100SJani Nikula 
1079379bc100SJani Nikula 	return index_to_dp_signal_levels[n_entries - 1] &
1080379bc100SJani Nikula 		DP_TRAIN_VOLTAGE_SWING_MASK;
1081379bc100SJani Nikula }
1082379bc100SJani Nikula 
1083379bc100SJani Nikula /*
1084379bc100SJani Nikula  * We assume that the full set of pre-emphasis values can be
1085379bc100SJani Nikula  * used on all DDI platforms. Should that change we need to
1086379bc100SJani Nikula  * rethink this code.
1087379bc100SJani Nikula  */
108853de0a20SVille Syrjälä static u8 intel_ddi_dp_preemph_max(struct intel_dp *intel_dp)
1089379bc100SJani Nikula {
1090379bc100SJani Nikula 	return DP_TRAIN_PRE_EMPH_LEVEL_3;
1091379bc100SJani Nikula }
1092379bc100SJani Nikula 
10935e7fe4d9SVille Syrjälä static u32 icl_combo_phy_loadgen_select(const struct intel_crtc_state *crtc_state,
10945e7fe4d9SVille Syrjälä 					int lane)
10955e7fe4d9SVille Syrjälä {
10965e7fe4d9SVille Syrjälä 	if (crtc_state->port_clock > 600000)
10975e7fe4d9SVille Syrjälä 		return 0;
10985e7fe4d9SVille Syrjälä 
10995e7fe4d9SVille Syrjälä 	if (crtc_state->lane_count == 4)
11005e7fe4d9SVille Syrjälä 		return lane >= 1 ? LOADGEN_SELECT : 0;
11015e7fe4d9SVille Syrjälä 	else
11025e7fe4d9SVille Syrjälä 		return lane == 1 || lane == 2 ? LOADGEN_SELECT : 0;
11035e7fe4d9SVille Syrjälä }
11045e7fe4d9SVille Syrjälä 
1105a8143150SJosé Roberto de Souza static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
1106193299adSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
1107379bc100SJani Nikula {
1108a8143150SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1109e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1110f0e86e05SJosé Roberto de Souza 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
1111a621860aSVille Syrjälä 	int n_entries, ln;
1112a621860aSVille Syrjälä 	u32 val;
1113379bc100SJani Nikula 
1114e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1115e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
111685da0292SVille Syrjälä 		return;
1117379bc100SJani Nikula 
1118a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
111981619f4aSJosé Roberto de Souza 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
112081619f4aSJosé Roberto de Souza 
112181619f4aSJosé Roberto de Souza 		val = EDP4K2K_MODE_OVRD_EN | EDP4K2K_MODE_OVRD_OPTIMIZED;
1122e505d764SVille Syrjälä 		intel_dp->hobl_active = is_hobl_buf_trans(trans);
112381619f4aSJosé Roberto de Souza 		intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy), val,
112481619f4aSJosé Roberto de Souza 			     intel_dp->hobl_active ? val : 0);
112581619f4aSJosé Roberto de Souza 	}
112681619f4aSJosé Roberto de Souza 
1127379bc100SJani Nikula 	/* Set PORT_TX_DW5 */
1128e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1129379bc100SJani Nikula 	val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
1130379bc100SJani Nikula 		  TAP2_DISABLE | TAP3_DISABLE);
1131379bc100SJani Nikula 	val |= SCALING_MODE_SEL(0x2);
1132379bc100SJani Nikula 	val |= RTERM_SELECT(0x6);
1133379bc100SJani Nikula 	val |= TAP3_DISABLE;
1134f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1135379bc100SJani Nikula 
1136379bc100SJani Nikula 	/* Program PORT_TX_DW2 */
1137f20ca899SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
113831e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
113931e914a2SVille Syrjälä 
1140c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy),
1141c1d53cbdSVille Syrjälä 			     SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK | RCOMP_SCALAR_MASK,
1142c1d53cbdSVille Syrjälä 			     SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel) |
1143c1d53cbdSVille Syrjälä 			     SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel) |
1144c1d53cbdSVille Syrjälä 			     RCOMP_SCALAR(0x98));
1145f20ca899SVille Syrjälä 	}
1146379bc100SJani Nikula 
1147379bc100SJani Nikula 	/* Program PORT_TX_DW4 */
1148379bc100SJani Nikula 	/* We cannot write to GRP. It would overwrite individual loadgen. */
1149a1f01768SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
115031e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
115131e914a2SVille Syrjälä 
1152c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1153c1d53cbdSVille Syrjälä 			     POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK,
1154c1d53cbdSVille Syrjälä 			     POST_CURSOR_1(trans->entries[level].icl.dw4_post_cursor_1) |
1155c1d53cbdSVille Syrjälä 			     POST_CURSOR_2(trans->entries[level].icl.dw4_post_cursor_2) |
1156c1d53cbdSVille Syrjälä 			     CURSOR_COEFF(trans->entries[level].icl.dw4_cursor_coeff));
1157379bc100SJani Nikula 	}
1158379bc100SJani Nikula 
1159379bc100SJani Nikula 	/* Program PORT_TX_DW7 */
1160f20ca899SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
116131e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
116231e914a2SVille Syrjälä 
1163c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy),
1164c1d53cbdSVille Syrjälä 			     N_SCALAR_MASK,
1165c1d53cbdSVille Syrjälä 			     N_SCALAR(trans->entries[level].icl.dw7_n_scalar));
1166f20ca899SVille Syrjälä 	}
1167379bc100SJani Nikula }
1168379bc100SJani Nikula 
1169193299adSVille Syrjälä static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder,
1170193299adSVille Syrjälä 					    const struct intel_crtc_state *crtc_state)
1171379bc100SJani Nikula {
1172379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1173dc867bc7SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
1174379bc100SJani Nikula 	u32 val;
11755e7fe4d9SVille Syrjälä 	int ln;
1176379bc100SJani Nikula 
1177379bc100SJani Nikula 	/*
1178379bc100SJani Nikula 	 * 1. If port type is eDP or DP,
1179379bc100SJani Nikula 	 * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
1180379bc100SJani Nikula 	 * else clear to 0b.
1181379bc100SJani Nikula 	 */
1182e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
1183a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1184379bc100SJani Nikula 		val &= ~COMMON_KEEPER_EN;
1185379bc100SJani Nikula 	else
1186379bc100SJani Nikula 		val |= COMMON_KEEPER_EN;
1187f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
1188379bc100SJani Nikula 
1189379bc100SJani Nikula 	/* 2. Program loadgen select */
1190379bc100SJani Nikula 	/*
1191e6908588SVille Syrjälä 	 * Program PORT_TX_DW4 depending on Bit rate and used lanes
1192379bc100SJani Nikula 	 * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
1193379bc100SJani Nikula 	 * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
1194379bc100SJani Nikula 	 * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
1195379bc100SJani Nikula 	 */
1196a1f01768SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
1197c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1198c1d53cbdSVille Syrjälä 			     LOADGEN_SELECT,
1199c1d53cbdSVille Syrjälä 			     icl_combo_phy_loadgen_select(crtc_state, ln));
1200379bc100SJani Nikula 	}
1201379bc100SJani Nikula 
1202379bc100SJani Nikula 	/* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
1203c1d53cbdSVille Syrjälä 	intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy),
1204c1d53cbdSVille Syrjälä 		     0, SUS_CLOCK_CONFIG);
1205379bc100SJani Nikula 
1206379bc100SJani Nikula 	/* 4. Clear training enable to change swing values */
1207e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1208379bc100SJani Nikula 	val &= ~TX_TRAINING_EN;
1209f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1210379bc100SJani Nikula 
1211379bc100SJani Nikula 	/* 5. Program swing and de-emphasis */
1212193299adSVille Syrjälä 	icl_ddi_combo_vswing_program(encoder, crtc_state);
1213379bc100SJani Nikula 
1214379bc100SJani Nikula 	/* 6. Set training enable to trigger update */
1215e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1216379bc100SJani Nikula 	val |= TX_TRAINING_EN;
1217f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1218379bc100SJani Nikula }
1219379bc100SJani Nikula 
1220193299adSVille Syrjälä static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder,
1221193299adSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
1222379bc100SJani Nikula {
1223379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1224f21e8b80SJosé Roberto de Souza 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
1225e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1226a621860aSVille Syrjälä 	int n_entries, ln;
1227379bc100SJani Nikula 
122811a89708SImre Deak 	if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1229f8c6b615SVille Syrjälä 		return;
1230f8c6b615SVille Syrjälä 
1231e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1232e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
123385da0292SVille Syrjälä 		return;
1234379bc100SJani Nikula 
1235379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1236d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port),
1237d4e0f163SVille Syrjälä 			     CRI_USE_FS32, 0);
1238d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port),
1239d4e0f163SVille Syrjälä 			     CRI_USE_FS32, 0);
1240379bc100SJani Nikula 	}
1241379bc100SJani Nikula 
1242379bc100SJani Nikula 	/* Program MG_TX_SWINGCTRL with values from vswing table */
1243379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1244305448e5SVille Syrjälä 		int level;
1245305448e5SVille Syrjälä 
1246305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1247305448e5SVille Syrjälä 
1248d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port),
1249d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1250d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1251379bc100SJani Nikula 
1252305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1253305448e5SVille Syrjälä 
1254d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port),
1255d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1256d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1257379bc100SJani Nikula 	}
1258379bc100SJani Nikula 
1259379bc100SJani Nikula 	/* Program MG_TX_DRVCTRL with values from vswing table */
1260379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1261305448e5SVille Syrjälä 		int level;
1262305448e5SVille Syrjälä 
1263305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1264305448e5SVille Syrjälä 
1265d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_DRVCTRL(ln, tc_port),
1266d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1267d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1268d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1269d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1270d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_EN);
1271379bc100SJani Nikula 
1272305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1273305448e5SVille Syrjälä 
1274d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_DRVCTRL(ln, tc_port),
1275d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1276d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1277d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1278d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1279d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_EN);
1280379bc100SJani Nikula 
1281379bc100SJani Nikula 		/* FIXME: Program CRI_LOADGEN_SEL after the spec is updated */
1282379bc100SJani Nikula 	}
1283379bc100SJani Nikula 
1284379bc100SJani Nikula 	/*
1285379bc100SJani Nikula 	 * Program MG_CLKHUB<LN, port being used> with value from frequency table
1286379bc100SJani Nikula 	 * In case of Legacy mode on MG PHY, both TX1 and TX2 enabled so use the
1287379bc100SJani Nikula 	 * values from table for which TX1 and TX2 enabled.
1288379bc100SJani Nikula 	 */
1289379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1290d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_CLKHUB(ln, tc_port),
1291d4e0f163SVille Syrjälä 			     CFG_LOW_RATE_LKREN_EN,
1292d4e0f163SVille Syrjälä 			     crtc_state->port_clock < 300000 ? CFG_LOW_RATE_LKREN_EN : 0);
1293379bc100SJani Nikula 	}
1294379bc100SJani Nikula 
1295379bc100SJani Nikula 	/* Program the MG_TX_DCC<LN, port being used> based on the link frequency */
1296379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1297d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_DCC(ln, tc_port),
1298d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1299d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN,
1300d4e0f163SVille Syrjälä 			     crtc_state->port_clock > 500000 ?
1301d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1302d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1303379bc100SJani Nikula 
1304d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_DCC(ln, tc_port),
1305d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1306d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN,
1307d4e0f163SVille Syrjälä 			     crtc_state->port_clock > 500000 ?
1308d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1309d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1310379bc100SJani Nikula 	}
1311379bc100SJani Nikula 
1312379bc100SJani Nikula 	/* Program MG_TX_PISO_READLOAD with values from vswing table */
1313379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1314d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_PISO_READLOAD(ln, tc_port),
1315d4e0f163SVille Syrjälä 			     0, CRI_CALCINIT);
1316d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_PISO_READLOAD(ln, tc_port),
1317d4e0f163SVille Syrjälä 			     0, CRI_CALCINIT);
1318379bc100SJani Nikula 	}
1319379bc100SJani Nikula }
1320379bc100SJani Nikula 
1321193299adSVille Syrjälä static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
1322193299adSVille Syrjälä 					  const struct intel_crtc_state *crtc_state)
1323978c3e53SClinton A Taylor {
1324978c3e53SClinton A Taylor 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1325978c3e53SClinton A Taylor 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
1326e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1327a621860aSVille Syrjälä 	int n_entries, ln;
1328978c3e53SClinton A Taylor 
132911a89708SImre Deak 	if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1330f8c6b615SVille Syrjälä 		return;
1331f8c6b615SVille Syrjälä 
1332e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1333e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
133485da0292SVille Syrjälä 		return;
1335978c3e53SClinton A Taylor 
1336978c3e53SClinton A Taylor 	for (ln = 0; ln < 2; ln++) {
1337a905ced6SVille Syrjälä 		int level;
1338a905ced6SVille Syrjälä 
1339b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0);
13402d69c42eSJosé Roberto de Souza 
1341a905ced6SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1342a905ced6SVille Syrjälä 
1343b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln),
1344c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF_MASK |
1345a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1346c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL_MASK,
1347c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1348a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1349c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1350978c3e53SClinton A Taylor 
1351a905ced6SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1352a905ced6SVille Syrjälä 
1353b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln),
1354c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF_MASK |
1355a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1356c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL_MASK,
1357c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1358a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1359c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1360978c3e53SClinton A Taylor 
1361b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
1362c86e1873SVille Syrjälä 				  DKL_TX_DP20BITMODE, 0);
13635ff59dddSJosé Roberto de Souza 
13645ff59dddSJosé Roberto de Souza 		if (IS_ALDERLAKE_P(dev_priv)) {
13655ff59dddSJosé Roberto de Souza 			u32 val;
13665ff59dddSJosé Roberto de Souza 
13675ff59dddSJosé Roberto de Souza 			if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
13685ff59dddSJosé Roberto de Souza 				if (ln == 0) {
13695ff59dddSJosé Roberto de Souza 					val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13705ff59dddSJosé Roberto de Souza 					val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(2);
13715ff59dddSJosé Roberto de Souza 				} else {
13725ff59dddSJosé Roberto de Souza 					val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(3);
13735ff59dddSJosé Roberto de Souza 					val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(3);
13745ff59dddSJosé Roberto de Souza 				}
13755ff59dddSJosé Roberto de Souza 			} else {
13765ff59dddSJosé Roberto de Souza 				val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13775ff59dddSJosé Roberto de Souza 				val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0);
13785ff59dddSJosé Roberto de Souza 			}
13795ff59dddSJosé Roberto de Souza 
1380b8ed5533SImre Deak 			intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
13815ff59dddSJosé Roberto de Souza 					  DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
13825ff59dddSJosé Roberto de Souza 					  DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
13835ff59dddSJosé Roberto de Souza 					  val);
13845ff59dddSJosé Roberto de Souza 		}
1385978c3e53SClinton A Taylor 	}
1386978c3e53SClinton A Taylor }
1387978c3e53SClinton A Taylor 
1388a621860aSVille Syrjälä static int translate_signal_level(struct intel_dp *intel_dp,
1389a621860aSVille Syrjälä 				  u8 signal_levels)
1390379bc100SJani Nikula {
13918b4f2137SPankaj Bharadiya 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
1392379bc100SJani Nikula 	int i;
1393379bc100SJani Nikula 
1394379bc100SJani Nikula 	for (i = 0; i < ARRAY_SIZE(index_to_dp_signal_levels); i++) {
1395379bc100SJani Nikula 		if (index_to_dp_signal_levels[i] == signal_levels)
1396379bc100SJani Nikula 			return i;
1397379bc100SJani Nikula 	}
1398379bc100SJani Nikula 
13998b4f2137SPankaj Bharadiya 	drm_WARN(&i915->drm, 1,
14008b4f2137SPankaj Bharadiya 		 "Unsupported voltage swing/pre-emphasis level: 0x%x\n",
1401379bc100SJani Nikula 		 signal_levels);
1402379bc100SJani Nikula 
1403379bc100SJani Nikula 	return 0;
1404379bc100SJani Nikula }
1405379bc100SJani Nikula 
14065c31e9d0SJani Nikula static int intel_ddi_dp_level(struct intel_dp *intel_dp,
14075c31e9d0SJani Nikula 			      const struct intel_crtc_state *crtc_state,
14085c31e9d0SJani Nikula 			      int lane)
1409379bc100SJani Nikula {
1410d0920a45SVille Syrjälä 	u8 train_set = intel_dp->train_set[lane];
14115c31e9d0SJani Nikula 
14125c31e9d0SJani Nikula 	if (intel_dp_is_uhbr(crtc_state)) {
14135c31e9d0SJani Nikula 		return train_set & DP_TX_FFE_PRESET_VALUE_MASK;
14145c31e9d0SJani Nikula 	} else {
1415a621860aSVille Syrjälä 		u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
1416379bc100SJani Nikula 						DP_TRAIN_PRE_EMPHASIS_MASK);
1417379bc100SJani Nikula 
14188b4f2137SPankaj Bharadiya 		return translate_signal_level(intel_dp, signal_levels);
1419379bc100SJani Nikula 	}
14205c31e9d0SJani Nikula }
1421379bc100SJani Nikula 
1422193299adSVille Syrjälä int intel_ddi_level(struct intel_encoder *encoder,
1423d0920a45SVille Syrjälä 		    const struct intel_crtc_state *crtc_state,
1424d0920a45SVille Syrjälä 		    int lane)
1425a046a0daSMatt Roper {
14262c63e0f9SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
14272c63e0f9SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
14282c63e0f9SVille Syrjälä 	int level, n_entries;
14292c63e0f9SVille Syrjälä 
14302c63e0f9SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
14312c63e0f9SVille Syrjälä 	if (drm_WARN_ON_ONCE(&i915->drm, !trans))
14322c63e0f9SVille Syrjälä 		return 0;
14332c63e0f9SVille Syrjälä 
1434e722ab8bSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
14353e022c1fSVille Syrjälä 		level = intel_ddi_hdmi_level(encoder, trans);
1436e722ab8bSVille Syrjälä 	else
14375c31e9d0SJani Nikula 		level = intel_ddi_dp_level(enc_to_intel_dp(encoder), crtc_state,
14385c31e9d0SJani Nikula 					   lane);
14392c63e0f9SVille Syrjälä 
14402c63e0f9SVille Syrjälä 	if (drm_WARN_ON_ONCE(&i915->drm, level >= n_entries))
14412c63e0f9SVille Syrjälä 		level = n_entries - 1;
14422c63e0f9SVille Syrjälä 
14432c63e0f9SVille Syrjälä 	return level;
1444e722ab8bSVille Syrjälä }
1445e722ab8bSVille Syrjälä 
1446e722ab8bSVille Syrjälä static void
1447e722ab8bSVille Syrjälä hsw_set_signal_levels(struct intel_encoder *encoder,
1448a621860aSVille Syrjälä 		      const struct intel_crtc_state *crtc_state)
1449fb83f72cSVille Syrjälä {
1450fb83f72cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1451e722ab8bSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1452d0920a45SVille Syrjälä 	int level = intel_ddi_level(encoder, crtc_state, 0);
1453fb83f72cSVille Syrjälä 	enum port port = encoder->port;
1454fb83f72cSVille Syrjälä 	u32 signal_levels;
1455fb83f72cSVille Syrjälä 
1456e722ab8bSVille Syrjälä 	if (has_iboost(dev_priv))
1457e722ab8bSVille Syrjälä 		skl_ddi_set_iboost(encoder, crtc_state, level);
1458e722ab8bSVille Syrjälä 
1459e722ab8bSVille Syrjälä 	/* HDMI ignores the rest */
1460e722ab8bSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1461e722ab8bSVille Syrjälä 		return;
1462e722ab8bSVille Syrjälä 
1463fb83f72cSVille Syrjälä 	signal_levels = DDI_BUF_TRANS_SELECT(level);
1464fb83f72cSVille Syrjälä 
1465fb83f72cSVille Syrjälä 	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
1466fb83f72cSVille Syrjälä 		    signal_levels);
1467fb83f72cSVille Syrjälä 
1468fb83f72cSVille Syrjälä 	intel_dp->DP &= ~DDI_BUF_EMP_MASK;
1469fb83f72cSVille Syrjälä 	intel_dp->DP |= signal_levels;
1470fb83f72cSVille Syrjälä 
1471fb83f72cSVille Syrjälä 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
1472fb83f72cSVille Syrjälä 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
1473379bc100SJani Nikula }
1474379bc100SJani Nikula 
14754da27d5dSLucas De Marchi static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14769c6a5c35SVille Syrjälä 				  u32 clk_sel_mask, u32 clk_sel, u32 clk_off)
14779c6a5c35SVille Syrjälä {
147836d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
14799c6a5c35SVille Syrjälä 
14809c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, clk_sel_mask, clk_sel);
14819c6a5c35SVille Syrjälä 
14829c6a5c35SVille Syrjälä 	/*
14839c6a5c35SVille Syrjälä 	 * "This step and the step before must be
14849c6a5c35SVille Syrjälä 	 *  done with separate register writes."
14859c6a5c35SVille Syrjälä 	 */
14869c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, clk_off, 0);
14879c6a5c35SVille Syrjälä 
148836d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
14899c6a5c35SVille Syrjälä }
14909c6a5c35SVille Syrjälä 
14914da27d5dSLucas De Marchi static void _icl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14929c6a5c35SVille Syrjälä 				   u32 clk_off)
14939c6a5c35SVille Syrjälä {
149436d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
14959c6a5c35SVille Syrjälä 
14969c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, 0, clk_off);
14979c6a5c35SVille Syrjälä 
149836d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
14999c6a5c35SVille Syrjälä }
15009c6a5c35SVille Syrjälä 
15014da27d5dSLucas De Marchi static bool _icl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg,
15020fbd8694SVille Syrjälä 				      u32 clk_off)
15030fbd8694SVille Syrjälä {
15040fbd8694SVille Syrjälä 	return !(intel_de_read(i915, reg) & clk_off);
15050fbd8694SVille Syrjälä }
15060fbd8694SVille Syrjälä 
1507351221ffSVille Syrjälä static struct intel_shared_dpll *
15084da27d5dSLucas De Marchi _icl_ddi_get_pll(struct drm_i915_private *i915, i915_reg_t reg,
1509351221ffSVille Syrjälä 		 u32 clk_sel_mask, u32 clk_sel_shift)
1510351221ffSVille Syrjälä {
1511351221ffSVille Syrjälä 	enum intel_dpll_id id;
1512351221ffSVille Syrjälä 
1513351221ffSVille Syrjälä 	id = (intel_de_read(i915, reg) & clk_sel_mask) >> clk_sel_shift;
1514351221ffSVille Syrjälä 
1515351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1516351221ffSVille Syrjälä }
1517351221ffSVille Syrjälä 
151840b316d4SVille Syrjälä static void adls_ddi_enable_clock(struct intel_encoder *encoder,
151940b316d4SVille Syrjälä 				  const struct intel_crtc_state *crtc_state)
152040b316d4SVille Syrjälä {
152140b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
152240b316d4SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
152340b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
152440b316d4SVille Syrjälä 
152540b316d4SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
152640b316d4SVille Syrjälä 		return;
152740b316d4SVille Syrjälä 
15284da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
152940b316d4SVille Syrjälä 			      ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
153040b316d4SVille Syrjälä 			      pll->info->id << ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy),
153140b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
153240b316d4SVille Syrjälä }
153340b316d4SVille Syrjälä 
153440b316d4SVille Syrjälä static void adls_ddi_disable_clock(struct intel_encoder *encoder)
153540b316d4SVille Syrjälä {
153640b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
153740b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
153840b316d4SVille Syrjälä 
15394da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
154040b316d4SVille Syrjälä 			       ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
154140b316d4SVille Syrjälä }
154240b316d4SVille Syrjälä 
15430fbd8694SVille Syrjälä static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder)
15440fbd8694SVille Syrjälä {
15450fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15460fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
15470fbd8694SVille Syrjälä 
15484da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy),
15490fbd8694SVille Syrjälä 					 ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15500fbd8694SVille Syrjälä }
15510fbd8694SVille Syrjälä 
1552351221ffSVille Syrjälä static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
1553351221ffSVille Syrjälä {
1554351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1555351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1556351221ffSVille Syrjälä 
15574da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy),
1558351221ffSVille Syrjälä 				ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
1559351221ffSVille Syrjälä 				ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy));
1560351221ffSVille Syrjälä }
1561351221ffSVille Syrjälä 
156240b316d4SVille Syrjälä static void rkl_ddi_enable_clock(struct intel_encoder *encoder,
156340b316d4SVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
156440b316d4SVille Syrjälä {
156540b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
156640b316d4SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
156740b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
156840b316d4SVille Syrjälä 
156940b316d4SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
157040b316d4SVille Syrjälä 		return;
157140b316d4SVille Syrjälä 
15724da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
157340b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
157440b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
157540b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
157640b316d4SVille Syrjälä }
157740b316d4SVille Syrjälä 
157840b316d4SVille Syrjälä static void rkl_ddi_disable_clock(struct intel_encoder *encoder)
157940b316d4SVille Syrjälä {
158040b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
158140b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
158240b316d4SVille Syrjälä 
15834da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
158440b316d4SVille Syrjälä 			       RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
158540b316d4SVille Syrjälä }
158640b316d4SVille Syrjälä 
15870fbd8694SVille Syrjälä static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder)
15880fbd8694SVille Syrjälä {
15890fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15900fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
15910fbd8694SVille Syrjälä 
15924da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
15930fbd8694SVille Syrjälä 					 RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15940fbd8694SVille Syrjälä }
15950fbd8694SVille Syrjälä 
1596351221ffSVille Syrjälä static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
1597351221ffSVille Syrjälä {
1598351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1599351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1600351221ffSVille Syrjälä 
16014da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1602351221ffSVille Syrjälä 				RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1603351221ffSVille Syrjälä 				RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1604351221ffSVille Syrjälä }
1605351221ffSVille Syrjälä 
160635bb6b1aSVille Syrjälä static void dg1_ddi_enable_clock(struct intel_encoder *encoder,
160711ffe972SLucas De Marchi 				 const struct intel_crtc_state *crtc_state)
160811ffe972SLucas De Marchi {
160997a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16109c6a5c35SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
161197a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
161211ffe972SLucas De Marchi 
161397a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1614f67a008eSVille Syrjälä 		return;
1615f67a008eSVille Syrjälä 
161611ffe972SLucas De Marchi 	/*
161711ffe972SLucas De Marchi 	 * If we fail this, something went very wrong: first 2 PLLs should be
161811ffe972SLucas De Marchi 	 * used by first 2 phys and last 2 PLLs by last phys
161911ffe972SLucas De Marchi 	 */
162097a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm,
162111ffe972SLucas De Marchi 			(pll->info->id < DPLL_ID_DG1_DPLL2 && phy >= PHY_C) ||
162211ffe972SLucas De Marchi 			(pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C)))
162311ffe972SLucas De Marchi 		return;
162411ffe972SLucas De Marchi 
16254da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16267815ed88SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
16279c6a5c35SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
16289c6a5c35SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
162911ffe972SLucas De Marchi }
163011ffe972SLucas De Marchi 
163135bb6b1aSVille Syrjälä static void dg1_ddi_disable_clock(struct intel_encoder *encoder)
163235bb6b1aSVille Syrjälä {
163397a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
163497a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
163535bb6b1aSVille Syrjälä 
16364da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16379c6a5c35SVille Syrjälä 			       DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
163835bb6b1aSVille Syrjälä }
163935bb6b1aSVille Syrjälä 
16400fbd8694SVille Syrjälä static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder)
16410fbd8694SVille Syrjälä {
16420fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16430fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16440fbd8694SVille Syrjälä 
16454da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy),
16460fbd8694SVille Syrjälä 					 DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
16470fbd8694SVille Syrjälä }
16480fbd8694SVille Syrjälä 
1649351221ffSVille Syrjälä static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
1650351221ffSVille Syrjälä {
1651351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1652351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16533352d86dSJosé Roberto de Souza 	enum intel_dpll_id id;
16543352d86dSJosé Roberto de Souza 	u32 val;
1655351221ffSVille Syrjälä 
16563352d86dSJosé Roberto de Souza 	val = intel_de_read(i915, DG1_DPCLKA_CFGCR0(phy));
16573352d86dSJosé Roberto de Souza 	val &= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
16583352d86dSJosé Roberto de Souza 	val >>= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
16593352d86dSJosé Roberto de Souza 	id = val;
16603352d86dSJosé Roberto de Souza 
16613352d86dSJosé Roberto de Souza 	/*
16623352d86dSJosé Roberto de Souza 	 * _DG1_DPCLKA0_CFGCR0 maps between DPLL 0 and 1 with one bit for phy A
16633352d86dSJosé Roberto de Souza 	 * and B while _DG1_DPCLKA1_CFGCR0 maps between DPLL 2 and 3 with one
16643352d86dSJosé Roberto de Souza 	 * bit for phy C and D.
16653352d86dSJosé Roberto de Souza 	 */
16663352d86dSJosé Roberto de Souza 	if (phy >= PHY_C)
16673352d86dSJosé Roberto de Souza 		id += DPLL_ID_DG1_DPLL2;
16683352d86dSJosé Roberto de Souza 
16693352d86dSJosé Roberto de Souza 	return intel_get_shared_dpll_by_id(i915, id);
1670351221ffSVille Syrjälä }
1671351221ffSVille Syrjälä 
167236ecb0ecSVille Syrjälä static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder,
1673379bc100SJani Nikula 				       const struct intel_crtc_state *crtc_state)
1674379bc100SJani Nikula {
167597a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16769c6a5c35SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
167797a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1678cd803bb4SMatt Roper 
167997a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1680f67a008eSVille Syrjälä 		return;
1681f67a008eSVille Syrjälä 
16824da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
168340b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
168440b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
168540b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1686379bc100SJani Nikula }
1687379bc100SJani Nikula 
168836ecb0ecSVille Syrjälä static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder)
1689379bc100SJani Nikula {
169097a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
169197a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1692379bc100SJani Nikula 
16934da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
169440b316d4SVille Syrjälä 			       ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1695379bc100SJani Nikula }
1696379bc100SJani Nikula 
16970fbd8694SVille Syrjälä static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder)
16980fbd8694SVille Syrjälä {
16990fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17000fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
17010fbd8694SVille Syrjälä 
17024da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
17030fbd8694SVille Syrjälä 					 ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
17040fbd8694SVille Syrjälä }
17050fbd8694SVille Syrjälä 
1706351221ffSVille Syrjälä struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
1707351221ffSVille Syrjälä {
1708351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1709351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1710351221ffSVille Syrjälä 
17114da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1712351221ffSVille Syrjälä 				ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1713351221ffSVille Syrjälä 				ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1714351221ffSVille Syrjälä }
1715351221ffSVille Syrjälä 
171636ecb0ecSVille Syrjälä static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder,
1717379bc100SJani Nikula 				    const struct intel_crtc_state *crtc_state)
1718379bc100SJani Nikula {
171936ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1720379bc100SJani Nikula 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
172136ecb0ecSVille Syrjälä 	enum port port = encoder->port;
1722379bc100SJani Nikula 
172336ecb0ecSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1724379bc100SJani Nikula 		return;
1725379bc100SJani Nikula 
1726c2052d6eSJosé Roberto de Souza 	/*
172736ecb0ecSVille Syrjälä 	 * "For DDIC and DDID, program DDI_CLK_SEL to map the MG clock to the port.
172836ecb0ecSVille Syrjälä 	 *  MG does not exist, but the programming is required to ungate DDIC and DDID."
1729c2052d6eSJosé Roberto de Souza 	 */
173036ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_MG);
173136ecb0ecSVille Syrjälä 
173236ecb0ecSVille Syrjälä 	icl_ddi_combo_enable_clock(encoder, crtc_state);
1733379bc100SJani Nikula }
1734379bc100SJani Nikula 
173536ecb0ecSVille Syrjälä static void jsl_ddi_tc_disable_clock(struct intel_encoder *encoder)
1736379bc100SJani Nikula {
173736ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1738379bc100SJani Nikula 	enum port port = encoder->port;
1739379bc100SJani Nikula 
174036ecb0ecSVille Syrjälä 	icl_ddi_combo_disable_clock(encoder);
174136ecb0ecSVille Syrjälä 
174236ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1743379bc100SJani Nikula }
174436ecb0ecSVille Syrjälä 
17450fbd8694SVille Syrjälä static bool jsl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17460fbd8694SVille Syrjälä {
17470fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17480fbd8694SVille Syrjälä 	enum port port = encoder->port;
17490fbd8694SVille Syrjälä 	u32 tmp;
17500fbd8694SVille Syrjälä 
17510fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
17520fbd8694SVille Syrjälä 
17530fbd8694SVille Syrjälä 	if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
17540fbd8694SVille Syrjälä 		return false;
17550fbd8694SVille Syrjälä 
17560fbd8694SVille Syrjälä 	return icl_ddi_combo_is_clock_enabled(encoder);
17570fbd8694SVille Syrjälä }
17580fbd8694SVille Syrjälä 
175936ecb0ecSVille Syrjälä static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder,
176036ecb0ecSVille Syrjälä 				    const struct intel_crtc_state *crtc_state)
176136ecb0ecSVille Syrjälä {
176236ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
176336ecb0ecSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
176436ecb0ecSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
176536ecb0ecSVille Syrjälä 	enum port port = encoder->port;
176636ecb0ecSVille Syrjälä 
176736ecb0ecSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
176836ecb0ecSVille Syrjälä 		return;
176936ecb0ecSVille Syrjälä 
177036ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port),
177136ecb0ecSVille Syrjälä 		       icl_pll_to_ddi_clk_sel(encoder, crtc_state));
177236ecb0ecSVille Syrjälä 
177336d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
177436ecb0ecSVille Syrjälä 
177536ecb0ecSVille Syrjälä 	intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
177636ecb0ecSVille Syrjälä 		     ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port), 0);
177736ecb0ecSVille Syrjälä 
177836d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
177936ecb0ecSVille Syrjälä }
178036ecb0ecSVille Syrjälä 
178136ecb0ecSVille Syrjälä static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder)
178236ecb0ecSVille Syrjälä {
178336ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
178436ecb0ecSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
178536ecb0ecSVille Syrjälä 	enum port port = encoder->port;
178636ecb0ecSVille Syrjälä 
178736d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
178836ecb0ecSVille Syrjälä 
178936ecb0ecSVille Syrjälä 	intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
179036ecb0ecSVille Syrjälä 		     0, ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
179136ecb0ecSVille Syrjälä 
179236d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
179336ecb0ecSVille Syrjälä 
179436ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1795379bc100SJani Nikula }
1796379bc100SJani Nikula 
17970fbd8694SVille Syrjälä static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17980fbd8694SVille Syrjälä {
17990fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
18000fbd8694SVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
18010fbd8694SVille Syrjälä 	enum port port = encoder->port;
18020fbd8694SVille Syrjälä 	u32 tmp;
18030fbd8694SVille Syrjälä 
18040fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
18050fbd8694SVille Syrjälä 
18060fbd8694SVille Syrjälä 	if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
18070fbd8694SVille Syrjälä 		return false;
18080fbd8694SVille Syrjälä 
18090fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, ICL_DPCLKA_CFGCR0);
18100fbd8694SVille Syrjälä 
18110fbd8694SVille Syrjälä 	return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
18120fbd8694SVille Syrjälä }
18130fbd8694SVille Syrjälä 
1814351221ffSVille Syrjälä static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder)
1815351221ffSVille Syrjälä {
1816351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1817351221ffSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
1818351221ffSVille Syrjälä 	enum port port = encoder->port;
1819351221ffSVille Syrjälä 	enum intel_dpll_id id;
1820351221ffSVille Syrjälä 	u32 tmp;
1821351221ffSVille Syrjälä 
1822351221ffSVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
1823351221ffSVille Syrjälä 
1824351221ffSVille Syrjälä 	switch (tmp & DDI_CLK_SEL_MASK) {
1825351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_162:
1826351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_270:
1827351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_540:
1828351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_810:
1829351221ffSVille Syrjälä 		id = DPLL_ID_ICL_TBTPLL;
1830351221ffSVille Syrjälä 		break;
1831351221ffSVille Syrjälä 	case DDI_CLK_SEL_MG:
1832351221ffSVille Syrjälä 		id = icl_tc_port_to_pll_id(tc_port);
1833351221ffSVille Syrjälä 		break;
1834351221ffSVille Syrjälä 	default:
1835351221ffSVille Syrjälä 		MISSING_CASE(tmp);
1836351221ffSVille Syrjälä 		fallthrough;
1837351221ffSVille Syrjälä 	case DDI_CLK_SEL_NONE:
1838351221ffSVille Syrjälä 		return NULL;
1839351221ffSVille Syrjälä 	}
1840351221ffSVille Syrjälä 
1841351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1842351221ffSVille Syrjälä }
1843351221ffSVille Syrjälä 
1844351221ffSVille Syrjälä static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
1845351221ffSVille Syrjälä {
1846351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1847351221ffSVille Syrjälä 	enum intel_dpll_id id;
1848351221ffSVille Syrjälä 
1849351221ffSVille Syrjälä 	switch (encoder->port) {
1850351221ffSVille Syrjälä 	case PORT_A:
1851351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL0;
1852351221ffSVille Syrjälä 		break;
1853351221ffSVille Syrjälä 	case PORT_B:
1854351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL1;
1855351221ffSVille Syrjälä 		break;
1856351221ffSVille Syrjälä 	case PORT_C:
1857351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL2;
1858351221ffSVille Syrjälä 		break;
1859351221ffSVille Syrjälä 	default:
1860351221ffSVille Syrjälä 		MISSING_CASE(encoder->port);
1861351221ffSVille Syrjälä 		return NULL;
1862351221ffSVille Syrjälä 	}
1863351221ffSVille Syrjälä 
1864351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1865351221ffSVille Syrjälä }
1866351221ffSVille Syrjälä 
186738e31f1aSVille Syrjälä static void skl_ddi_enable_clock(struct intel_encoder *encoder,
186838e31f1aSVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
186938e31f1aSVille Syrjälä {
187038e31f1aSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
187138e31f1aSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
187238e31f1aSVille Syrjälä 	enum port port = encoder->port;
187338e31f1aSVille Syrjälä 
187438e31f1aSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
187538e31f1aSVille Syrjälä 		return;
187638e31f1aSVille Syrjälä 
187736d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
187838e31f1aSVille Syrjälä 
18797815ed88SVille Syrjälä 	intel_de_rmw(i915, DPLL_CTRL2,
18807815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_OFF(port) |
18817815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_SEL_MASK(port),
18827815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_SEL(pll->info->id, port) |
188338e31f1aSVille Syrjälä 		     DPLL_CTRL2_DDI_SEL_OVERRIDE(port));
188438e31f1aSVille Syrjälä 
188536d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
188638e31f1aSVille Syrjälä }
188738e31f1aSVille Syrjälä 
188838e31f1aSVille Syrjälä static void skl_ddi_disable_clock(struct intel_encoder *encoder)
188938e31f1aSVille Syrjälä {
189038e31f1aSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
189138e31f1aSVille Syrjälä 	enum port port = encoder->port;
189238e31f1aSVille Syrjälä 
189336d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
1894be317ca0SVille Syrjälä 
18957815ed88SVille Syrjälä 	intel_de_rmw(i915, DPLL_CTRL2,
18967815ed88SVille Syrjälä 		     0, DPLL_CTRL2_DDI_CLK_OFF(port));
1897be317ca0SVille Syrjälä 
189836d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
189938e31f1aSVille Syrjälä }
190038e31f1aSVille Syrjälä 
19010fbd8694SVille Syrjälä static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder)
19020fbd8694SVille Syrjälä {
19030fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19040fbd8694SVille Syrjälä 	enum port port = encoder->port;
19050fbd8694SVille Syrjälä 
19060fbd8694SVille Syrjälä 	/*
19070fbd8694SVille Syrjälä 	 * FIXME Not sure if the override affects both
19080fbd8694SVille Syrjälä 	 * the PLL selection and the CLK_OFF bit.
19090fbd8694SVille Syrjälä 	 */
19100fbd8694SVille Syrjälä 	return !(intel_de_read(i915, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port));
19110fbd8694SVille Syrjälä }
19120fbd8694SVille Syrjälä 
1913351221ffSVille Syrjälä static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
1914351221ffSVille Syrjälä {
1915351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1916351221ffSVille Syrjälä 	enum port port = encoder->port;
1917351221ffSVille Syrjälä 	enum intel_dpll_id id;
1918351221ffSVille Syrjälä 	u32 tmp;
1919351221ffSVille Syrjälä 
1920351221ffSVille Syrjälä 	tmp = intel_de_read(i915, DPLL_CTRL2);
1921351221ffSVille Syrjälä 
1922351221ffSVille Syrjälä 	/*
1923351221ffSVille Syrjälä 	 * FIXME Not sure if the override affects both
1924351221ffSVille Syrjälä 	 * the PLL selection and the CLK_OFF bit.
1925351221ffSVille Syrjälä 	 */
1926351221ffSVille Syrjälä 	if ((tmp & DPLL_CTRL2_DDI_SEL_OVERRIDE(port)) == 0)
1927351221ffSVille Syrjälä 		return NULL;
1928351221ffSVille Syrjälä 
1929351221ffSVille Syrjälä 	id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >>
1930351221ffSVille Syrjälä 		DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port);
1931351221ffSVille Syrjälä 
1932351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1933351221ffSVille Syrjälä }
1934351221ffSVille Syrjälä 
1935d135368dSVille Syrjälä void hsw_ddi_enable_clock(struct intel_encoder *encoder,
1936d135368dSVille Syrjälä 			  const struct intel_crtc_state *crtc_state)
1937d135368dSVille Syrjälä {
1938d135368dSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1939d135368dSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
1940d135368dSVille Syrjälä 	enum port port = encoder->port;
1941d135368dSVille Syrjälä 
1942d135368dSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1943d135368dSVille Syrjälä 		return;
1944d135368dSVille Syrjälä 
1945d135368dSVille Syrjälä 	intel_de_write(i915, PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll));
1946d135368dSVille Syrjälä }
1947d135368dSVille Syrjälä 
1948d135368dSVille Syrjälä void hsw_ddi_disable_clock(struct intel_encoder *encoder)
1949d135368dSVille Syrjälä {
1950d135368dSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1951d135368dSVille Syrjälä 	enum port port = encoder->port;
1952d135368dSVille Syrjälä 
1953d135368dSVille Syrjälä 	intel_de_write(i915, PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
1954d135368dSVille Syrjälä }
1955d135368dSVille Syrjälä 
19560fbd8694SVille Syrjälä bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder)
19570fbd8694SVille Syrjälä {
19580fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19590fbd8694SVille Syrjälä 	enum port port = encoder->port;
19600fbd8694SVille Syrjälä 
19610fbd8694SVille Syrjälä 	return intel_de_read(i915, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE;
19620fbd8694SVille Syrjälä }
19630fbd8694SVille Syrjälä 
1964351221ffSVille Syrjälä static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
1965351221ffSVille Syrjälä {
1966351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1967351221ffSVille Syrjälä 	enum port port = encoder->port;
1968351221ffSVille Syrjälä 	enum intel_dpll_id id;
1969351221ffSVille Syrjälä 	u32 tmp;
1970351221ffSVille Syrjälä 
1971351221ffSVille Syrjälä 	tmp = intel_de_read(i915, PORT_CLK_SEL(port));
1972351221ffSVille Syrjälä 
1973351221ffSVille Syrjälä 	switch (tmp & PORT_CLK_SEL_MASK) {
1974351221ffSVille Syrjälä 	case PORT_CLK_SEL_WRPLL1:
1975351221ffSVille Syrjälä 		id = DPLL_ID_WRPLL1;
1976351221ffSVille Syrjälä 		break;
1977351221ffSVille Syrjälä 	case PORT_CLK_SEL_WRPLL2:
1978351221ffSVille Syrjälä 		id = DPLL_ID_WRPLL2;
1979351221ffSVille Syrjälä 		break;
1980351221ffSVille Syrjälä 	case PORT_CLK_SEL_SPLL:
1981351221ffSVille Syrjälä 		id = DPLL_ID_SPLL;
1982351221ffSVille Syrjälä 		break;
1983351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_810:
1984351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_810;
1985351221ffSVille Syrjälä 		break;
1986351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_1350:
1987351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_1350;
1988351221ffSVille Syrjälä 		break;
1989351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_2700:
1990351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_2700;
1991351221ffSVille Syrjälä 		break;
1992351221ffSVille Syrjälä 	default:
1993351221ffSVille Syrjälä 		MISSING_CASE(tmp);
1994351221ffSVille Syrjälä 		fallthrough;
1995351221ffSVille Syrjälä 	case PORT_CLK_SEL_NONE:
1996351221ffSVille Syrjälä 		return NULL;
1997351221ffSVille Syrjälä 	}
1998351221ffSVille Syrjälä 
1999351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
2000351221ffSVille Syrjälä }
2001351221ffSVille Syrjälä 
2002c133df69SVille Syrjälä void intel_ddi_enable_clock(struct intel_encoder *encoder,
2003c133df69SVille Syrjälä 			    const struct intel_crtc_state *crtc_state)
2004c133df69SVille Syrjälä {
2005c133df69SVille Syrjälä 	if (encoder->enable_clock)
2006c133df69SVille Syrjälä 		encoder->enable_clock(encoder, crtc_state);
2007c133df69SVille Syrjälä }
2008c133df69SVille Syrjälä 
2009d39ef5d5SVille Syrjälä void intel_ddi_disable_clock(struct intel_encoder *encoder)
2010c133df69SVille Syrjälä {
2011c133df69SVille Syrjälä 	if (encoder->disable_clock)
2012c133df69SVille Syrjälä 		encoder->disable_clock(encoder);
2013c133df69SVille Syrjälä }
2014c133df69SVille Syrjälä 
2015aaca50efSVille Syrjälä void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
2016dc1ddac6SVille Syrjälä {
201797a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2018dc1ddac6SVille Syrjälä 	u32 port_mask;
2019dc1ddac6SVille Syrjälä 	bool ddi_clk_needed;
2020dc1ddac6SVille Syrjälä 
2021dc1ddac6SVille Syrjälä 	/*
2022dc1ddac6SVille Syrjälä 	 * In case of DP MST, we sanitize the primary encoder only, not the
2023dc1ddac6SVille Syrjälä 	 * virtual ones.
2024dc1ddac6SVille Syrjälä 	 */
2025dc1ddac6SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_DP_MST)
2026dc1ddac6SVille Syrjälä 		return;
2027dc1ddac6SVille Syrjälä 
2028dc1ddac6SVille Syrjälä 	if (!encoder->base.crtc && intel_encoder_is_dp(encoder)) {
2029dc1ddac6SVille Syrjälä 		u8 pipe_mask;
2030dc1ddac6SVille Syrjälä 		bool is_mst;
2031dc1ddac6SVille Syrjälä 
2032dc1ddac6SVille Syrjälä 		intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
2033dc1ddac6SVille Syrjälä 		/*
2034dc1ddac6SVille Syrjälä 		 * In the unlikely case that BIOS enables DP in MST mode, just
2035dc1ddac6SVille Syrjälä 		 * warn since our MST HW readout is incomplete.
2036dc1ddac6SVille Syrjälä 		 */
203797a24a70SVille Syrjälä 		if (drm_WARN_ON(&i915->drm, is_mst))
2038dc1ddac6SVille Syrjälä 			return;
2039dc1ddac6SVille Syrjälä 	}
2040dc1ddac6SVille Syrjälä 
2041dc1ddac6SVille Syrjälä 	port_mask = BIT(encoder->port);
2042dc1ddac6SVille Syrjälä 	ddi_clk_needed = encoder->base.crtc;
2043dc1ddac6SVille Syrjälä 
2044dc1ddac6SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_DSI) {
2045dc1ddac6SVille Syrjälä 		struct intel_encoder *other_encoder;
2046dc1ddac6SVille Syrjälä 
2047dc1ddac6SVille Syrjälä 		port_mask = intel_dsi_encoder_ports(encoder);
2048dc1ddac6SVille Syrjälä 		/*
2049dc1ddac6SVille Syrjälä 		 * Sanity check that we haven't incorrectly registered another
2050dc1ddac6SVille Syrjälä 		 * encoder using any of the ports of this DSI encoder.
2051dc1ddac6SVille Syrjälä 		 */
205297a24a70SVille Syrjälä 		for_each_intel_encoder(&i915->drm, other_encoder) {
2053dc1ddac6SVille Syrjälä 			if (other_encoder == encoder)
2054dc1ddac6SVille Syrjälä 				continue;
2055dc1ddac6SVille Syrjälä 
205697a24a70SVille Syrjälä 			if (drm_WARN_ON(&i915->drm,
2057dc1ddac6SVille Syrjälä 					port_mask & BIT(other_encoder->port)))
2058dc1ddac6SVille Syrjälä 				return;
2059dc1ddac6SVille Syrjälä 		}
2060dc1ddac6SVille Syrjälä 		/*
2061dc1ddac6SVille Syrjälä 		 * For DSI we keep the ddi clocks gated
2062dc1ddac6SVille Syrjälä 		 * except during enable/disable sequence.
2063dc1ddac6SVille Syrjälä 		 */
2064dc1ddac6SVille Syrjälä 		ddi_clk_needed = false;
2065dc1ddac6SVille Syrjälä 	}
2066dc1ddac6SVille Syrjälä 
2067f82f2563SMatt Roper 	if (ddi_clk_needed || !encoder->is_clock_enabled ||
20680fbd8694SVille Syrjälä 	    !encoder->is_clock_enabled(encoder))
20690fbd8694SVille Syrjälä 		return;
20700fbd8694SVille Syrjälä 
20710fbd8694SVille Syrjälä 	drm_notice(&i915->drm,
20720fbd8694SVille Syrjälä 		   "[ENCODER:%d:%s] is disabled/in DSI mode with an ungated DDI clock, gate it\n",
20730fbd8694SVille Syrjälä 		   encoder->base.base.id, encoder->base.name);
20740fbd8694SVille Syrjälä 
2075dc1ddac6SVille Syrjälä 	encoder->disable_clock(encoder);
2076dc1ddac6SVille Syrjälä }
2077dc1ddac6SVille Syrjälä 
20788aaf5cbdSJosé Roberto de Souza static void
20797801f3b7SLucas De Marchi icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
20803b51be4eSClinton A Taylor 		       const struct intel_crtc_state *crtc_state)
2081379bc100SJani Nikula {
20827801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
20837801f3b7SLucas De Marchi 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
20845b6a9ba9SVille Syrjälä 	enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
20853b51be4eSClinton A Taylor 	u32 ln0, ln1, pin_assignment;
20863b51be4eSClinton A Taylor 	u8 width;
2087379bc100SJani Nikula 
20885b6a9ba9SVille Syrjälä 	if (!intel_phy_is_tc(dev_priv, phy) ||
208911a89708SImre Deak 	    intel_tc_port_in_tbt_alt_mode(dig_port))
2090379bc100SJani Nikula 		return;
2091379bc100SJani Nikula 
2092005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2093b8ed5533SImre Deak 		ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0));
2094b8ed5533SImre Deak 		ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1));
2095978c3e53SClinton A Taylor 	} else {
2096f7960e7fSJani Nikula 		ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port));
2097f7960e7fSJani Nikula 		ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
2098978c3e53SClinton A Taylor 	}
2099379bc100SJani Nikula 
21004f72a8eeSKhaled Almahallawy 	ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2101379bc100SJani Nikula 	ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2102379bc100SJani Nikula 
21033b51be4eSClinton A Taylor 	/* DPPATC */
21047801f3b7SLucas De Marchi 	pin_assignment = intel_tc_port_get_pin_assignment_mask(dig_port);
21053b51be4eSClinton A Taylor 	width = crtc_state->lane_count;
2106379bc100SJani Nikula 
21073b51be4eSClinton A Taylor 	switch (pin_assignment) {
21083b51be4eSClinton A Taylor 	case 0x0:
21091de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm,
211011a89708SImre Deak 			    !intel_tc_port_in_legacy_mode(dig_port));
21113b51be4eSClinton A Taylor 		if (width == 1) {
2112379bc100SJani Nikula 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21133b51be4eSClinton A Taylor 		} else {
21143b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21153b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
2116379bc100SJani Nikula 		}
2117379bc100SJani Nikula 		break;
21183b51be4eSClinton A Taylor 	case 0x1:
21193b51be4eSClinton A Taylor 		if (width == 4) {
21203b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21213b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21223b51be4eSClinton A Taylor 		}
2123379bc100SJani Nikula 		break;
21243b51be4eSClinton A Taylor 	case 0x2:
21253b51be4eSClinton A Taylor 		if (width == 2) {
21263b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21273b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21283b51be4eSClinton A Taylor 		}
21293b51be4eSClinton A Taylor 		break;
21303b51be4eSClinton A Taylor 	case 0x3:
21313b51be4eSClinton A Taylor 	case 0x5:
21323b51be4eSClinton A Taylor 		if (width == 1) {
21333b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21343b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21353b51be4eSClinton A Taylor 		} else {
21363b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21373b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21383b51be4eSClinton A Taylor 		}
21393b51be4eSClinton A Taylor 		break;
21403b51be4eSClinton A Taylor 	case 0x4:
21413b51be4eSClinton A Taylor 	case 0x6:
21423b51be4eSClinton A Taylor 		if (width == 1) {
21433b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21443b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21453b51be4eSClinton A Taylor 		} else {
21463b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21473b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21483b51be4eSClinton A Taylor 		}
21493b51be4eSClinton A Taylor 		break;
2150379bc100SJani Nikula 	default:
21513b51be4eSClinton A Taylor 		MISSING_CASE(pin_assignment);
2152379bc100SJani Nikula 	}
2153379bc100SJani Nikula 
2154005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2155b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0);
2156b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1);
2157978c3e53SClinton A Taylor 	} else {
2158f7960e7fSJani Nikula 		intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0);
2159f7960e7fSJani Nikula 		intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1);
2160379bc100SJani Nikula 	}
2161978c3e53SClinton A Taylor }
2162379bc100SJani Nikula 
2163ef79fafeSVille Syrjälä static enum transcoder
2164ef79fafeSVille Syrjälä tgl_dp_tp_transcoder(const struct intel_crtc_state *crtc_state)
2165ef79fafeSVille Syrjälä {
2166ef79fafeSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
2167ef79fafeSVille Syrjälä 		return crtc_state->mst_master_transcoder;
2168ef79fafeSVille Syrjälä 	else
2169ef79fafeSVille Syrjälä 		return crtc_state->cpu_transcoder;
2170ef79fafeSVille Syrjälä }
2171ef79fafeSVille Syrjälä 
2172ef79fafeSVille Syrjälä i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
2173ef79fafeSVille Syrjälä 			 const struct intel_crtc_state *crtc_state)
2174ef79fafeSVille Syrjälä {
2175ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2176ef79fafeSVille Syrjälä 
2177005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
2178ef79fafeSVille Syrjälä 		return TGL_DP_TP_CTL(tgl_dp_tp_transcoder(crtc_state));
2179ef79fafeSVille Syrjälä 	else
2180ef79fafeSVille Syrjälä 		return DP_TP_CTL(encoder->port);
2181ef79fafeSVille Syrjälä }
2182ef79fafeSVille Syrjälä 
2183ef79fafeSVille Syrjälä i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
2184ef79fafeSVille Syrjälä 			    const struct intel_crtc_state *crtc_state)
2185ef79fafeSVille Syrjälä {
2186ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2187ef79fafeSVille Syrjälä 
2188005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
2189ef79fafeSVille Syrjälä 		return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state));
2190ef79fafeSVille Syrjälä 	else
2191ef79fafeSVille Syrjälä 		return DP_TP_STATUS(encoder->port);
2192ef79fafeSVille Syrjälä }
2193ef79fafeSVille Syrjälä 
21941639406aSManasi Navare static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
21951639406aSManasi Navare 							  const struct intel_crtc_state *crtc_state,
21961639406aSManasi Navare 							  bool enable)
21971639406aSManasi Navare {
21981639406aSManasi Navare 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
21991639406aSManasi Navare 
22001639406aSManasi Navare 	if (!crtc_state->vrr.enable)
22011639406aSManasi Navare 		return;
22021639406aSManasi Navare 
22031639406aSManasi Navare 	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL,
22041639406aSManasi Navare 			       enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
22051639406aSManasi Navare 		drm_dbg_kms(&i915->drm,
22060868b1ceSVille Syrjälä 			    "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
2207707c3a7dSLucas De Marchi 			    str_enable_disable(enable));
22081639406aSManasi Navare }
22091639406aSManasi Navare 
2210379bc100SJani Nikula static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
2211379bc100SJani Nikula 					const struct intel_crtc_state *crtc_state)
2212379bc100SJani Nikula {
221347bdb1caSJani Nikula 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
221447bdb1caSJani Nikula 
2215379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2216379bc100SJani Nikula 		return;
2217379bc100SJani Nikula 
2218379bc100SJani Nikula 	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION, DP_FEC_READY) <= 0)
221947bdb1caSJani Nikula 		drm_dbg_kms(&i915->drm,
222047bdb1caSJani Nikula 			    "Failed to set FEC_READY in the sink\n");
2221379bc100SJani Nikula }
2222379bc100SJani Nikula 
2223379bc100SJani Nikula static void intel_ddi_enable_fec(struct intel_encoder *encoder,
2224379bc100SJani Nikula 				 const struct intel_crtc_state *crtc_state)
2225379bc100SJani Nikula {
2226379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
22274444df6eSLucas De Marchi 	struct intel_dp *intel_dp;
2228379bc100SJani Nikula 
2229379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2230379bc100SJani Nikula 		return;
2231379bc100SJani Nikula 
2232b7d02c3aSVille Syrjälä 	intel_dp = enc_to_intel_dp(encoder);
22338910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
22348910d8b7SAndrzej Hajda 		     0, DP_TP_CTL_FEC_ENABLE);
2235379bc100SJani Nikula }
2236379bc100SJani Nikula 
2237379bc100SJani Nikula static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
2238379bc100SJani Nikula 					const struct intel_crtc_state *crtc_state)
2239379bc100SJani Nikula {
2240379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
22414444df6eSLucas De Marchi 	struct intel_dp *intel_dp;
2242379bc100SJani Nikula 
2243379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2244379bc100SJani Nikula 		return;
2245379bc100SJani Nikula 
2246b7d02c3aSVille Syrjälä 	intel_dp = enc_to_intel_dp(encoder);
22478910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
22488910d8b7SAndrzej Hajda 		     DP_TP_CTL_FEC_ENABLE, 0);
2249ef79fafeSVille Syrjälä 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
2250379bc100SJani Nikula }
2251379bc100SJani Nikula 
22525cdf706fSVille Syrjälä static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
22535cdf706fSVille Syrjälä 				     const struct intel_crtc_state *crtc_state)
22545cdf706fSVille Syrjälä {
22555cdf706fSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
22565cdf706fSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
22575cdf706fSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
22585cdf706fSVille Syrjälä 
22595cdf706fSVille Syrjälä 	if (intel_phy_is_combo(i915, phy)) {
22605cdf706fSVille Syrjälä 		bool lane_reversal =
22615cdf706fSVille Syrjälä 			dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
22625cdf706fSVille Syrjälä 
22635cdf706fSVille Syrjälä 		intel_combo_phy_power_up_lanes(i915, phy, false,
22645cdf706fSVille Syrjälä 					       crtc_state->lane_count,
22655cdf706fSVille Syrjälä 					       lane_reversal);
22665cdf706fSVille Syrjälä 	}
22675cdf706fSVille Syrjälä }
22685cdf706fSVille Syrjälä 
2269f6864b27SJani Nikula /* Splitter enable for eDP MSO is limited to certain pipes. */
2270f6864b27SJani Nikula static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915)
2271f6864b27SJani Nikula {
2272f6864b27SJani Nikula 	if (IS_ALDERLAKE_P(i915))
2273f6864b27SJani Nikula 		return BIT(PIPE_A) | BIT(PIPE_B);
2274f6864b27SJani Nikula 	else
2275f6864b27SJani Nikula 		return BIT(PIPE_A);
2276f6864b27SJani Nikula }
2277f6864b27SJani Nikula 
22785b616a29SJani Nikula static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
22795b616a29SJani Nikula 				     struct intel_crtc_state *pipe_config)
22805b616a29SJani Nikula {
22815b616a29SJani Nikula 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
22825b616a29SJani Nikula 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
22835b616a29SJani Nikula 	enum pipe pipe = crtc->pipe;
22845b616a29SJani Nikula 	u32 dss1;
22855b616a29SJani Nikula 
22865b616a29SJani Nikula 	if (!HAS_MSO(i915))
22875b616a29SJani Nikula 		return;
22885b616a29SJani Nikula 
22895b616a29SJani Nikula 	dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe));
22905b616a29SJani Nikula 
22915b616a29SJani Nikula 	pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE;
22925b616a29SJani Nikula 	if (!pipe_config->splitter.enable)
22935b616a29SJani Nikula 		return;
22945b616a29SJani Nikula 
2295f6864b27SJani Nikula 	if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) {
22965b616a29SJani Nikula 		pipe_config->splitter.enable = false;
22975b616a29SJani Nikula 		return;
22985b616a29SJani Nikula 	}
22995b616a29SJani Nikula 
23005b616a29SJani Nikula 	switch (dss1 & SPLITTER_CONFIGURATION_MASK) {
23015b616a29SJani Nikula 	default:
23025b616a29SJani Nikula 		drm_WARN(&i915->drm, true,
23035b616a29SJani Nikula 			 "Invalid splitter configuration, dss1=0x%08x\n", dss1);
23045b616a29SJani Nikula 		fallthrough;
23055b616a29SJani Nikula 	case SPLITTER_CONFIGURATION_2_SEGMENT:
23065b616a29SJani Nikula 		pipe_config->splitter.link_count = 2;
23075b616a29SJani Nikula 		break;
23085b616a29SJani Nikula 	case SPLITTER_CONFIGURATION_4_SEGMENT:
23095b616a29SJani Nikula 		pipe_config->splitter.link_count = 4;
23105b616a29SJani Nikula 		break;
23115b616a29SJani Nikula 	}
23125b616a29SJani Nikula 
23135b616a29SJani Nikula 	pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1);
23145b616a29SJani Nikula }
23155b616a29SJani Nikula 
2316bc71194eSJani Nikula static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
2317bc71194eSJani Nikula {
2318bc71194eSJani Nikula 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2319bc71194eSJani Nikula 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2320bc71194eSJani Nikula 	enum pipe pipe = crtc->pipe;
2321bc71194eSJani Nikula 	u32 dss1 = 0;
2322bc71194eSJani Nikula 
2323bc71194eSJani Nikula 	if (!HAS_MSO(i915))
2324bc71194eSJani Nikula 		return;
2325bc71194eSJani Nikula 
2326bc71194eSJani Nikula 	if (crtc_state->splitter.enable) {
2327bc71194eSJani Nikula 		dss1 |= SPLITTER_ENABLE;
2328bc71194eSJani Nikula 		dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
2329bc71194eSJani Nikula 		if (crtc_state->splitter.link_count == 2)
2330bc71194eSJani Nikula 			dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT;
2331bc71194eSJani Nikula 		else
2332bc71194eSJani Nikula 			dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT;
2333bc71194eSJani Nikula 	}
2334bc71194eSJani Nikula 
2335bc71194eSJani Nikula 	intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe),
2336bc71194eSJani Nikula 		     SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK |
2337bc71194eSJani Nikula 		     OVERLAP_PIXELS_MASK, dss1);
2338bc71194eSJani Nikula }
2339bc71194eSJani Nikula 
234023ef6194SJosé Roberto de Souza static u8 mtl_get_port_width(u8 lane_count)
234123ef6194SJosé Roberto de Souza {
234223ef6194SJosé Roberto de Souza 	switch (lane_count) {
234323ef6194SJosé Roberto de Souza 	case 1:
234423ef6194SJosé Roberto de Souza 		return 0;
234523ef6194SJosé Roberto de Souza 	case 2:
234623ef6194SJosé Roberto de Souza 		return 1;
234723ef6194SJosé Roberto de Souza 	case 3:
234823ef6194SJosé Roberto de Souza 		return 4;
234923ef6194SJosé Roberto de Souza 	case 4:
235023ef6194SJosé Roberto de Souza 		return 3;
235123ef6194SJosé Roberto de Souza 	default:
235223ef6194SJosé Roberto de Souza 		MISSING_CASE(lane_count);
235323ef6194SJosé Roberto de Souza 		return 4;
235423ef6194SJosé Roberto de Souza 	}
235523ef6194SJosé Roberto de Souza }
235623ef6194SJosé Roberto de Souza 
235723ef6194SJosé Roberto de Souza static void
235823ef6194SJosé Roberto de Souza mtl_ddi_enable_d2d(struct intel_encoder *encoder)
235923ef6194SJosé Roberto de Souza {
236023ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
236123ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
236223ef6194SJosé Roberto de Souza 
236323ef6194SJosé Roberto de Souza 	intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port), 0,
236423ef6194SJosé Roberto de Souza 		     XELPDP_PORT_BUF_D2D_LINK_ENABLE);
236523ef6194SJosé Roberto de Souza 
236623ef6194SJosé Roberto de Souza 	if (wait_for_us((intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) &
236723ef6194SJosé Roberto de Souza 			 XELPDP_PORT_BUF_D2D_LINK_STATE), 100)) {
236823ef6194SJosé Roberto de Souza 		drm_err(&dev_priv->drm, "Timeout waiting for D2D Link enable for PORT_BUF_CTL %c\n",
236923ef6194SJosé Roberto de Souza 			port_name(port));
237023ef6194SJosé Roberto de Souza 	}
237123ef6194SJosé Roberto de Souza }
237223ef6194SJosé Roberto de Souza 
237323ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_program(struct intel_encoder *encoder,
237423ef6194SJosé Roberto de Souza 				     const struct intel_crtc_state *crtc_state)
237523ef6194SJosé Roberto de Souza {
237623ef6194SJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
237723ef6194SJosé Roberto de Souza 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
237823ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
237923ef6194SJosé Roberto de Souza 	u32 val;
238023ef6194SJosé Roberto de Souza 
238123ef6194SJosé Roberto de Souza 	val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port));
238223ef6194SJosé Roberto de Souza 	val &= ~XELPDP_PORT_WIDTH_MASK;
238323ef6194SJosé Roberto de Souza 	val |= XELPDP_PORT_WIDTH(mtl_get_port_width(crtc_state->lane_count));
238423ef6194SJosé Roberto de Souza 
238523ef6194SJosé Roberto de Souza 	val &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK;
238623ef6194SJosé Roberto de Souza 	if (intel_dp_is_uhbr(crtc_state))
238723ef6194SJosé Roberto de Souza 		val |= XELPDP_PORT_BUF_PORT_DATA_40BIT;
238823ef6194SJosé Roberto de Souza 	else
238923ef6194SJosé Roberto de Souza 		val |= XELPDP_PORT_BUF_PORT_DATA_10BIT;
239023ef6194SJosé Roberto de Souza 
239123ef6194SJosé Roberto de Souza 	if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
239223ef6194SJosé Roberto de Souza 		val |= XELPDP_PORT_REVERSAL;
239323ef6194SJosé Roberto de Souza 
239423ef6194SJosé Roberto de Souza 	intel_de_write(i915, XELPDP_PORT_BUF_CTL1(port), val);
239523ef6194SJosé Roberto de Souza }
239623ef6194SJosé Roberto de Souza 
239723ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_io_selection(struct intel_encoder *encoder)
239823ef6194SJosé Roberto de Souza {
239923ef6194SJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
240023ef6194SJosé Roberto de Souza 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
240123ef6194SJosé Roberto de Souza 	u32 val;
240223ef6194SJosé Roberto de Souza 
240323ef6194SJosé Roberto de Souza 	val = intel_tc_port_in_tbt_alt_mode(dig_port) ?
240423ef6194SJosé Roberto de Souza 	      XELPDP_PORT_BUF_IO_SELECT_TBT : 0;
240523ef6194SJosé Roberto de Souza 	intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(encoder->port),
240623ef6194SJosé Roberto de Souza 		     XELPDP_PORT_BUF_IO_SELECT_TBT, val);
240723ef6194SJosé Roberto de Souza }
240823ef6194SJosé Roberto de Souza 
240923ef6194SJosé Roberto de Souza static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
241023ef6194SJosé Roberto de Souza 				  struct intel_encoder *encoder,
241123ef6194SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state,
241223ef6194SJosé Roberto de Souza 				  const struct drm_connector_state *conn_state)
241323ef6194SJosé Roberto de Souza {
241423ef6194SJosé Roberto de Souza 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
241523ef6194SJosé Roberto de Souza 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
241623ef6194SJosé Roberto de Souza 
241723ef6194SJosé Roberto de Souza 	intel_dp_set_link_params(intel_dp,
241823ef6194SJosé Roberto de Souza 				 crtc_state->port_clock,
241923ef6194SJosé Roberto de Souza 				 crtc_state->lane_count);
242023ef6194SJosé Roberto de Souza 
242123ef6194SJosé Roberto de Souza 	/*
242223ef6194SJosé Roberto de Souza 	 * We only configure what the register value will be here.  Actual
242323ef6194SJosé Roberto de Souza 	 * enabling happens during link training farther down.
242423ef6194SJosé Roberto de Souza 	 */
242523ef6194SJosé Roberto de Souza 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
242623ef6194SJosé Roberto de Souza 
242723ef6194SJosé Roberto de Souza 	/*
242823ef6194SJosé Roberto de Souza 	 * 1. Enable Power Wells
242923ef6194SJosé Roberto de Souza 	 *
243023ef6194SJosé Roberto de Souza 	 * This was handled at the beginning of intel_atomic_commit_tail(),
243123ef6194SJosé Roberto de Souza 	 * before we called down into this function.
243223ef6194SJosé Roberto de Souza 	 */
243323ef6194SJosé Roberto de Souza 
243423ef6194SJosé Roberto de Souza 	/* 2. PMdemand was already set */
243523ef6194SJosé Roberto de Souza 
243623ef6194SJosé Roberto de Souza 	/* 3. Select Thunderbolt */
243723ef6194SJosé Roberto de Souza 	mtl_port_buf_ctl_io_selection(encoder);
243823ef6194SJosé Roberto de Souza 
243923ef6194SJosé Roberto de Souza 	/* 4. Enable Panel Power if PPS is required */
244023ef6194SJosé Roberto de Souza 	intel_pps_on(intel_dp);
244123ef6194SJosé Roberto de Souza 
244223ef6194SJosé Roberto de Souza 	/* 5. Enable the port PLL */
244323ef6194SJosé Roberto de Souza 	intel_ddi_enable_clock(encoder, crtc_state);
244423ef6194SJosé Roberto de Souza 
244523ef6194SJosé Roberto de Souza 	/*
244623ef6194SJosé Roberto de Souza 	 * 6.a Configure Transcoder Clock Select to direct the Port clock to the
244723ef6194SJosé Roberto de Souza 	 * Transcoder.
244823ef6194SJosé Roberto de Souza 	 */
244923ef6194SJosé Roberto de Souza 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
245023ef6194SJosé Roberto de Souza 
245123ef6194SJosé Roberto de Souza 	/*
245223ef6194SJosé Roberto de Souza 	 * 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings.
245323ef6194SJosé Roberto de Souza 	 */
245423ef6194SJosé Roberto de Souza 	intel_ddi_config_transcoder_dp2(encoder, crtc_state);
245523ef6194SJosé Roberto de Souza 
245623ef6194SJosé Roberto de Souza 	/*
245723ef6194SJosé Roberto de Souza 	 * 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
245823ef6194SJosé Roberto de Souza 	 * Transport Select
245923ef6194SJosé Roberto de Souza 	 */
246023ef6194SJosé Roberto de Souza 	intel_ddi_config_transcoder_func(encoder, crtc_state);
246123ef6194SJosé Roberto de Souza 
246223ef6194SJosé Roberto de Souza 	/*
246323ef6194SJosé Roberto de Souza 	 * 6.e Program CoG/MSO configuration bits in DSS_CTL1 if selected.
246423ef6194SJosé Roberto de Souza 	 */
246523ef6194SJosé Roberto de Souza 	intel_ddi_mso_configure(crtc_state);
246623ef6194SJosé Roberto de Souza 
246723ef6194SJosé Roberto de Souza 	if (!is_mst)
246823ef6194SJosé Roberto de Souza 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
246923ef6194SJosé Roberto de Souza 
247023ef6194SJosé Roberto de Souza 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
247123ef6194SJosé Roberto de Souza 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
247223ef6194SJosé Roberto de Souza 	/*
247323ef6194SJosé Roberto de Souza 	 * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
247423ef6194SJosé Roberto de Souza 	 * in the FEC_CONFIGURATION register to 1 before initiating link
247523ef6194SJosé Roberto de Souza 	 * training
247623ef6194SJosé Roberto de Souza 	 */
247723ef6194SJosé Roberto de Souza 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
247823ef6194SJosé Roberto de Souza 
247923ef6194SJosé Roberto de Souza 	intel_dp_check_frl_training(intel_dp);
248023ef6194SJosé Roberto de Souza 	intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
248123ef6194SJosé Roberto de Souza 
248223ef6194SJosé Roberto de Souza 	/*
248323ef6194SJosé Roberto de Souza 	 * 6. The rest of the below are substeps under the bspec's "Enable and
248423ef6194SJosé Roberto de Souza 	 * Train Display Port" step.  Note that steps that are specific to
248523ef6194SJosé Roberto de Souza 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
248623ef6194SJosé Roberto de Souza 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
248723ef6194SJosé Roberto de Souza 	 * us when active_mst_links==0, so any steps designated for "single
248823ef6194SJosé Roberto de Souza 	 * stream or multi-stream master transcoder" can just be performed
248923ef6194SJosé Roberto de Souza 	 * unconditionally here.
249023ef6194SJosé Roberto de Souza 	 *
249123ef6194SJosé Roberto de Souza 	 * mtl_ddi_prepare_link_retrain() that is called by
249223ef6194SJosé Roberto de Souza 	 * intel_dp_start_link_train() will execute steps: 6.d, 6.f, 6.g, 6.h,
249323ef6194SJosé Roberto de Souza 	 * 6.i and 6.j
249423ef6194SJosé Roberto de Souza 	 *
249523ef6194SJosé Roberto de Souza 	 * 6.k Follow DisplayPort specification training sequence (see notes for
249623ef6194SJosé Roberto de Souza 	 *     failure handling)
249723ef6194SJosé Roberto de Souza 	 * 6.m If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
249823ef6194SJosé Roberto de Souza 	 *     Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
249923ef6194SJosé Roberto de Souza 	 *     (timeout after 800 us)
250023ef6194SJosé Roberto de Souza 	 */
250123ef6194SJosé Roberto de Souza 	intel_dp_start_link_train(intel_dp, crtc_state);
250223ef6194SJosé Roberto de Souza 
250323ef6194SJosé Roberto de Souza 	/* 6.n Set DP_TP_CTL link training to Normal */
250423ef6194SJosé Roberto de Souza 	if (!is_trans_port_sync_mode(crtc_state))
250523ef6194SJosé Roberto de Souza 		intel_dp_stop_link_train(intel_dp, crtc_state);
250623ef6194SJosé Roberto de Souza 
250723ef6194SJosé Roberto de Souza 	/* 6.o Configure and enable FEC if needed */
250823ef6194SJosé Roberto de Souza 	intel_ddi_enable_fec(encoder, crtc_state);
250923ef6194SJosé Roberto de Souza 
251023ef6194SJosé Roberto de Souza 	intel_dsc_dp_pps_write(encoder, crtc_state);
251123ef6194SJosé Roberto de Souza }
251223ef6194SJosé Roberto de Souza 
2513ede9771dSVille Syrjälä static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
2514ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
251599389390SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state,
251699389390SJosé Roberto de Souza 				  const struct drm_connector_state *conn_state)
251799389390SJosé Roberto de Souza {
2518b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
251999389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2520b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
252199389390SJosé Roberto de Souza 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
252299389390SJosé Roberto de Souza 
2523a621860aSVille Syrjälä 	intel_dp_set_link_params(intel_dp,
2524a621860aSVille Syrjälä 				 crtc_state->port_clock,
2525a621860aSVille Syrjälä 				 crtc_state->lane_count);
252699389390SJosé Roberto de Souza 
25275e19c0b0SMatt Roper 	/*
25289f620f1dSVille Syrjälä 	 * We only configure what the register value will be here.  Actual
25299f620f1dSVille Syrjälä 	 * enabling happens during link training farther down.
25309f620f1dSVille Syrjälä 	 */
25319f620f1dSVille Syrjälä 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
25329f620f1dSVille Syrjälä 
25339f620f1dSVille Syrjälä 	/*
25345e19c0b0SMatt Roper 	 * 1. Enable Power Wells
25355e19c0b0SMatt Roper 	 *
25365e19c0b0SMatt Roper 	 * This was handled at the beginning of intel_atomic_commit_tail(),
25375e19c0b0SMatt Roper 	 * before we called down into this function.
25385e19c0b0SMatt Roper 	 */
253999389390SJosé Roberto de Souza 
25405e19c0b0SMatt Roper 	/* 2. Enable Panel Power if PPS is required */
2541eb46f498SJani Nikula 	intel_pps_on(intel_dp);
254299389390SJosé Roberto de Souza 
254399389390SJosé Roberto de Souza 	/*
25445e19c0b0SMatt Roper 	 * 3. For non-TBT Type-C ports, set FIA lane count
25455e19c0b0SMatt Roper 	 * (DFLEXDPSP.DPX4TXLATC)
25465e19c0b0SMatt Roper 	 *
25475e19c0b0SMatt Roper 	 * This was done before tgl_ddi_pre_enable_dp by
25481e98f88cSLucas De Marchi 	 * hsw_crtc_enable()->intel_encoders_pre_pll_enable().
254999389390SJosé Roberto de Souza 	 */
255099389390SJosé Roberto de Souza 
25515e19c0b0SMatt Roper 	/*
25525e19c0b0SMatt Roper 	 * 4. Enable the port PLL.
25535e19c0b0SMatt Roper 	 *
25545e19c0b0SMatt Roper 	 * The PLL enabling itself was already done before this function by
25551e98f88cSLucas De Marchi 	 * hsw_crtc_enable()->intel_enable_shared_dpll().  We need only
25565e19c0b0SMatt Roper 	 * configure the PLL to port mapping here.
25575e19c0b0SMatt Roper 	 */
2558c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
25596171e58bSClinton A Taylor 
25605e19c0b0SMatt Roper 	/* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */
256111a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2562a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2563a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
256499389390SJosé Roberto de Souza 								   dig_port->ddi_io_power_domain);
2565a4550977SImre Deak 	}
256699389390SJosé Roberto de Souza 
25675e19c0b0SMatt Roper 	/* 6. Program DP_MODE */
25683b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
256999389390SJosé Roberto de Souza 
257099389390SJosé Roberto de Souza 	/*
25715e19c0b0SMatt Roper 	 * 7. The rest of the below are substeps under the bspec's "Enable and
25725e19c0b0SMatt Roper 	 * Train Display Port" step.  Note that steps that are specific to
25735e19c0b0SMatt Roper 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
25745e19c0b0SMatt Roper 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
25755e19c0b0SMatt Roper 	 * us when active_mst_links==0, so any steps designated for "single
25765e19c0b0SMatt Roper 	 * stream or multi-stream master transcoder" can just be performed
25775e19c0b0SMatt Roper 	 * unconditionally here.
25785e19c0b0SMatt Roper 	 */
25795e19c0b0SMatt Roper 
25805e19c0b0SMatt Roper 	/*
25815e19c0b0SMatt Roper 	 * 7.a Configure Transcoder Clock Select to direct the Port clock to the
25825e19c0b0SMatt Roper 	 * Transcoder.
258399389390SJosé Roberto de Souza 	 */
258455a4679eSVille Syrjälä 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
258599389390SJosé Roberto de Souza 
2586fe6959a6SVille Syrjälä 	if (HAS_DP20(dev_priv))
2587fe6959a6SVille Syrjälä 		intel_ddi_config_transcoder_dp2(encoder, crtc_state);
2588fe6959a6SVille Syrjälä 
25895e19c0b0SMatt Roper 	/*
25905e19c0b0SMatt Roper 	 * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
25915e19c0b0SMatt Roper 	 * Transport Select
25925e19c0b0SMatt Roper 	 */
2593eed22a46SVille Syrjälä 	intel_ddi_config_transcoder_func(encoder, crtc_state);
259499389390SJosé Roberto de Souza 
25955e19c0b0SMatt Roper 	/*
25965e19c0b0SMatt Roper 	 * 7.c Configure & enable DP_TP_CTL with link training pattern 1
25975e19c0b0SMatt Roper 	 * selected
25985e19c0b0SMatt Roper 	 *
25995e19c0b0SMatt Roper 	 * This will be handled by the intel_dp_start_link_train() farther
26005e19c0b0SMatt Roper 	 * down this function.
26015e19c0b0SMatt Roper 	 */
26025e19c0b0SMatt Roper 
26035e19c0b0SMatt Roper 	/* 7.e Configure voltage swing and related IO settings */
2604e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
260599389390SJosé Roberto de Souza 
26065e19c0b0SMatt Roper 	/*
26075e19c0b0SMatt Roper 	 * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up
26085e19c0b0SMatt Roper 	 * the used lanes of the DDI.
26095e19c0b0SMatt Roper 	 */
26105cdf706fSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
261199389390SJosé Roberto de Souza 
26125e19c0b0SMatt Roper 	/*
2613bc71194eSJani Nikula 	 * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected.
2614bc71194eSJani Nikula 	 */
2615bc71194eSJani Nikula 	intel_ddi_mso_configure(crtc_state);
2616bc71194eSJani Nikula 
261799389390SJosé Roberto de Souza 	if (!is_mst)
26180e634efdSVille Syrjälä 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
261999389390SJosé Roberto de Souza 
2620522508b6SAnkit Nautiyal 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
262199389390SJosé Roberto de Souza 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
262299389390SJosé Roberto de Souza 	/*
262399389390SJosé Roberto de Souza 	 * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
262499389390SJosé Roberto de Souza 	 * in the FEC_CONFIGURATION register to 1 before initiating link
262599389390SJosé Roberto de Souza 	 * training
262699389390SJosé Roberto de Souza 	 */
262799389390SJosé Roberto de Souza 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
26285e19c0b0SMatt Roper 
26294f3dd47aSAnkit Nautiyal 	intel_dp_check_frl_training(intel_dp);
263010fec80bSAnkit Nautiyal 	intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
26314f3dd47aSAnkit Nautiyal 
26325e19c0b0SMatt Roper 	/*
26335e19c0b0SMatt Roper 	 * 7.i Follow DisplayPort specification training sequence (see notes for
26345e19c0b0SMatt Roper 	 *     failure handling)
26355e19c0b0SMatt Roper 	 * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
26365e19c0b0SMatt Roper 	 *     Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
26375e19c0b0SMatt Roper 	 *     (timeout after 800 us)
26385e19c0b0SMatt Roper 	 */
2639a621860aSVille Syrjälä 	intel_dp_start_link_train(intel_dp, crtc_state);
264099389390SJosé Roberto de Souza 
26415e19c0b0SMatt Roper 	/* 7.k Set DP_TP_CTL link training to Normal */
2642eadf6f91SManasi Navare 	if (!is_trans_port_sync_mode(crtc_state))
2643a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
264499389390SJosé Roberto de Souza 
26455e19c0b0SMatt Roper 	/* 7.l Configure and enable FEC if needed */
264699389390SJosé Roberto de Souza 	intel_ddi_enable_fec(encoder, crtc_state);
26473126977dSVille Syrjälä 
26483126977dSVille Syrjälä 	intel_dsc_dp_pps_write(encoder, crtc_state);
264999389390SJosé Roberto de Souza }
265099389390SJosé Roberto de Souza 
2651ede9771dSVille Syrjälä static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
2652ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
2653379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state,
2654379bc100SJani Nikula 				  const struct drm_connector_state *conn_state)
2655379bc100SJani Nikula {
2656b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2657379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2658379bc100SJani Nikula 	enum port port = encoder->port;
2659b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2660379bc100SJani Nikula 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
2661379bc100SJani Nikula 
2662005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) < 11)
26631de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm,
26641de143ccSPankaj Bharadiya 			    is_mst && (port == PORT_A || port == PORT_E));
2665542dfab5SJosé Roberto de Souza 	else
26661de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm, is_mst && port == PORT_A);
2667379bc100SJani Nikula 
2668a621860aSVille Syrjälä 	intel_dp_set_link_params(intel_dp,
2669a621860aSVille Syrjälä 				 crtc_state->port_clock,
2670a621860aSVille Syrjälä 				 crtc_state->lane_count);
2671379bc100SJani Nikula 
26729f620f1dSVille Syrjälä 	/*
26739f620f1dSVille Syrjälä 	 * We only configure what the register value will be here.  Actual
26749f620f1dSVille Syrjälä 	 * enabling happens during link training farther down.
26759f620f1dSVille Syrjälä 	 */
26769f620f1dSVille Syrjälä 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
26779f620f1dSVille Syrjälä 
2678eb46f498SJani Nikula 	intel_pps_on(intel_dp);
2679379bc100SJani Nikula 
2680c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
2681379bc100SJani Nikula 
268211a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2683a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2684a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
26853b2ed431SImre Deak 								   dig_port->ddi_io_power_domain);
2686a4550977SImre Deak 	}
2687379bc100SJani Nikula 
26883b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
2689379bc100SJani Nikula 
26905bafd85dSVille Syrjälä 	if (has_buf_trans_select(dev_priv))
2691266152aeSVille Syrjälä 		hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
2692379bc100SJani Nikula 
2693e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
2694e722ab8bSVille Syrjälä 
26955cdf706fSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
2696379bc100SJani Nikula 
2697379bc100SJani Nikula 	if (!is_mst)
26980e634efdSVille Syrjälä 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
2699522508b6SAnkit Nautiyal 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
2700379bc100SJani Nikula 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
2701379bc100SJani Nikula 					      true);
2702379bc100SJani Nikula 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
2703a621860aSVille Syrjälä 	intel_dp_start_link_train(intel_dp, crtc_state);
2704005e9537SMatt Roper 	if ((port != PORT_A || DISPLAY_VER(dev_priv) >= 9) &&
2705eadf6f91SManasi Navare 	    !is_trans_port_sync_mode(crtc_state))
2706a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
2707379bc100SJani Nikula 
2708379bc100SJani Nikula 	intel_ddi_enable_fec(encoder, crtc_state);
2709379bc100SJani Nikula 
2710379bc100SJani Nikula 	if (!is_mst)
271155a4679eSVille Syrjälä 		intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2712379bc100SJani Nikula 
27133126977dSVille Syrjälä 	intel_dsc_dp_pps_write(encoder, crtc_state);
2714379bc100SJani Nikula }
2715379bc100SJani Nikula 
2716ede9771dSVille Syrjälä static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
2717ede9771dSVille Syrjälä 				    struct intel_encoder *encoder,
271899389390SJosé Roberto de Souza 				    const struct intel_crtc_state *crtc_state,
271999389390SJosé Roberto de Souza 				    const struct drm_connector_state *conn_state)
272099389390SJosé Roberto de Souza {
272199389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
272299389390SJosé Roberto de Souza 
27231a324a40SArun R Murthy 	if (HAS_DP20(dev_priv))
27241a324a40SArun R Murthy 		intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
27251a324a40SArun R Murthy 					    crtc_state);
27261a324a40SArun R Murthy 
272723ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14)
272823ef6194SJosé Roberto de Souza 		mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
272923ef6194SJosé Roberto de Souza 	else if (DISPLAY_VER(dev_priv) >= 12)
2730ede9771dSVille Syrjälä 		tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
273199389390SJosé Roberto de Souza 	else
2732ede9771dSVille Syrjälä 		hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
27330c06fa15SGwan-gyeong Mun 
2734bd8c9ccaSGwan-gyeong Mun 	/* MST will call a setting of MSA after an allocating of Virtual Channel
2735bd8c9ccaSGwan-gyeong Mun 	 * from MST encoder pre_enable callback.
2736bd8c9ccaSGwan-gyeong Mun 	 */
27378de5df3bSVille Syrjälä 	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
27380c06fa15SGwan-gyeong Mun 		intel_ddi_set_dp_msa(crtc_state, conn_state);
27391fc1e8d4SJosé Roberto de Souza }
274099389390SJosé Roberto de Souza 
2741ede9771dSVille Syrjälä static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
2742ede9771dSVille Syrjälä 				      struct intel_encoder *encoder,
2743379bc100SJani Nikula 				      const struct intel_crtc_state *crtc_state,
2744379bc100SJani Nikula 				      const struct drm_connector_state *conn_state)
2745379bc100SJani Nikula {
27460ba7ffeaSLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
27470ba7ffeaSLucas De Marchi 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
2748379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2749379bc100SJani Nikula 
2750379bc100SJani Nikula 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
2751c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
2752379bc100SJani Nikula 
2753a4550977SImre Deak 	drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2754a4550977SImre Deak 	dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
2755a4550977SImre Deak 							   dig_port->ddi_io_power_domain);
2756379bc100SJani Nikula 
27573b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
2758379bc100SJani Nikula 
275955a4679eSVille Syrjälä 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2760379bc100SJani Nikula 
27610ba7ffeaSLucas De Marchi 	dig_port->set_infoframes(encoder,
2762379bc100SJani Nikula 				 crtc_state->has_infoframe,
2763379bc100SJani Nikula 				 crtc_state, conn_state);
2764379bc100SJani Nikula }
2765379bc100SJani Nikula 
2766ede9771dSVille Syrjälä static void intel_ddi_pre_enable(struct intel_atomic_state *state,
2767ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
2768379bc100SJani Nikula 				 const struct intel_crtc_state *crtc_state,
2769379bc100SJani Nikula 				 const struct drm_connector_state *conn_state)
2770379bc100SJani Nikula {
27712225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2772379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2773379bc100SJani Nikula 	enum pipe pipe = crtc->pipe;
2774379bc100SJani Nikula 
2775379bc100SJani Nikula 	/*
2776379bc100SJani Nikula 	 * When called from DP MST code:
2777379bc100SJani Nikula 	 * - conn_state will be NULL
2778379bc100SJani Nikula 	 * - encoder will be the main encoder (ie. mst->primary)
2779379bc100SJani Nikula 	 * - the main connector associated with this port
2780379bc100SJani Nikula 	 *   won't be active or linked to a crtc
2781379bc100SJani Nikula 	 * - crtc_state will be the state of the first stream to
2782379bc100SJani Nikula 	 *   be activated on this port, and it may not be the same
2783379bc100SJani Nikula 	 *   stream that will be deactivated last, but each stream
2784379bc100SJani Nikula 	 *   should have a state that is identical when it comes to
2785379bc100SJani Nikula 	 *   the DP link parameteres
2786379bc100SJani Nikula 	 */
2787379bc100SJani Nikula 
27881de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
2789379bc100SJani Nikula 
2790379bc100SJani Nikula 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
2791379bc100SJani Nikula 
2792379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
2793ede9771dSVille Syrjälä 		intel_ddi_pre_enable_hdmi(state, encoder, crtc_state,
2794ede9771dSVille Syrjälä 					  conn_state);
2795379bc100SJani Nikula 	} else {
2796f7af425dSVille Syrjälä 		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2797379bc100SJani Nikula 
2798ede9771dSVille Syrjälä 		intel_ddi_pre_enable_dp(state, encoder, crtc_state,
2799ede9771dSVille Syrjälä 					conn_state);
2800379bc100SJani Nikula 
2801f7af425dSVille Syrjälä 		/* FIXME precompute everything properly */
28020ea02bb8SJosé Roberto de Souza 		/* FIXME how do we turn infoframes off again? */
2803f7af425dSVille Syrjälä 		if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
2804379bc100SJani Nikula 			dig_port->set_infoframes(encoder,
2805379bc100SJani Nikula 						 crtc_state->has_infoframe,
2806379bc100SJani Nikula 						 crtc_state, conn_state);
2807379bc100SJani Nikula 	}
2808379bc100SJani Nikula }
2809379bc100SJani Nikula 
281023ef6194SJosé Roberto de Souza static void
281123ef6194SJosé Roberto de Souza mtl_ddi_disable_d2d_link(struct intel_encoder *encoder)
281223ef6194SJosé Roberto de Souza {
281323ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
281423ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
281523ef6194SJosé Roberto de Souza 
281623ef6194SJosé Roberto de Souza 	intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port),
281723ef6194SJosé Roberto de Souza 		     XELPDP_PORT_BUF_D2D_LINK_ENABLE, 0);
281823ef6194SJosé Roberto de Souza 
281923ef6194SJosé Roberto de Souza 	if (wait_for_us(!(intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) &
282023ef6194SJosé Roberto de Souza 			  XELPDP_PORT_BUF_D2D_LINK_STATE), 100))
282123ef6194SJosé Roberto de Souza 		drm_err(&dev_priv->drm, "Timeout waiting for D2D Link disable for PORT_BUF_CTL %c\n",
282223ef6194SJosé Roberto de Souza 			port_name(port));
282323ef6194SJosé Roberto de Souza }
282423ef6194SJosé Roberto de Souza 
282523ef6194SJosé Roberto de Souza static void mtl_disable_ddi_buf(struct intel_encoder *encoder,
282623ef6194SJosé Roberto de Souza 				const struct intel_crtc_state *crtc_state)
282723ef6194SJosé Roberto de Souza {
282823ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
282923ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
283023ef6194SJosé Roberto de Souza 	u32 val;
283123ef6194SJosé Roberto de Souza 
283223ef6194SJosé Roberto de Souza 	/* 3.b Clear DDI_CTL_DE Enable to 0. */
283323ef6194SJosé Roberto de Souza 	val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
283423ef6194SJosé Roberto de Souza 	if (val & DDI_BUF_CTL_ENABLE) {
283523ef6194SJosé Roberto de Souza 		val &= ~DDI_BUF_CTL_ENABLE;
283623ef6194SJosé Roberto de Souza 		intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
283723ef6194SJosé Roberto de Souza 
283823ef6194SJosé Roberto de Souza 		/* 3.c Poll for PORT_BUF_CTL Idle Status == 1, timeout after 100us */
283923ef6194SJosé Roberto de Souza 		mtl_wait_ddi_buf_idle(dev_priv, port);
284023ef6194SJosé Roberto de Souza 	}
284123ef6194SJosé Roberto de Souza 
284223ef6194SJosé Roberto de Souza 	/* 3.d Disable D2D Link */
284323ef6194SJosé Roberto de Souza 	mtl_ddi_disable_d2d_link(encoder);
284423ef6194SJosé Roberto de Souza 
284523ef6194SJosé Roberto de Souza 	/* 3.e Disable DP_TP_CTL */
284623ef6194SJosé Roberto de Souza 	if (intel_crtc_has_dp_encoder(crtc_state)) {
284723ef6194SJosé Roberto de Souza 		intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
284823ef6194SJosé Roberto de Souza 			     DP_TP_CTL_ENABLE, 0);
284923ef6194SJosé Roberto de Souza 	}
285023ef6194SJosé Roberto de Souza }
285123ef6194SJosé Roberto de Souza 
285223ef6194SJosé Roberto de Souza static void disable_ddi_buf(struct intel_encoder *encoder,
2853379bc100SJani Nikula 			    const struct intel_crtc_state *crtc_state)
2854379bc100SJani Nikula {
2855379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2856379bc100SJani Nikula 	enum port port = encoder->port;
2857379bc100SJani Nikula 	bool wait = false;
2858379bc100SJani Nikula 	u32 val;
2859379bc100SJani Nikula 
2860f7960e7fSJani Nikula 	val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
2861379bc100SJani Nikula 	if (val & DDI_BUF_CTL_ENABLE) {
2862379bc100SJani Nikula 		val &= ~DDI_BUF_CTL_ENABLE;
2863f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
2864379bc100SJani Nikula 		wait = true;
2865379bc100SJani Nikula 	}
2866379bc100SJani Nikula 
28678910d8b7SAndrzej Hajda 	if (intel_crtc_has_dp_encoder(crtc_state))
28688910d8b7SAndrzej Hajda 		intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
28698c042949SVille Syrjälä 			     DP_TP_CTL_ENABLE, 0);
2870379bc100SJani Nikula 
2871379bc100SJani Nikula 	/* Disable FEC in DP Sink */
2872379bc100SJani Nikula 	intel_ddi_disable_fec_state(encoder, crtc_state);
2873379bc100SJani Nikula 
2874379bc100SJani Nikula 	if (wait)
2875379bc100SJani Nikula 		intel_wait_ddi_buf_idle(dev_priv, port);
2876379bc100SJani Nikula }
2877379bc100SJani Nikula 
287823ef6194SJosé Roberto de Souza static void intel_disable_ddi_buf(struct intel_encoder *encoder,
287923ef6194SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state)
288023ef6194SJosé Roberto de Souza {
288123ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
288223ef6194SJosé Roberto de Souza 
288323ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14) {
288423ef6194SJosé Roberto de Souza 		mtl_disable_ddi_buf(encoder, crtc_state);
288523ef6194SJosé Roberto de Souza 
288623ef6194SJosé Roberto de Souza 		/* 3.f Disable DP_TP_CTL FEC Enable if it is needed */
288723ef6194SJosé Roberto de Souza 		intel_ddi_disable_fec_state(encoder, crtc_state);
288823ef6194SJosé Roberto de Souza 	} else {
288923ef6194SJosé Roberto de Souza 		disable_ddi_buf(encoder, crtc_state);
289023ef6194SJosé Roberto de Souza 	}
289123ef6194SJosé Roberto de Souza }
289223ef6194SJosé Roberto de Souza 
2893ede9771dSVille Syrjälä static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
2894ede9771dSVille Syrjälä 				      struct intel_encoder *encoder,
2895379bc100SJani Nikula 				      const struct intel_crtc_state *old_crtc_state,
2896379bc100SJani Nikula 				      const struct drm_connector_state *old_conn_state)
2897379bc100SJani Nikula {
2898379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2899b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2900379bc100SJani Nikula 	struct intel_dp *intel_dp = &dig_port->dp;
290123ef6194SJosé Roberto de Souza 	intel_wakeref_t wakeref;
2902379bc100SJani Nikula 	bool is_mst = intel_crtc_has_type(old_crtc_state,
2903379bc100SJani Nikula 					  INTEL_OUTPUT_DP_MST);
2904379bc100SJani Nikula 
2905c980216dSImre Deak 	if (!is_mst)
2906c980216dSImre Deak 		intel_dp_set_infoframes(encoder, false,
2907c980216dSImre Deak 					old_crtc_state, old_conn_state);
2908fa37a213SGwan-gyeong Mun 
2909379bc100SJani Nikula 	/*
2910379bc100SJani Nikula 	 * Power down sink before disabling the port, otherwise we end
2911379bc100SJani Nikula 	 * up getting interrupts from the sink on detecting link loss.
2912379bc100SJani Nikula 	 */
29130e634efdSVille Syrjälä 	intel_dp_set_power(intel_dp, DP_SET_POWER_D3);
291478eaaba3SJosé Roberto de Souza 
2915005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2916c59053dcSJosé Roberto de Souza 		if (is_mst) {
2917c59053dcSJosé Roberto de Souza 			enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
2918c59053dcSJosé Roberto de Souza 
29198910d8b7SAndrzej Hajda 			intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
29208910d8b7SAndrzej Hajda 				     TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK,
29218910d8b7SAndrzej Hajda 				     0);
2922c59053dcSJosé Roberto de Souza 		}
2923c59053dcSJosé Roberto de Souza 	} else {
2924c59053dcSJosé Roberto de Souza 		if (!is_mst)
292555a4679eSVille Syrjälä 			intel_ddi_disable_transcoder_clock(old_crtc_state);
2926c59053dcSJosé Roberto de Souza 	}
2927379bc100SJani Nikula 
2928379bc100SJani Nikula 	intel_disable_ddi_buf(encoder, old_crtc_state);
2929379bc100SJani Nikula 
29303ca8f191SJosé Roberto de Souza 	/*
29313ca8f191SJosé Roberto de Souza 	 * From TGL spec: "If single stream or multi-stream master transcoder:
29323ca8f191SJosé Roberto de Souza 	 * Configure Transcoder Clock select to direct no clock to the
29333ca8f191SJosé Roberto de Souza 	 * transcoder"
29343ca8f191SJosé Roberto de Souza 	 */
2935005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
293655a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
29373ca8f191SJosé Roberto de Souza 
2938eb46f498SJani Nikula 	intel_pps_vdd_on(intel_dp);
2939eb46f498SJani Nikula 	intel_pps_off(intel_dp);
2940379bc100SJani Nikula 
294123ef6194SJosé Roberto de Souza 	wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
294223ef6194SJosé Roberto de Souza 
294323ef6194SJosé Roberto de Souza 	if (wakeref)
2944a4550977SImre Deak 		intel_display_power_put(dev_priv,
2945a4550977SImre Deak 					dig_port->ddi_io_power_domain,
294623ef6194SJosé Roberto de Souza 					wakeref);
2947379bc100SJani Nikula 
2948c133df69SVille Syrjälä 	intel_ddi_disable_clock(encoder);
294923ef6194SJosé Roberto de Souza 
295023ef6194SJosé Roberto de Souza 	/* De-select Thunderbolt */
295123ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14)
295223ef6194SJosé Roberto de Souza 		intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(encoder->port),
295323ef6194SJosé Roberto de Souza 			     XELPDP_PORT_BUF_IO_SELECT_TBT, 0);
2954379bc100SJani Nikula }
2955379bc100SJani Nikula 
2956ede9771dSVille Syrjälä static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
2957ede9771dSVille Syrjälä 					struct intel_encoder *encoder,
2958379bc100SJani Nikula 					const struct intel_crtc_state *old_crtc_state,
2959379bc100SJani Nikula 					const struct drm_connector_state *old_conn_state)
2960379bc100SJani Nikula {
2961379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2962b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2963379bc100SJani Nikula 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
296423ef6194SJosé Roberto de Souza 	intel_wakeref_t wakeref;
2965379bc100SJani Nikula 
2966379bc100SJani Nikula 	dig_port->set_infoframes(encoder, false,
2967379bc100SJani Nikula 				 old_crtc_state, old_conn_state);
2968379bc100SJani Nikula 
2969c1949189SImre Deak 	if (DISPLAY_VER(dev_priv) < 12)
297055a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
2971379bc100SJani Nikula 
2972379bc100SJani Nikula 	intel_disable_ddi_buf(encoder, old_crtc_state);
2973379bc100SJani Nikula 
2974c1949189SImre Deak 	if (DISPLAY_VER(dev_priv) >= 12)
297555a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
2976c1949189SImre Deak 
297723ef6194SJosé Roberto de Souza 	wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
297823ef6194SJosé Roberto de Souza 	if (wakeref)
2979a4550977SImre Deak 		intel_display_power_put(dev_priv,
2980a4550977SImre Deak 					dig_port->ddi_io_power_domain,
298123ef6194SJosé Roberto de Souza 					wakeref);
2982379bc100SJani Nikula 
2983c133df69SVille Syrjälä 	intel_ddi_disable_clock(encoder);
2984379bc100SJani Nikula 
2985379bc100SJani Nikula 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
2986379bc100SJani Nikula }
2987379bc100SJani Nikula 
2988ede9771dSVille Syrjälä static void intel_ddi_post_disable(struct intel_atomic_state *state,
2989ede9771dSVille Syrjälä 				   struct intel_encoder *encoder,
2990379bc100SJani Nikula 				   const struct intel_crtc_state *old_crtc_state,
2991379bc100SJani Nikula 				   const struct drm_connector_state *old_conn_state)
2992379bc100SJani Nikula {
2993379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2994a6e7a006SVille Syrjälä 	struct intel_crtc *slave_crtc;
2995379bc100SJani Nikula 
29967829c92bSVille Syrjälä 	if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) {
2997773b4b54SVille Syrjälä 		intel_crtc_vblank_off(old_crtc_state);
2998773b4b54SVille Syrjälä 
29990504d0acSVille Syrjälä 		intel_disable_transcoder(old_crtc_state);
30000504d0acSVille Syrjälä 
3001773b4b54SVille Syrjälä 		intel_ddi_disable_transcoder_func(old_crtc_state);
3002773b4b54SVille Syrjälä 
3003773b4b54SVille Syrjälä 		intel_dsc_disable(old_crtc_state);
3004773b4b54SVille Syrjälä 
3005005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 9)
3006f6df4d46SLucas De Marchi 			skl_scaler_disable(old_crtc_state);
3007773b4b54SVille Syrjälä 		else
30089eae5e27SLucas De Marchi 			ilk_pfit_disable(old_crtc_state);
30097829c92bSVille Syrjälä 	}
3010773b4b54SVille Syrjälä 
3011a6e7a006SVille Syrjälä 	for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc,
3012a6e7a006SVille Syrjälä 					 intel_crtc_bigjoiner_slave_pipes(old_crtc_state)) {
30134e3cdb45SManasi Navare 		const struct intel_crtc_state *old_slave_crtc_state =
3014f2e19b58SVille Syrjälä 			intel_atomic_get_old_crtc_state(state, slave_crtc);
30154e3cdb45SManasi Navare 
30164e3cdb45SManasi Navare 		intel_crtc_vblank_off(old_slave_crtc_state);
30174e3cdb45SManasi Navare 
30184e3cdb45SManasi Navare 		intel_dsc_disable(old_slave_crtc_state);
30194e3cdb45SManasi Navare 		skl_scaler_disable(old_slave_crtc_state);
30204e3cdb45SManasi Navare 	}
30214e3cdb45SManasi Navare 
3022379bc100SJani Nikula 	/*
3023379bc100SJani Nikula 	 * When called from DP MST code:
3024379bc100SJani Nikula 	 * - old_conn_state will be NULL
3025379bc100SJani Nikula 	 * - encoder will be the main encoder (ie. mst->primary)
3026379bc100SJani Nikula 	 * - the main connector associated with this port
3027379bc100SJani Nikula 	 *   won't be active or linked to a crtc
3028379bc100SJani Nikula 	 * - old_crtc_state will be the state of the last stream to
3029379bc100SJani Nikula 	 *   be deactivated on this port, and it may not be the same
3030379bc100SJani Nikula 	 *   stream that was activated last, but each stream
3031379bc100SJani Nikula 	 *   should have a state that is identical when it comes to
3032379bc100SJani Nikula 	 *   the DP link parameteres
3033379bc100SJani Nikula 	 */
3034379bc100SJani Nikula 
3035379bc100SJani Nikula 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3036ede9771dSVille Syrjälä 		intel_ddi_post_disable_hdmi(state, encoder, old_crtc_state,
3037ede9771dSVille Syrjälä 					    old_conn_state);
3038379bc100SJani Nikula 	else
3039ede9771dSVille Syrjälä 		intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
3040ede9771dSVille Syrjälä 					  old_conn_state);
3041b108bdd0SImre Deak }
3042b108bdd0SImre Deak 
3043b108bdd0SImre Deak static void intel_ddi_post_pll_disable(struct intel_atomic_state *state,
3044b108bdd0SImre Deak 				       struct intel_encoder *encoder,
3045b108bdd0SImre Deak 				       const struct intel_crtc_state *old_crtc_state,
3046b108bdd0SImre Deak 				       const struct drm_connector_state *old_conn_state)
3047b108bdd0SImre Deak {
3048b108bdd0SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3049b108bdd0SImre Deak 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3050b108bdd0SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
3051b108bdd0SImre Deak 	bool is_tc_port = intel_phy_is_tc(i915, phy);
3052379bc100SJani Nikula 
3053637c7aa2SImre Deak 	main_link_aux_power_domain_put(dig_port, old_crtc_state);
305417bef9baSVille Syrjälä 
305517bef9baSVille Syrjälä 	if (is_tc_port)
305617bef9baSVille Syrjälä 		intel_tc_port_put_link(dig_port);
3057379bc100SJani Nikula }
3058379bc100SJani Nikula 
3059d82a855aSVille Syrjälä static void trans_port_sync_stop_link_train(struct intel_atomic_state *state,
3060d82a855aSVille Syrjälä 					    struct intel_encoder *encoder,
3061d82a855aSVille Syrjälä 					    const struct intel_crtc_state *crtc_state)
3062d82a855aSVille Syrjälä {
3063d82a855aSVille Syrjälä 	const struct drm_connector_state *conn_state;
3064d82a855aSVille Syrjälä 	struct drm_connector *conn;
3065d82a855aSVille Syrjälä 	int i;
3066d82a855aSVille Syrjälä 
3067d82a855aSVille Syrjälä 	if (!crtc_state->sync_mode_slaves_mask)
3068d82a855aSVille Syrjälä 		return;
3069d82a855aSVille Syrjälä 
3070d82a855aSVille Syrjälä 	for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
3071d82a855aSVille Syrjälä 		struct intel_encoder *slave_encoder =
3072d82a855aSVille Syrjälä 			to_intel_encoder(conn_state->best_encoder);
3073d82a855aSVille Syrjälä 		struct intel_crtc *slave_crtc = to_intel_crtc(conn_state->crtc);
3074d82a855aSVille Syrjälä 		const struct intel_crtc_state *slave_crtc_state;
3075d82a855aSVille Syrjälä 
3076d82a855aSVille Syrjälä 		if (!slave_crtc)
3077d82a855aSVille Syrjälä 			continue;
3078d82a855aSVille Syrjälä 
3079d82a855aSVille Syrjälä 		slave_crtc_state =
3080d82a855aSVille Syrjälä 			intel_atomic_get_new_crtc_state(state, slave_crtc);
3081d82a855aSVille Syrjälä 
3082d82a855aSVille Syrjälä 		if (slave_crtc_state->master_transcoder !=
3083d82a855aSVille Syrjälä 		    crtc_state->cpu_transcoder)
3084d82a855aSVille Syrjälä 			continue;
3085d82a855aSVille Syrjälä 
3086a621860aSVille Syrjälä 		intel_dp_stop_link_train(enc_to_intel_dp(slave_encoder),
3087a621860aSVille Syrjälä 					 slave_crtc_state);
3088d82a855aSVille Syrjälä 	}
3089d82a855aSVille Syrjälä 
3090d82a855aSVille Syrjälä 	usleep_range(200, 400);
3091d82a855aSVille Syrjälä 
3092a621860aSVille Syrjälä 	intel_dp_stop_link_train(enc_to_intel_dp(encoder),
3093a621860aSVille Syrjälä 				 crtc_state);
3094d82a855aSVille Syrjälä }
3095d82a855aSVille Syrjälä 
3096ede9771dSVille Syrjälä static void intel_enable_ddi_dp(struct intel_atomic_state *state,
3097ede9771dSVille Syrjälä 				struct intel_encoder *encoder,
3098379bc100SJani Nikula 				const struct intel_crtc_state *crtc_state,
3099379bc100SJani Nikula 				const struct drm_connector_state *conn_state)
3100379bc100SJani Nikula {
3101379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3102b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3103998cc864SUma Shankar 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3104379bc100SJani Nikula 	enum port port = encoder->port;
3105379bc100SJani Nikula 
3106005e9537SMatt Roper 	if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
3107a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
3108379bc100SJani Nikula 
31096306d8dbSHans de Goede 	drm_connector_update_privacy_screen(conn_state);
3110379bc100SJani Nikula 	intel_edp_backlight_on(crtc_state, conn_state);
3111998cc864SUma Shankar 
3112998cc864SUma Shankar 	if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
31131bf3657cSGwan-gyeong Mun 		intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3114998cc864SUma Shankar 
3115379bc100SJani Nikula 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
3116d82a855aSVille Syrjälä 
3117d82a855aSVille Syrjälä 	trans_port_sync_stop_link_train(state, encoder, crtc_state);
3118379bc100SJani Nikula }
3119379bc100SJani Nikula 
3120379bc100SJani Nikula static i915_reg_t
3121379bc100SJani Nikula gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
3122379bc100SJani Nikula 			       enum port port)
3123379bc100SJani Nikula {
312412c4d4c1SVille Syrjälä 	static const enum transcoder trans[] = {
312512c4d4c1SVille Syrjälä 		[PORT_A] = TRANSCODER_EDP,
312612c4d4c1SVille Syrjälä 		[PORT_B] = TRANSCODER_A,
312712c4d4c1SVille Syrjälä 		[PORT_C] = TRANSCODER_B,
312812c4d4c1SVille Syrjälä 		[PORT_D] = TRANSCODER_C,
312912c4d4c1SVille Syrjälä 		[PORT_E] = TRANSCODER_A,
3130379bc100SJani Nikula 	};
3131379bc100SJani Nikula 
3132005e9537SMatt Roper 	drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9);
3133379bc100SJani Nikula 
31341de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E))
3135379bc100SJani Nikula 		port = PORT_A;
3136379bc100SJani Nikula 
313712c4d4c1SVille Syrjälä 	return CHICKEN_TRANS(trans[port]);
3138379bc100SJani Nikula }
3139379bc100SJani Nikula 
3140ede9771dSVille Syrjälä static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
3141ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
3142379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state,
3143379bc100SJani Nikula 				  const struct drm_connector_state *conn_state)
3144379bc100SJani Nikula {
3145379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3146b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3147379bc100SJani Nikula 	struct drm_connector *connector = conn_state->connector;
3148379bc100SJani Nikula 	enum port port = encoder->port;
3149e99ba962SImre Deak 	enum phy phy = intel_port_to_phy(dev_priv, port);
3150e99ba962SImre Deak 	u32 buf_ctl;
3151379bc100SJani Nikula 
3152379bc100SJani Nikula 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3153379bc100SJani Nikula 					       crtc_state->hdmi_high_tmds_clock_ratio,
3154379bc100SJani Nikula 					       crtc_state->hdmi_scrambling))
315547bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
315647bdb1caSJani Nikula 			    "[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
3157379bc100SJani Nikula 			    connector->base.id, connector->name);
3158379bc100SJani Nikula 
31595bafd85dSVille Syrjälä 	if (has_buf_trans_select(dev_priv))
3160e722ab8bSVille Syrjälä 		hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state);
3161c9b69041SVille Syrjälä 
3162b66a8abaSAnkit Nautiyal 	/* e. Enable D2D Link for C10/C20 Phy */
3163b66a8abaSAnkit Nautiyal 	if (DISPLAY_VER(dev_priv) >= 14)
3164b66a8abaSAnkit Nautiyal 		mtl_ddi_enable_d2d(encoder);
3165b66a8abaSAnkit Nautiyal 
3166e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
3167c9b69041SVille Syrjälä 
3168379bc100SJani Nikula 	/* Display WA #1143: skl,kbl,cfl */
316993e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
3170379bc100SJani Nikula 		/*
3171379bc100SJani Nikula 		 * For some reason these chicken bits have been
3172379bc100SJani Nikula 		 * stuffed into a transcoder register, event though
3173379bc100SJani Nikula 		 * the bits affect a specific DDI port rather than
3174379bc100SJani Nikula 		 * a specific transcoder.
3175379bc100SJani Nikula 		 */
3176379bc100SJani Nikula 		i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port);
3177379bc100SJani Nikula 		u32 val;
3178379bc100SJani Nikula 
3179f7960e7fSJani Nikula 		val = intel_de_read(dev_priv, reg);
3180379bc100SJani Nikula 
3181379bc100SJani Nikula 		if (port == PORT_E)
3182379bc100SJani Nikula 			val |= DDIE_TRAINING_OVERRIDE_ENABLE |
3183379bc100SJani Nikula 				DDIE_TRAINING_OVERRIDE_VALUE;
3184379bc100SJani Nikula 		else
3185379bc100SJani Nikula 			val |= DDI_TRAINING_OVERRIDE_ENABLE |
3186379bc100SJani Nikula 				DDI_TRAINING_OVERRIDE_VALUE;
3187379bc100SJani Nikula 
3188f7960e7fSJani Nikula 		intel_de_write(dev_priv, reg, val);
3189f7960e7fSJani Nikula 		intel_de_posting_read(dev_priv, reg);
3190379bc100SJani Nikula 
3191379bc100SJani Nikula 		udelay(1);
3192379bc100SJani Nikula 
3193379bc100SJani Nikula 		if (port == PORT_E)
3194379bc100SJani Nikula 			val &= ~(DDIE_TRAINING_OVERRIDE_ENABLE |
3195379bc100SJani Nikula 				 DDIE_TRAINING_OVERRIDE_VALUE);
3196379bc100SJani Nikula 		else
3197379bc100SJani Nikula 			val &= ~(DDI_TRAINING_OVERRIDE_ENABLE |
3198379bc100SJani Nikula 				 DDI_TRAINING_OVERRIDE_VALUE);
3199379bc100SJani Nikula 
3200f7960e7fSJani Nikula 		intel_de_write(dev_priv, reg, val);
3201379bc100SJani Nikula 	}
3202379bc100SJani Nikula 
32031e0cb7beSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
32041e0cb7beSVille Syrjälä 
3205379bc100SJani Nikula 	/* In HDMI/DVI mode, the port width, and swing/emphasis values
3206379bc100SJani Nikula 	 * are ignored so nothing special needs to be done besides
3207379bc100SJani Nikula 	 * enabling the port.
3208414002f1SImre Deak 	 *
3209414002f1SImre Deak 	 * On ADL_P the PHY link rate and lane count must be programmed but
3210414002f1SImre Deak 	 * these are both 0 for HDMI.
3211b66a8abaSAnkit Nautiyal 	 *
3212b66a8abaSAnkit Nautiyal 	 * But MTL onwards HDMI2.1 is supported and in TMDS mode this
3213b66a8abaSAnkit Nautiyal 	 * is filled with lane count, already set in the crtc_state.
3214b66a8abaSAnkit Nautiyal 	 * The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
3215379bc100SJani Nikula 	 */
3216e99ba962SImre Deak 	buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
3217b66a8abaSAnkit Nautiyal 	if (DISPLAY_VER(dev_priv) >= 14) {
3218b66a8abaSAnkit Nautiyal 		u8  lane_count = mtl_get_port_width(crtc_state->lane_count);
3219b66a8abaSAnkit Nautiyal 		u32 port_buf = 0;
3220b66a8abaSAnkit Nautiyal 
3221b66a8abaSAnkit Nautiyal 		port_buf |= XELPDP_PORT_WIDTH(lane_count);
3222b66a8abaSAnkit Nautiyal 
3223b66a8abaSAnkit Nautiyal 		if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
3224b66a8abaSAnkit Nautiyal 			port_buf |= XELPDP_PORT_REVERSAL;
3225b66a8abaSAnkit Nautiyal 
3226b66a8abaSAnkit Nautiyal 		intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port),
3227b66a8abaSAnkit Nautiyal 			     XELPDP_PORT_WIDTH_MASK | XELPDP_PORT_REVERSAL, port_buf);
3228b66a8abaSAnkit Nautiyal 
3229b66a8abaSAnkit Nautiyal 		buf_ctl |= DDI_PORT_WIDTH(lane_count);
3230b66a8abaSAnkit Nautiyal 	} else if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
3231e99ba962SImre Deak 		drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port));
3232e99ba962SImre Deak 		buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
3233e99ba962SImre Deak 	}
3234b66a8abaSAnkit Nautiyal 
3235e99ba962SImre Deak 	intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
3236379bc100SJani Nikula 
323765e75edaSAnkit Nautiyal 	intel_wait_ddi_buf_active(dev_priv, port);
323865e75edaSAnkit Nautiyal 
3239379bc100SJani Nikula 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
3240379bc100SJani Nikula }
3241379bc100SJani Nikula 
3242ede9771dSVille Syrjälä static void intel_enable_ddi(struct intel_atomic_state *state,
3243ede9771dSVille Syrjälä 			     struct intel_encoder *encoder,
3244379bc100SJani Nikula 			     const struct intel_crtc_state *crtc_state,
3245379bc100SJani Nikula 			     const struct drm_connector_state *conn_state)
3246379bc100SJani Nikula {
32478b4f2137SPankaj Bharadiya 	drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
324821fd23acSJani Nikula 
3249df529053SVille Syrjälä 	if (!intel_crtc_is_bigjoiner_slave(crtc_state))
3250eed22a46SVille Syrjälä 		intel_ddi_enable_transcoder_func(encoder, crtc_state);
32517c2fedd7SVille Syrjälä 
32528853750dSVinod Govindapillai 	/* Enable/Disable DP2.0 SDP split config before transcoder */
32538853750dSVinod Govindapillai 	intel_audio_sdp_split_update(encoder, crtc_state);
32548853750dSVinod Govindapillai 
32558c66081bSVille Syrjälä 	intel_enable_transcoder(crtc_state);
325621fd23acSJani Nikula 
325721fd23acSJani Nikula 	intel_crtc_vblank_on(crtc_state);
325821fd23acSJani Nikula 
3259379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
3260ede9771dSVille Syrjälä 		intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state);
3261379bc100SJani Nikula 	else
3262ede9771dSVille Syrjälä 		intel_enable_ddi_dp(state, encoder, crtc_state, conn_state);
3263379bc100SJani Nikula 
3264379bc100SJani Nikula 	/* Enable hdcp if it's desired */
3265379bc100SJani Nikula 	if (conn_state->content_protection ==
3266379bc100SJani Nikula 	    DRM_MODE_CONTENT_PROTECTION_DESIRED)
3267*4c4279a8SSuraj Kandpal 		intel_hdcp_enable(state, encoder, crtc_state, conn_state);
3268379bc100SJani Nikula }
3269379bc100SJani Nikula 
3270ede9771dSVille Syrjälä static void intel_disable_ddi_dp(struct intel_atomic_state *state,
3271ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
3272379bc100SJani Nikula 				 const struct intel_crtc_state *old_crtc_state,
3273379bc100SJani Nikula 				 const struct drm_connector_state *old_conn_state)
3274379bc100SJani Nikula {
3275b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3276379bc100SJani Nikula 
3277379bc100SJani Nikula 	intel_dp->link_trained = false;
3278379bc100SJani Nikula 
3279179db7c1SJani Nikula 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
3280f28c5950SVille Syrjälä 
3281f28c5950SVille Syrjälä 	intel_psr_disable(intel_dp, old_crtc_state);
3282379bc100SJani Nikula 	intel_edp_backlight_off(old_conn_state);
3283379bc100SJani Nikula 	/* Disable the decompression in DP Sink */
3284379bc100SJani Nikula 	intel_dp_sink_set_decompression_state(intel_dp, old_crtc_state,
3285379bc100SJani Nikula 					      false);
32861639406aSManasi Navare 	/* Disable Ignore_MSA bit in DP Sink */
32871639406aSManasi Navare 	intel_dp_sink_set_msa_timing_par_ignore_state(intel_dp, old_crtc_state,
32881639406aSManasi Navare 						      false);
3289379bc100SJani Nikula }
3290379bc100SJani Nikula 
3291ede9771dSVille Syrjälä static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
3292ede9771dSVille Syrjälä 				   struct intel_encoder *encoder,
3293379bc100SJani Nikula 				   const struct intel_crtc_state *old_crtc_state,
3294379bc100SJani Nikula 				   const struct drm_connector_state *old_conn_state)
3295379bc100SJani Nikula {
329647bdb1caSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3297379bc100SJani Nikula 	struct drm_connector *connector = old_conn_state->connector;
3298379bc100SJani Nikula 
3299179db7c1SJani Nikula 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
3300f28c5950SVille Syrjälä 
3301379bc100SJani Nikula 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3302379bc100SJani Nikula 					       false, false))
330347bdb1caSJani Nikula 		drm_dbg_kms(&i915->drm,
330447bdb1caSJani Nikula 			    "[CONNECTOR:%d:%s] Failed to reset sink scrambling/TMDS bit clock ratio\n",
3305379bc100SJani Nikula 			    connector->base.id, connector->name);
3306379bc100SJani Nikula }
3307379bc100SJani Nikula 
3308ede9771dSVille Syrjälä static void intel_disable_ddi(struct intel_atomic_state *state,
3309ede9771dSVille Syrjälä 			      struct intel_encoder *encoder,
3310379bc100SJani Nikula 			      const struct intel_crtc_state *old_crtc_state,
3311379bc100SJani Nikula 			      const struct drm_connector_state *old_conn_state)
3312379bc100SJani Nikula {
3313379bc100SJani Nikula 	intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
3314379bc100SJani Nikula 
3315379bc100SJani Nikula 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3316ede9771dSVille Syrjälä 		intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
3317ede9771dSVille Syrjälä 				       old_conn_state);
3318379bc100SJani Nikula 	else
3319ede9771dSVille Syrjälä 		intel_disable_ddi_dp(state, encoder, old_crtc_state,
3320ede9771dSVille Syrjälä 				     old_conn_state);
3321379bc100SJani Nikula }
3322379bc100SJani Nikula 
3323ede9771dSVille Syrjälä static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
3324ede9771dSVille Syrjälä 				     struct intel_encoder *encoder,
3325379bc100SJani Nikula 				     const struct intel_crtc_state *crtc_state,
3326379bc100SJani Nikula 				     const struct drm_connector_state *conn_state)
3327379bc100SJani Nikula {
33280c06fa15SGwan-gyeong Mun 	intel_ddi_set_dp_msa(crtc_state, conn_state);
3329379bc100SJani Nikula 
333076d45d06SGwan-gyeong Mun 	intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3331379bc100SJani Nikula 
3332c0a52f8bSJani Nikula 	intel_backlight_update(state, encoder, crtc_state, conn_state);
33336306d8dbSHans de Goede 	drm_connector_update_privacy_screen(conn_state);
3334379bc100SJani Nikula }
3335379bc100SJani Nikula 
3336f1c7a36bSSean Paul void intel_ddi_update_pipe(struct intel_atomic_state *state,
3337ede9771dSVille Syrjälä 			   struct intel_encoder *encoder,
3338379bc100SJani Nikula 			   const struct intel_crtc_state *crtc_state,
3339379bc100SJani Nikula 			   const struct drm_connector_state *conn_state)
3340379bc100SJani Nikula {
3341d456512cSRamalingam C 
3342f1c7a36bSSean Paul 	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
3343f1c7a36bSSean Paul 	    !intel_encoder_is_mst(encoder))
3344ede9771dSVille Syrjälä 		intel_ddi_update_pipe_dp(state, encoder, crtc_state,
3345ede9771dSVille Syrjälä 					 conn_state);
3346379bc100SJani Nikula 
3347ede9771dSVille Syrjälä 	intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state);
3348379bc100SJani Nikula }
3349379bc100SJani Nikula 
335027ac123bSImre Deak void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
335127ac123bSImre Deak 				  struct intel_encoder *encoder,
335227ac123bSImre Deak 				  struct intel_crtc *crtc)
335327ac123bSImre Deak {
335427ac123bSImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
335527ac123bSImre Deak 	struct intel_crtc_state *crtc_state =
335627ac123bSImre Deak 		intel_atomic_get_new_crtc_state(state, crtc);
335727ac123bSImre Deak 	struct intel_crtc *slave_crtc;
335827ac123bSImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
335927ac123bSImre Deak 
336062618c7fSMika Kahola 	/* FIXME: Add MTL pll_mgr */
336162618c7fSMika Kahola 	if (DISPLAY_VER(i915) >= 14 || !intel_phy_is_tc(i915, phy))
336227ac123bSImre Deak 		return;
336327ac123bSImre Deak 
336427ac123bSImre Deak 	intel_update_active_dpll(state, crtc, encoder);
336527ac123bSImre Deak 	for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
336627ac123bSImre Deak 					 intel_crtc_bigjoiner_slave_pipes(crtc_state))
336727ac123bSImre Deak 		intel_update_active_dpll(state, slave_crtc, encoder);
336827ac123bSImre Deak }
336927ac123bSImre Deak 
3370379bc100SJani Nikula static void
3371ede9771dSVille Syrjälä intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
3372ede9771dSVille Syrjälä 			 struct intel_encoder *encoder,
3373379bc100SJani Nikula 			 const struct intel_crtc_state *crtc_state,
3374379bc100SJani Nikula 			 const struct drm_connector_state *conn_state)
3375379bc100SJani Nikula {
3376379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3377b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3378d8fe2ab6SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
3379d8fe2ab6SMatt Roper 	bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
3380379bc100SJani Nikula 
33810f752b21SImre Deak 	if (is_tc_port) {
33820f752b21SImre Deak 		struct intel_crtc *master_crtc =
33830f752b21SImre Deak 			to_intel_crtc(crtc_state->uapi.crtc);
33840f752b21SImre Deak 
338524a7bfe0SImre Deak 		intel_tc_port_get_link(dig_port, crtc_state->lane_count);
338627ac123bSImre Deak 		intel_ddi_update_active_dpll(state, encoder, master_crtc);
33870f752b21SImre Deak 	}
33880f752b21SImre Deak 
3389637c7aa2SImre Deak 	main_link_aux_power_domain_get(dig_port, crtc_state);
3390379bc100SJani Nikula 
339111a89708SImre Deak 	if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port))
33929d44dcb9SLucas De Marchi 		/*
33939d44dcb9SLucas De Marchi 		 * Program the lane count for static/dynamic connections on
33949d44dcb9SLucas De Marchi 		 * Type-C ports.  Skip this step for TBT.
33959d44dcb9SLucas De Marchi 		 */
33969d44dcb9SLucas De Marchi 		intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count);
33972446e1d6SMatt Roper 	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3398379bc100SJani Nikula 		bxt_ddi_phy_set_lane_optim_mask(encoder,
3399379bc100SJani Nikula 						crtc_state->lane_lat_optim_mask);
3400379bc100SJani Nikula }
3401379bc100SJani Nikula 
340255223c3bSImre Deak static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
340355223c3bSImre Deak {
340455223c3bSImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
340555223c3bSImre Deak 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
340655223c3bSImre Deak 	int ln;
340755223c3bSImre Deak 
340889cb0ba4SImre Deak 	for (ln = 0; ln < 2; ln++)
3409b8ed5533SImre Deak 		intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0);
341055223c3bSImre Deak }
341155223c3bSImre Deak 
341223ef6194SJosé Roberto de Souza static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
341323ef6194SJosé Roberto de Souza 					 const struct intel_crtc_state *crtc_state)
341423ef6194SJosé Roberto de Souza {
341523ef6194SJosé Roberto de Souza 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
341623ef6194SJosé Roberto de Souza 	struct intel_encoder *encoder = &dig_port->base;
341723ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
341823ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
341923ef6194SJosé Roberto de Souza 	u32 dp_tp_ctl;
342023ef6194SJosé Roberto de Souza 
342123ef6194SJosé Roberto de Souza 	/*
342223ef6194SJosé Roberto de Souza 	 * TODO: To train with only a different voltage swing entry is not
342323ef6194SJosé Roberto de Souza 	 * necessary disable and enable port
342423ef6194SJosé Roberto de Souza 	 */
342523ef6194SJosé Roberto de Souza 	dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
342623ef6194SJosé Roberto de Souza 	if (dp_tp_ctl & DP_TP_CTL_ENABLE)
342723ef6194SJosé Roberto de Souza 		mtl_disable_ddi_buf(encoder, crtc_state);
342823ef6194SJosé Roberto de Souza 
342923ef6194SJosé Roberto de Souza 	/* 6.d Configure and enable DP_TP_CTL with link training pattern 1 selected */
343023ef6194SJosé Roberto de Souza 	dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
343123ef6194SJosé Roberto de Souza 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
343223ef6194SJosé Roberto de Souza 		dp_tp_ctl |= DP_TP_CTL_MODE_MST;
343323ef6194SJosé Roberto de Souza 	} else {
343423ef6194SJosé Roberto de Souza 		dp_tp_ctl |= DP_TP_CTL_MODE_SST;
343523ef6194SJosé Roberto de Souza 		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
343623ef6194SJosé Roberto de Souza 			dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
343723ef6194SJosé Roberto de Souza 	}
343823ef6194SJosé Roberto de Souza 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
343923ef6194SJosé Roberto de Souza 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
344023ef6194SJosé Roberto de Souza 
344123ef6194SJosé Roberto de Souza 	/* 6.f Enable D2D Link */
344223ef6194SJosé Roberto de Souza 	mtl_ddi_enable_d2d(encoder);
344323ef6194SJosé Roberto de Souza 
344423ef6194SJosé Roberto de Souza 	/* 6.g Configure voltage swing and related IO settings */
344523ef6194SJosé Roberto de Souza 	encoder->set_signal_levels(encoder, crtc_state);
344623ef6194SJosé Roberto de Souza 
344723ef6194SJosé Roberto de Souza 	/* 6.h Configure PORT_BUF_CTL1 */
344823ef6194SJosé Roberto de Souza 	mtl_port_buf_ctl_program(encoder, crtc_state);
344923ef6194SJosé Roberto de Souza 
345023ef6194SJosé Roberto de Souza 	/* 6.i Configure and enable DDI_CTL_DE to start sending valid data to port slice */
345123ef6194SJosé Roberto de Souza 	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
345223ef6194SJosé Roberto de Souza 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
345323ef6194SJosé Roberto de Souza 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
345423ef6194SJosé Roberto de Souza 
345523ef6194SJosé Roberto de Souza 	/* 6.j Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 us */
345623ef6194SJosé Roberto de Souza 	intel_wait_ddi_buf_active(dev_priv, port);
345723ef6194SJosé Roberto de Souza }
345823ef6194SJosé Roberto de Souza 
3459a621860aSVille Syrjälä static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
3460a621860aSVille Syrjälä 					   const struct intel_crtc_state *crtc_state)
3461379bc100SJani Nikula {
346255223c3bSImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
346355223c3bSImre Deak 	struct intel_encoder *encoder = &dig_port->base;
3464ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3465ef79fafeSVille Syrjälä 	enum port port = encoder->port;
346635ac28a8SLucas De Marchi 	u32 dp_tp_ctl, ddi_buf_ctl;
3467379bc100SJani Nikula 	bool wait = false;
3468379bc100SJani Nikula 
3469ef79fafeSVille Syrjälä 	dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
347035ac28a8SLucas De Marchi 
347135ac28a8SLucas De Marchi 	if (dp_tp_ctl & DP_TP_CTL_ENABLE) {
3472f7960e7fSJani Nikula 		ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port));
347335ac28a8SLucas De Marchi 		if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) {
3474f7960e7fSJani Nikula 			intel_de_write(dev_priv, DDI_BUF_CTL(port),
347535ac28a8SLucas De Marchi 				       ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE);
3476379bc100SJani Nikula 			wait = true;
3477379bc100SJani Nikula 		}
3478379bc100SJani Nikula 
34798c042949SVille Syrjälä 		dp_tp_ctl &= ~DP_TP_CTL_ENABLE;
3480ef79fafeSVille Syrjälä 		intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3481ef79fafeSVille Syrjälä 		intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3482379bc100SJani Nikula 
3483379bc100SJani Nikula 		if (wait)
3484379bc100SJani Nikula 			intel_wait_ddi_buf_idle(dev_priv, port);
3485379bc100SJani Nikula 	}
3486379bc100SJani Nikula 
3487963501bdSImre Deak 	dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
3488a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
348935ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_MODE_MST;
3490a621860aSVille Syrjälä 	} else {
349135ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_MODE_SST;
3492379bc100SJani Nikula 		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
349335ac28a8SLucas De Marchi 			dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
3494379bc100SJani Nikula 	}
3495ef79fafeSVille Syrjälä 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3496ef79fafeSVille Syrjälä 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3497379bc100SJani Nikula 
349855223c3bSImre Deak 	if (IS_ALDERLAKE_P(dev_priv) &&
349955223c3bSImre Deak 	    (intel_tc_port_in_dp_alt_mode(dig_port) || intel_tc_port_in_legacy_mode(dig_port)))
350055223c3bSImre Deak 		adlp_tbt_to_dp_alt_switch_wa(encoder);
350155223c3bSImre Deak 
3502379bc100SJani Nikula 	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
3503f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
3504f7960e7fSJani Nikula 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
3505379bc100SJani Nikula 
3506e828da30SManasi Navare 	intel_wait_ddi_buf_active(dev_priv, port);
3507379bc100SJani Nikula }
3508379bc100SJani Nikula 
3509eee3f911SVille Syrjälä static void intel_ddi_set_link_train(struct intel_dp *intel_dp,
3510a621860aSVille Syrjälä 				     const struct intel_crtc_state *crtc_state,
3511eee3f911SVille Syrjälä 				     u8 dp_train_pat)
3512eee3f911SVille Syrjälä {
3513ef79fafeSVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
3514ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3515eee3f911SVille Syrjälä 	u32 temp;
3516eee3f911SVille Syrjälä 
3517ef79fafeSVille Syrjälä 	temp = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3518eee3f911SVille Syrjälä 
3519eee3f911SVille Syrjälä 	temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
35206777a855SImre Deak 	switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
3521eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_DISABLE:
3522eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
3523eee3f911SVille Syrjälä 		break;
3524eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_1:
3525eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
3526eee3f911SVille Syrjälä 		break;
3527eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_2:
3528eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
3529eee3f911SVille Syrjälä 		break;
3530eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_3:
3531eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
3532eee3f911SVille Syrjälä 		break;
3533eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_4:
3534eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT4;
3535eee3f911SVille Syrjälä 		break;
3536eee3f911SVille Syrjälä 	}
3537eee3f911SVille Syrjälä 
3538ef79fafeSVille Syrjälä 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), temp);
3539eee3f911SVille Syrjälä }
3540eee3f911SVille Syrjälä 
3541a621860aSVille Syrjälä static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp,
3542a621860aSVille Syrjälä 					  const struct intel_crtc_state *crtc_state)
35438fdda385SVille Syrjälä {
35448fdda385SVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
35458fdda385SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
35468fdda385SVille Syrjälä 	enum port port = encoder->port;
35478fdda385SVille Syrjälä 
35488910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
35498910d8b7SAndrzej Hajda 		     DP_TP_CTL_LINK_TRAIN_MASK, DP_TP_CTL_LINK_TRAIN_IDLE);
35508fdda385SVille Syrjälä 
35518fdda385SVille Syrjälä 	/*
35528fdda385SVille Syrjälä 	 * Until TGL on PORT_A we can have only eDP in SST mode. There the only
35538fdda385SVille Syrjälä 	 * reason we need to set idle transmission mode is to work around a HW
35548fdda385SVille Syrjälä 	 * issue where we enable the pipe while not in idle link-training mode.
35558fdda385SVille Syrjälä 	 * In this case there is requirement to wait for a minimum number of
35568fdda385SVille Syrjälä 	 * idle patterns to be sent.
35578fdda385SVille Syrjälä 	 */
3558005e9537SMatt Roper 	if (port == PORT_A && DISPLAY_VER(dev_priv) < 12)
35598fdda385SVille Syrjälä 		return;
35608fdda385SVille Syrjälä 
3561ef79fafeSVille Syrjälä 	if (intel_de_wait_for_set(dev_priv,
3562ef79fafeSVille Syrjälä 				  dp_tp_status_reg(encoder, crtc_state),
35638fdda385SVille Syrjälä 				  DP_TP_STATUS_IDLE_DONE, 1))
35648fdda385SVille Syrjälä 		drm_err(&dev_priv->drm,
35658fdda385SVille Syrjälä 			"Timed out waiting for DP idle patterns\n");
35668fdda385SVille Syrjälä }
35678fdda385SVille Syrjälä 
3568379bc100SJani Nikula static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
3569379bc100SJani Nikula 				       enum transcoder cpu_transcoder)
3570379bc100SJani Nikula {
3571379bc100SJani Nikula 	if (cpu_transcoder == TRANSCODER_EDP)
3572379bc100SJani Nikula 		return false;
3573379bc100SJani Nikula 
3574615a7724SAnshuman Gupta 	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO_MMIO))
3575379bc100SJani Nikula 		return false;
3576379bc100SJani Nikula 
3577f7960e7fSJani Nikula 	return intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD) &
3578379bc100SJani Nikula 		AUDIO_OUTPUT_ENABLE(cpu_transcoder);
3579379bc100SJani Nikula }
3580379bc100SJani Nikula 
3581379bc100SJani Nikula void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
3582379bc100SJani Nikula 					 struct intel_crtc_state *crtc_state)
3583379bc100SJani Nikula {
3584005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12 && crtc_state->port_clock > 594000)
35850fde0b1dSMatt Roper 		crtc_state->min_voltage_level = 2;
358624ea098bSTejas Upadhyay 	else if (IS_JSL_EHL(dev_priv) && crtc_state->port_clock > 594000)
35879d5fd37eSMatt Roper 		crtc_state->min_voltage_level = 3;
3588005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11 && crtc_state->port_clock > 594000)
3589379bc100SJani Nikula 		crtc_state->min_voltage_level = 1;
3590379bc100SJani Nikula }
3591379bc100SJani Nikula 
3592dc5b8ed5SVille Syrjälä static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *dev_priv,
359302d8ea47SVille Syrjälä 						     enum transcoder cpu_transcoder)
359402d8ea47SVille Syrjälä {
3595dc5b8ed5SVille Syrjälä 	u32 master_select;
359602d8ea47SVille Syrjälä 
3597005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
3598dc5b8ed5SVille Syrjälä 		u32 ctl2 = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL2(cpu_transcoder));
359902d8ea47SVille Syrjälä 
360002d8ea47SVille Syrjälä 		if ((ctl2 & PORT_SYNC_MODE_ENABLE) == 0)
360102d8ea47SVille Syrjälä 			return INVALID_TRANSCODER;
360202d8ea47SVille Syrjälä 
3603d4d7d9caSVille Syrjälä 		master_select = REG_FIELD_GET(PORT_SYNC_MODE_MASTER_SELECT_MASK, ctl2);
3604dc5b8ed5SVille Syrjälä 	} else {
3605dc5b8ed5SVille Syrjälä 		u32 ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
3606dc5b8ed5SVille Syrjälä 
3607dc5b8ed5SVille Syrjälä 		if ((ctl & TRANS_DDI_PORT_SYNC_ENABLE) == 0)
3608dc5b8ed5SVille Syrjälä 			return INVALID_TRANSCODER;
3609dc5b8ed5SVille Syrjälä 
3610dc5b8ed5SVille Syrjälä 		master_select = REG_FIELD_GET(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, ctl);
3611dc5b8ed5SVille Syrjälä 	}
361202d8ea47SVille Syrjälä 
361302d8ea47SVille Syrjälä 	if (master_select == 0)
361402d8ea47SVille Syrjälä 		return TRANSCODER_EDP;
361502d8ea47SVille Syrjälä 	else
361602d8ea47SVille Syrjälä 		return master_select - 1;
361702d8ea47SVille Syrjälä }
361802d8ea47SVille Syrjälä 
3619dc5b8ed5SVille Syrjälä static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
362002d8ea47SVille Syrjälä {
362102d8ea47SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
362202d8ea47SVille Syrjälä 	u32 transcoders = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
362302d8ea47SVille Syrjälä 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
362402d8ea47SVille Syrjälä 	enum transcoder cpu_transcoder;
362502d8ea47SVille Syrjälä 
362602d8ea47SVille Syrjälä 	crtc_state->master_transcoder =
3627dc5b8ed5SVille Syrjälä 		bdw_transcoder_master_readout(dev_priv, crtc_state->cpu_transcoder);
362802d8ea47SVille Syrjälä 
362902d8ea47SVille Syrjälä 	for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
363002d8ea47SVille Syrjälä 		enum intel_display_power_domain power_domain;
363102d8ea47SVille Syrjälä 		intel_wakeref_t trans_wakeref;
363202d8ea47SVille Syrjälä 
363302d8ea47SVille Syrjälä 		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
363402d8ea47SVille Syrjälä 		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
363502d8ea47SVille Syrjälä 								   power_domain);
363602d8ea47SVille Syrjälä 
363702d8ea47SVille Syrjälä 		if (!trans_wakeref)
363802d8ea47SVille Syrjälä 			continue;
363902d8ea47SVille Syrjälä 
3640dc5b8ed5SVille Syrjälä 		if (bdw_transcoder_master_readout(dev_priv, cpu_transcoder) ==
364102d8ea47SVille Syrjälä 		    crtc_state->cpu_transcoder)
364202d8ea47SVille Syrjälä 			crtc_state->sync_mode_slaves_mask |= BIT(cpu_transcoder);
364302d8ea47SVille Syrjälä 
364402d8ea47SVille Syrjälä 		intel_display_power_put(dev_priv, power_domain, trans_wakeref);
364502d8ea47SVille Syrjälä 	}
364602d8ea47SVille Syrjälä 
364702d8ea47SVille Syrjälä 	drm_WARN_ON(&dev_priv->drm,
364802d8ea47SVille Syrjälä 		    crtc_state->master_transcoder != INVALID_TRANSCODER &&
364902d8ea47SVille Syrjälä 		    crtc_state->sync_mode_slaves_mask);
365002d8ea47SVille Syrjälä }
365102d8ea47SVille Syrjälä 
36520385eceaSManasi Navare static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
3653379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config)
3654379bc100SJani Nikula {
3655379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3656f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
3657379bc100SJani Nikula 	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
3658a44289b9SUma Shankar 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3659379bc100SJani Nikula 	u32 temp, flags = 0;
3660379bc100SJani Nikula 
3661f7960e7fSJani Nikula 	temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
3662379bc100SJani Nikula 	if (temp & TRANS_DDI_PHSYNC)
3663379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_PHSYNC;
3664379bc100SJani Nikula 	else
3665379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_NHSYNC;
3666379bc100SJani Nikula 	if (temp & TRANS_DDI_PVSYNC)
3667379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_PVSYNC;
3668379bc100SJani Nikula 	else
3669379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_NVSYNC;
3670379bc100SJani Nikula 
36711326a92cSMaarten Lankhorst 	pipe_config->hw.adjusted_mode.flags |= flags;
3672379bc100SJani Nikula 
3673379bc100SJani Nikula 	switch (temp & TRANS_DDI_BPC_MASK) {
3674379bc100SJani Nikula 	case TRANS_DDI_BPC_6:
3675379bc100SJani Nikula 		pipe_config->pipe_bpp = 18;
3676379bc100SJani Nikula 		break;
3677379bc100SJani Nikula 	case TRANS_DDI_BPC_8:
3678379bc100SJani Nikula 		pipe_config->pipe_bpp = 24;
3679379bc100SJani Nikula 		break;
3680379bc100SJani Nikula 	case TRANS_DDI_BPC_10:
3681379bc100SJani Nikula 		pipe_config->pipe_bpp = 30;
3682379bc100SJani Nikula 		break;
3683379bc100SJani Nikula 	case TRANS_DDI_BPC_12:
3684379bc100SJani Nikula 		pipe_config->pipe_bpp = 36;
3685379bc100SJani Nikula 		break;
3686379bc100SJani Nikula 	default:
3687379bc100SJani Nikula 		break;
3688379bc100SJani Nikula 	}
3689379bc100SJani Nikula 
3690379bc100SJani Nikula 	switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
3691379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_HDMI:
3692379bc100SJani Nikula 		pipe_config->has_hdmi_sink = true;
3693379bc100SJani Nikula 
3694379bc100SJani Nikula 		pipe_config->infoframes.enable |=
3695379bc100SJani Nikula 			intel_hdmi_infoframes_enabled(encoder, pipe_config);
3696379bc100SJani Nikula 
3697379bc100SJani Nikula 		if (pipe_config->infoframes.enable)
3698379bc100SJani Nikula 			pipe_config->has_infoframe = true;
3699379bc100SJani Nikula 
3700379bc100SJani Nikula 		if (temp & TRANS_DDI_HDMI_SCRAMBLING)
3701379bc100SJani Nikula 			pipe_config->hdmi_scrambling = true;
3702379bc100SJani Nikula 		if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
3703379bc100SJani Nikula 			pipe_config->hdmi_high_tmds_clock_ratio = true;
3704df561f66SGustavo A. R. Silva 		fallthrough;
3705379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DVI:
3706379bc100SJani Nikula 		pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
3707b66a8abaSAnkit Nautiyal 		if (DISPLAY_VER(dev_priv) >= 14)
3708b66a8abaSAnkit Nautiyal 			pipe_config->lane_count =
3709b66a8abaSAnkit Nautiyal 				((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
3710b66a8abaSAnkit Nautiyal 		else
3711379bc100SJani Nikula 			pipe_config->lane_count = 4;
3712379bc100SJani Nikula 		break;
3713379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_SST:
3714379bc100SJani Nikula 		if (encoder->type == INTEL_OUTPUT_EDP)
3715379bc100SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP);
3716379bc100SJani Nikula 		else
3717379bc100SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
3718379bc100SJani Nikula 		pipe_config->lane_count =
3719379bc100SJani Nikula 			((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
37206149cb68SVille Syrjälä 
37215cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
37225cd06644SVille Syrjälä 					       &pipe_config->dp_m_n);
37235cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
37246149cb68SVille Syrjälä 					       &pipe_config->dp_m2_n2);
37258aa940c8SMaarten Lankhorst 
3726005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 11) {
3727ef79fafeSVille Syrjälä 			i915_reg_t dp_tp_ctl = dp_tp_ctl_reg(encoder, pipe_config);
37288aa940c8SMaarten Lankhorst 
37298aa940c8SMaarten Lankhorst 			pipe_config->fec_enable =
3730f7960e7fSJani Nikula 				intel_de_read(dev_priv, dp_tp_ctl) & DP_TP_CTL_FEC_ENABLE;
37318aa940c8SMaarten Lankhorst 
373247bdb1caSJani Nikula 			drm_dbg_kms(&dev_priv->drm,
373347bdb1caSJani Nikula 				    "[ENCODER:%d:%s] Fec status: %u\n",
37348aa940c8SMaarten Lankhorst 				    encoder->base.base.id, encoder->base.name,
37358aa940c8SMaarten Lankhorst 				    pipe_config->fec_enable);
37368aa940c8SMaarten Lankhorst 		}
37378aa940c8SMaarten Lankhorst 
3738a44289b9SUma Shankar 		if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
3739a44289b9SUma Shankar 			pipe_config->infoframes.enable |=
3740a44289b9SUma Shankar 				intel_lspcon_infoframes_enabled(encoder, pipe_config);
3741a44289b9SUma Shankar 		else
3742dee66f3eSGwan-gyeong Mun 			pipe_config->infoframes.enable |=
3743dee66f3eSGwan-gyeong Mun 				intel_hdmi_infoframes_enabled(encoder, pipe_config);
3744379bc100SJani Nikula 		break;
374565213594SJani Nikula 	case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
374665213594SJani Nikula 		if (!HAS_DP20(dev_priv)) {
374765213594SJani Nikula 			/* FDI */
374865213594SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
374965213594SJani Nikula 			break;
375065213594SJani Nikula 		}
375165213594SJani Nikula 		fallthrough; /* 128b/132b */
3752379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_MST:
3753379bc100SJani Nikula 		pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
3754379bc100SJani Nikula 		pipe_config->lane_count =
3755379bc100SJani Nikula 			((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
37566671c367SJosé Roberto de Souza 
3757005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12)
37586671c367SJosé Roberto de Souza 			pipe_config->mst_master_transcoder =
37596671c367SJosé Roberto de Souza 					REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
37606671c367SJosé Roberto de Souza 
37615cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
37625cd06644SVille Syrjälä 					       &pipe_config->dp_m_n);
3763dee66f3eSGwan-gyeong Mun 
3764dee66f3eSGwan-gyeong Mun 		pipe_config->infoframes.enable |=
3765dee66f3eSGwan-gyeong Mun 			intel_hdmi_infoframes_enabled(encoder, pipe_config);
3766379bc100SJani Nikula 		break;
3767379bc100SJani Nikula 	default:
3768379bc100SJani Nikula 		break;
3769379bc100SJani Nikula 	}
37700385eceaSManasi Navare }
37710385eceaSManasi Navare 
3772351221ffSVille Syrjälä static void intel_ddi_get_config(struct intel_encoder *encoder,
37730385eceaSManasi Navare 				 struct intel_crtc_state *pipe_config)
37740385eceaSManasi Navare {
37750385eceaSManasi Navare 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
37760385eceaSManasi Navare 	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
37770385eceaSManasi Navare 
37780385eceaSManasi Navare 	/* XXX: DSI transcoder paranoia */
37790385eceaSManasi Navare 	if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)))
37800385eceaSManasi Navare 		return;
37810385eceaSManasi Navare 
37820385eceaSManasi Navare 	intel_ddi_read_func_ctl(encoder, pipe_config);
3783379bc100SJani Nikula 
37845b616a29SJani Nikula 	intel_ddi_mso_get_config(encoder, pipe_config);
37855b616a29SJani Nikula 
3786379bc100SJani Nikula 	pipe_config->has_audio =
3787379bc100SJani Nikula 		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
3788379bc100SJani Nikula 
3789822e5ae7SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_EDP)
3790822e5ae7SVille Syrjälä 		intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp);
3791379bc100SJani Nikula 
3792351221ffSVille Syrjälä 	ddi_dotclock_get(pipe_config);
3793379bc100SJani Nikula 
37942446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3795379bc100SJani Nikula 		pipe_config->lane_lat_optim_mask =
3796379bc100SJani Nikula 			bxt_ddi_phy_get_lane_lat_optim_mask(encoder);
3797379bc100SJani Nikula 
3798379bc100SJani Nikula 	intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
3799379bc100SJani Nikula 
3800379bc100SJani Nikula 	intel_hdmi_read_gcp_infoframe(encoder, pipe_config);
3801379bc100SJani Nikula 
3802379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3803379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_AVI,
3804379bc100SJani Nikula 			     &pipe_config->infoframes.avi);
3805379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3806379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_SPD,
3807379bc100SJani Nikula 			     &pipe_config->infoframes.spd);
3808379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3809379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_VENDOR,
3810379bc100SJani Nikula 			     &pipe_config->infoframes.hdmi);
3811379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3812379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_DRM,
3813379bc100SJani Nikula 			     &pipe_config->infoframes.drm);
381402d8ea47SVille Syrjälä 
3815005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
3816dc5b8ed5SVille Syrjälä 		bdw_get_trans_port_sync_config(pipe_config);
3817dee66f3eSGwan-gyeong Mun 
3818dee66f3eSGwan-gyeong Mun 	intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
38192c3928e4SGwan-gyeong Mun 	intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
382078b772e1SJosé Roberto de Souza 
382178b772e1SJosé Roberto de Souza 	intel_psr_get_config(encoder, pipe_config);
382261a60df6SVille Syrjälä 
382361a60df6SVille Syrjälä 	intel_audio_codec_get_config(encoder, pipe_config);
3824379bc100SJani Nikula }
3825379bc100SJani Nikula 
3826351221ffSVille Syrjälä void intel_ddi_get_clock(struct intel_encoder *encoder,
3827351221ffSVille Syrjälä 			 struct intel_crtc_state *crtc_state,
3828351221ffSVille Syrjälä 			 struct intel_shared_dpll *pll)
3829351221ffSVille Syrjälä {
3830351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3831351221ffSVille Syrjälä 	enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
3832351221ffSVille Syrjälä 	struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
3833351221ffSVille Syrjälä 	bool pll_active;
3834351221ffSVille Syrjälä 
3835086877a1SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
3836086877a1SVille Syrjälä 		return;
3837086877a1SVille Syrjälä 
3838351221ffSVille Syrjälä 	port_dpll->pll = pll;
3839351221ffSVille Syrjälä 	pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
3840351221ffSVille Syrjälä 	drm_WARN_ON(&i915->drm, !pll_active);
3841351221ffSVille Syrjälä 
3842351221ffSVille Syrjälä 	icl_set_active_port_dpll(crtc_state, port_dpll_id);
3843351221ffSVille Syrjälä 
3844351221ffSVille Syrjälä 	crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
3845351221ffSVille Syrjälä 						     &crtc_state->dpll_hw_state);
3846351221ffSVille Syrjälä }
3847351221ffSVille Syrjälä 
384851390cc0SRadhakrishna Sripada static void mtl_ddi_get_config(struct intel_encoder *encoder,
384951390cc0SRadhakrishna Sripada 			       struct intel_crtc_state *crtc_state)
385051390cc0SRadhakrishna Sripada {
385151390cc0SRadhakrishna Sripada 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
385251390cc0SRadhakrishna Sripada 	enum phy phy = intel_port_to_phy(i915, encoder->port);
38537dee06bcSMika Kahola 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
385451390cc0SRadhakrishna Sripada 
38557dee06bcSMika Kahola 	if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
38567dee06bcSMika Kahola 		crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
38577dee06bcSMika Kahola 	} else if (intel_is_c10phy(i915, phy)) {
385851390cc0SRadhakrishna Sripada 		intel_c10pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c10);
385951390cc0SRadhakrishna Sripada 		intel_c10pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c10);
3860f1f9e627SMika Kahola 		crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c10);
3861929f527aSMika Kahola 	} else {
3862929f527aSMika Kahola 		intel_c20pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c20);
3863f968a253SMika Kahola 		intel_c20pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c20);
3864f1f9e627SMika Kahola 		crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c20);
3865929f527aSMika Kahola 	}
3866929f527aSMika Kahola 
386751390cc0SRadhakrishna Sripada 	intel_ddi_get_config(encoder, crtc_state);
386851390cc0SRadhakrishna Sripada }
386951390cc0SRadhakrishna Sripada 
3870865b73eaSMatt Roper static void dg2_ddi_get_config(struct intel_encoder *encoder,
3871865b73eaSMatt Roper 				struct intel_crtc_state *crtc_state)
3872865b73eaSMatt Roper {
3873865b73eaSMatt Roper 	intel_mpllb_readout_hw_state(encoder, &crtc_state->mpllb_state);
3874865b73eaSMatt Roper 	crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->mpllb_state);
3875865b73eaSMatt Roper 
3876865b73eaSMatt Roper 	intel_ddi_get_config(encoder, crtc_state);
3877865b73eaSMatt Roper }
3878865b73eaSMatt Roper 
3879351221ffSVille Syrjälä static void adls_ddi_get_config(struct intel_encoder *encoder,
3880351221ffSVille Syrjälä 				struct intel_crtc_state *crtc_state)
3881351221ffSVille Syrjälä {
3882351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, adls_ddi_get_pll(encoder));
3883351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3884351221ffSVille Syrjälä }
3885351221ffSVille Syrjälä 
3886351221ffSVille Syrjälä static void rkl_ddi_get_config(struct intel_encoder *encoder,
3887351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3888351221ffSVille Syrjälä {
3889351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, rkl_ddi_get_pll(encoder));
3890351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3891351221ffSVille Syrjälä }
3892351221ffSVille Syrjälä 
3893351221ffSVille Syrjälä static void dg1_ddi_get_config(struct intel_encoder *encoder,
3894351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3895351221ffSVille Syrjälä {
3896351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, dg1_ddi_get_pll(encoder));
3897351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3898351221ffSVille Syrjälä }
3899351221ffSVille Syrjälä 
3900351221ffSVille Syrjälä static void icl_ddi_combo_get_config(struct intel_encoder *encoder,
3901351221ffSVille Syrjälä 				     struct intel_crtc_state *crtc_state)
3902351221ffSVille Syrjälä {
3903351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, icl_ddi_combo_get_pll(encoder));
3904351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3905351221ffSVille Syrjälä }
3906351221ffSVille Syrjälä 
39077c1da068SImre Deak static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll)
39087c1da068SImre Deak {
39097c1da068SImre Deak 	return pll->info->id == DPLL_ID_ICL_TBTPLL;
39107c1da068SImre Deak }
39117c1da068SImre Deak 
39127c1da068SImre Deak static enum icl_port_dpll_id
39137c1da068SImre Deak icl_ddi_tc_port_pll_type(struct intel_encoder *encoder,
39147c1da068SImre Deak 			 const struct intel_crtc_state *crtc_state)
39157c1da068SImre Deak {
39167c1da068SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
39177c1da068SImre Deak 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
39187c1da068SImre Deak 
39197c1da068SImre Deak 	if (drm_WARN_ON(&i915->drm, !pll))
39207c1da068SImre Deak 		return ICL_PORT_DPLL_DEFAULT;
39217c1da068SImre Deak 
39227c1da068SImre Deak 	if (icl_ddi_tc_pll_is_tbt(pll))
39237c1da068SImre Deak 		return ICL_PORT_DPLL_DEFAULT;
39247c1da068SImre Deak 	else
39257c1da068SImre Deak 		return ICL_PORT_DPLL_MG_PHY;
39267c1da068SImre Deak }
39277c1da068SImre Deak 
39287c1da068SImre Deak enum icl_port_dpll_id
39297c1da068SImre Deak intel_ddi_port_pll_type(struct intel_encoder *encoder,
39307c1da068SImre Deak 			const struct intel_crtc_state *crtc_state)
39317c1da068SImre Deak {
39327c1da068SImre Deak 	if (!encoder->port_pll_type)
39337c1da068SImre Deak 		return ICL_PORT_DPLL_DEFAULT;
39347c1da068SImre Deak 
39357c1da068SImre Deak 	return encoder->port_pll_type(encoder, crtc_state);
39367c1da068SImre Deak }
39377c1da068SImre Deak 
3938086877a1SVille Syrjälä static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
3939086877a1SVille Syrjälä 				 struct intel_crtc_state *crtc_state,
3940086877a1SVille Syrjälä 				 struct intel_shared_dpll *pll)
3941351221ffSVille Syrjälä {
3942351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3943351221ffSVille Syrjälä 	enum icl_port_dpll_id port_dpll_id;
3944351221ffSVille Syrjälä 	struct icl_port_dpll *port_dpll;
3945351221ffSVille Syrjälä 	bool pll_active;
3946351221ffSVille Syrjälä 
3947086877a1SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
3948086877a1SVille Syrjälä 		return;
3949351221ffSVille Syrjälä 
39507c1da068SImre Deak 	if (icl_ddi_tc_pll_is_tbt(pll))
3951351221ffSVille Syrjälä 		port_dpll_id = ICL_PORT_DPLL_DEFAULT;
3952351221ffSVille Syrjälä 	else
3953351221ffSVille Syrjälä 		port_dpll_id = ICL_PORT_DPLL_MG_PHY;
3954351221ffSVille Syrjälä 
3955351221ffSVille Syrjälä 	port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
3956351221ffSVille Syrjälä 
3957351221ffSVille Syrjälä 	port_dpll->pll = pll;
3958351221ffSVille Syrjälä 	pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
3959351221ffSVille Syrjälä 	drm_WARN_ON(&i915->drm, !pll_active);
3960351221ffSVille Syrjälä 
3961351221ffSVille Syrjälä 	icl_set_active_port_dpll(crtc_state, port_dpll_id);
3962351221ffSVille Syrjälä 
39637c1da068SImre Deak 	if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll))
3964351221ffSVille Syrjälä 		crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port);
3965351221ffSVille Syrjälä 	else
3966351221ffSVille Syrjälä 		crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
3967351221ffSVille Syrjälä 							     &crtc_state->dpll_hw_state);
3968086877a1SVille Syrjälä }
3969351221ffSVille Syrjälä 
3970086877a1SVille Syrjälä static void icl_ddi_tc_get_config(struct intel_encoder *encoder,
3971086877a1SVille Syrjälä 				  struct intel_crtc_state *crtc_state)
3972086877a1SVille Syrjälä {
3973086877a1SVille Syrjälä 	icl_ddi_tc_get_clock(encoder, crtc_state, icl_ddi_tc_get_pll(encoder));
3974351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3975351221ffSVille Syrjälä }
3976351221ffSVille Syrjälä 
3977351221ffSVille Syrjälä static void bxt_ddi_get_config(struct intel_encoder *encoder,
3978351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3979351221ffSVille Syrjälä {
3980351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, bxt_ddi_get_pll(encoder));
3981351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3982351221ffSVille Syrjälä }
3983351221ffSVille Syrjälä 
3984351221ffSVille Syrjälä static void skl_ddi_get_config(struct intel_encoder *encoder,
3985351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3986351221ffSVille Syrjälä {
3987351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, skl_ddi_get_pll(encoder));
3988351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3989351221ffSVille Syrjälä }
3990351221ffSVille Syrjälä 
3991351221ffSVille Syrjälä void hsw_ddi_get_config(struct intel_encoder *encoder,
3992351221ffSVille Syrjälä 			struct intel_crtc_state *crtc_state)
3993351221ffSVille Syrjälä {
3994351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, hsw_ddi_get_pll(encoder));
3995351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3996351221ffSVille Syrjälä }
3997351221ffSVille Syrjälä 
3998f9e76a6eSImre Deak static void intel_ddi_sync_state(struct intel_encoder *encoder,
3999f9e76a6eSImre Deak 				 const struct intel_crtc_state *crtc_state)
4000f9e76a6eSImre Deak {
40017194dc99SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
40027194dc99SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
40037194dc99SImre Deak 
40047194dc99SImre Deak 	if (intel_phy_is_tc(i915, phy))
40052a4d292fSImre Deak 		intel_tc_port_sanitize_mode(enc_to_dig_port(encoder),
40062a4d292fSImre Deak 					    crtc_state);
40077194dc99SImre Deak 
40087194dc99SImre Deak 	if (crtc_state && intel_crtc_has_dp_encoder(crtc_state))
4009f9e76a6eSImre Deak 		intel_dp_sync_state(encoder, crtc_state);
4010f9e76a6eSImre Deak }
4011f9e76a6eSImre Deak 
4012b671d6efSImre Deak static bool intel_ddi_initial_fastset_check(struct intel_encoder *encoder,
4013b671d6efSImre Deak 					    struct intel_crtc_state *crtc_state)
4014b671d6efSImre Deak {
4015eddb4afcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4016eddb4afcSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4017eddb4afcSVille Syrjälä 	bool fastset = true;
4018b671d6efSImre Deak 
4019eddb4afcSVille Syrjälä 	if (intel_phy_is_tc(i915, phy)) {
4020eddb4afcSVille Syrjälä 		drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute TC port DPLLs\n",
4021eddb4afcSVille Syrjälä 			    encoder->base.base.id, encoder->base.name);
4022eddb4afcSVille Syrjälä 		crtc_state->uapi.mode_changed = true;
4023eddb4afcSVille Syrjälä 		fastset = false;
4024eddb4afcSVille Syrjälä 	}
4025eddb4afcSVille Syrjälä 
4026eddb4afcSVille Syrjälä 	if (intel_crtc_has_dp_encoder(crtc_state) &&
4027eddb4afcSVille Syrjälä 	    !intel_dp_initial_fastset_check(encoder, crtc_state))
4028eddb4afcSVille Syrjälä 		fastset = false;
4029eddb4afcSVille Syrjälä 
4030eddb4afcSVille Syrjälä 	return fastset;
4031b671d6efSImre Deak }
4032b671d6efSImre Deak 
4033379bc100SJani Nikula static enum intel_output_type
4034379bc100SJani Nikula intel_ddi_compute_output_type(struct intel_encoder *encoder,
4035379bc100SJani Nikula 			      struct intel_crtc_state *crtc_state,
4036379bc100SJani Nikula 			      struct drm_connector_state *conn_state)
4037379bc100SJani Nikula {
4038379bc100SJani Nikula 	switch (conn_state->connector->connector_type) {
4039379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_HDMIA:
4040379bc100SJani Nikula 		return INTEL_OUTPUT_HDMI;
4041379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_eDP:
4042379bc100SJani Nikula 		return INTEL_OUTPUT_EDP;
4043379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_DisplayPort:
4044379bc100SJani Nikula 		return INTEL_OUTPUT_DP;
4045379bc100SJani Nikula 	default:
4046379bc100SJani Nikula 		MISSING_CASE(conn_state->connector->connector_type);
4047379bc100SJani Nikula 		return INTEL_OUTPUT_UNUSED;
4048379bc100SJani Nikula 	}
4049379bc100SJani Nikula }
4050379bc100SJani Nikula 
4051379bc100SJani Nikula static int intel_ddi_compute_config(struct intel_encoder *encoder,
4052379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config,
4053379bc100SJani Nikula 				    struct drm_connector_state *conn_state)
4054379bc100SJani Nikula {
40552225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
4056379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4057379bc100SJani Nikula 	enum port port = encoder->port;
4058379bc100SJani Nikula 	int ret;
4059379bc100SJani Nikula 
406010cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
4061379bc100SJani Nikula 		pipe_config->cpu_transcoder = TRANSCODER_EDP;
4062379bc100SJani Nikula 
4063bdacf087SAnshuman Gupta 	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
406434682d60SVille Syrjälä 		pipe_config->has_hdmi_sink =
406534682d60SVille Syrjälä 			intel_hdmi_compute_has_hdmi_sink(encoder, pipe_config, conn_state);
406634682d60SVille Syrjälä 
4067379bc100SJani Nikula 		ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
4068bdacf087SAnshuman Gupta 	} else {
4069379bc100SJani Nikula 		ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
4070bdacf087SAnshuman Gupta 	}
4071bdacf087SAnshuman Gupta 
4072379bc100SJani Nikula 	if (ret)
4073379bc100SJani Nikula 		return ret;
4074379bc100SJani Nikula 
4075379bc100SJani Nikula 	if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A &&
4076379bc100SJani Nikula 	    pipe_config->cpu_transcoder == TRANSCODER_EDP)
4077379bc100SJani Nikula 		pipe_config->pch_pfit.force_thru =
4078379bc100SJani Nikula 			pipe_config->pch_pfit.enabled ||
4079379bc100SJani Nikula 			pipe_config->crc_enabled;
4080379bc100SJani Nikula 
40812446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4082379bc100SJani Nikula 		pipe_config->lane_lat_optim_mask =
4083379bc100SJani Nikula 			bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
4084379bc100SJani Nikula 
4085379bc100SJani Nikula 	intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
4086379bc100SJani Nikula 
4087379bc100SJani Nikula 	return 0;
4088379bc100SJani Nikula }
4089379bc100SJani Nikula 
4090b50a1aa6SManasi Navare static bool mode_equal(const struct drm_display_mode *mode1,
4091b50a1aa6SManasi Navare 		       const struct drm_display_mode *mode2)
4092b50a1aa6SManasi Navare {
4093b50a1aa6SManasi Navare 	return drm_mode_match(mode1, mode2,
4094b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_TIMINGS |
4095b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_FLAGS |
4096b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_3D_FLAGS) &&
4097b50a1aa6SManasi Navare 		mode1->clock == mode2->clock; /* we want an exact match */
4098b50a1aa6SManasi Navare }
4099b50a1aa6SManasi Navare 
4100b50a1aa6SManasi Navare static bool m_n_equal(const struct intel_link_m_n *m_n_1,
4101b50a1aa6SManasi Navare 		      const struct intel_link_m_n *m_n_2)
4102b50a1aa6SManasi Navare {
4103b50a1aa6SManasi Navare 	return m_n_1->tu == m_n_2->tu &&
41045f721a5dSVille Syrjälä 		m_n_1->data_m == m_n_2->data_m &&
41055f721a5dSVille Syrjälä 		m_n_1->data_n == m_n_2->data_n &&
4106b50a1aa6SManasi Navare 		m_n_1->link_m == m_n_2->link_m &&
4107b50a1aa6SManasi Navare 		m_n_1->link_n == m_n_2->link_n;
4108b50a1aa6SManasi Navare }
4109b50a1aa6SManasi Navare 
4110b50a1aa6SManasi Navare static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
4111b50a1aa6SManasi Navare 				       const struct intel_crtc_state *crtc_state2)
4112b50a1aa6SManasi Navare {
4113b50a1aa6SManasi Navare 	return crtc_state1->hw.active && crtc_state2->hw.active &&
4114b50a1aa6SManasi Navare 		crtc_state1->output_types == crtc_state2->output_types &&
4115b50a1aa6SManasi Navare 		crtc_state1->output_format == crtc_state2->output_format &&
4116b50a1aa6SManasi Navare 		crtc_state1->lane_count == crtc_state2->lane_count &&
4117b50a1aa6SManasi Navare 		crtc_state1->port_clock == crtc_state2->port_clock &&
4118b50a1aa6SManasi Navare 		mode_equal(&crtc_state1->hw.adjusted_mode,
4119b50a1aa6SManasi Navare 			   &crtc_state2->hw.adjusted_mode) &&
4120b50a1aa6SManasi Navare 		m_n_equal(&crtc_state1->dp_m_n, &crtc_state2->dp_m_n);
4121b50a1aa6SManasi Navare }
4122b50a1aa6SManasi Navare 
4123b50a1aa6SManasi Navare static u8
4124b50a1aa6SManasi Navare intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state,
4125b50a1aa6SManasi Navare 				int tile_group_id)
4126b50a1aa6SManasi Navare {
4127b50a1aa6SManasi Navare 	struct drm_connector *connector;
4128b50a1aa6SManasi Navare 	const struct drm_connector_state *conn_state;
4129b50a1aa6SManasi Navare 	struct drm_i915_private *dev_priv = to_i915(ref_crtc_state->uapi.crtc->dev);
4130b50a1aa6SManasi Navare 	struct intel_atomic_state *state =
4131b50a1aa6SManasi Navare 		to_intel_atomic_state(ref_crtc_state->uapi.state);
4132b50a1aa6SManasi Navare 	u8 transcoders = 0;
4133b50a1aa6SManasi Navare 	int i;
4134b50a1aa6SManasi Navare 
4135dc5b8ed5SVille Syrjälä 	/*
4136dc5b8ed5SVille Syrjälä 	 * We don't enable port sync on BDW due to missing w/as and
4137dc5b8ed5SVille Syrjälä 	 * due to not having adjusted the modeset sequence appropriately.
4138dc5b8ed5SVille Syrjälä 	 */
4139005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) < 9)
4140b50a1aa6SManasi Navare 		return 0;
4141b50a1aa6SManasi Navare 
4142b50a1aa6SManasi Navare 	if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP))
4143b50a1aa6SManasi Navare 		return 0;
4144b50a1aa6SManasi Navare 
4145b50a1aa6SManasi Navare 	for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
4146b50a1aa6SManasi Navare 		struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
4147b50a1aa6SManasi Navare 		const struct intel_crtc_state *crtc_state;
4148b50a1aa6SManasi Navare 
4149b50a1aa6SManasi Navare 		if (!crtc)
4150b50a1aa6SManasi Navare 			continue;
4151b50a1aa6SManasi Navare 
4152b50a1aa6SManasi Navare 		if (!connector->has_tile ||
4153b50a1aa6SManasi Navare 		    connector->tile_group->id !=
4154b50a1aa6SManasi Navare 		    tile_group_id)
4155b50a1aa6SManasi Navare 			continue;
4156b50a1aa6SManasi Navare 		crtc_state = intel_atomic_get_new_crtc_state(state,
4157b50a1aa6SManasi Navare 							     crtc);
4158b50a1aa6SManasi Navare 		if (!crtcs_port_sync_compatible(ref_crtc_state,
4159b50a1aa6SManasi Navare 						crtc_state))
4160b50a1aa6SManasi Navare 			continue;
4161b50a1aa6SManasi Navare 		transcoders |= BIT(crtc_state->cpu_transcoder);
4162b50a1aa6SManasi Navare 	}
4163b50a1aa6SManasi Navare 
4164b50a1aa6SManasi Navare 	return transcoders;
4165b50a1aa6SManasi Navare }
4166b50a1aa6SManasi Navare 
4167b50a1aa6SManasi Navare static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
4168b50a1aa6SManasi Navare 					 struct intel_crtc_state *crtc_state,
4169b50a1aa6SManasi Navare 					 struct drm_connector_state *conn_state)
4170b50a1aa6SManasi Navare {
417147bdb1caSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4172b50a1aa6SManasi Navare 	struct drm_connector *connector = conn_state->connector;
4173b50a1aa6SManasi Navare 	u8 port_sync_transcoders = 0;
4174b50a1aa6SManasi Navare 
417547bdb1caSJani Nikula 	drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]",
4176b50a1aa6SManasi Navare 		    encoder->base.base.id, encoder->base.name,
4177b50a1aa6SManasi Navare 		    crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
4178b50a1aa6SManasi Navare 
4179b50a1aa6SManasi Navare 	if (connector->has_tile)
4180b50a1aa6SManasi Navare 		port_sync_transcoders = intel_ddi_port_sync_transcoders(crtc_state,
4181b50a1aa6SManasi Navare 									connector->tile_group->id);
4182b50a1aa6SManasi Navare 
4183b50a1aa6SManasi Navare 	/*
4184b50a1aa6SManasi Navare 	 * EDP Transcoders cannot be ensalved
4185b50a1aa6SManasi Navare 	 * make them a master always when present
4186b50a1aa6SManasi Navare 	 */
4187b50a1aa6SManasi Navare 	if (port_sync_transcoders & BIT(TRANSCODER_EDP))
4188b50a1aa6SManasi Navare 		crtc_state->master_transcoder = TRANSCODER_EDP;
4189b50a1aa6SManasi Navare 	else
4190b50a1aa6SManasi Navare 		crtc_state->master_transcoder = ffs(port_sync_transcoders) - 1;
4191b50a1aa6SManasi Navare 
4192b50a1aa6SManasi Navare 	if (crtc_state->master_transcoder == crtc_state->cpu_transcoder) {
4193b50a1aa6SManasi Navare 		crtc_state->master_transcoder = INVALID_TRANSCODER;
4194b50a1aa6SManasi Navare 		crtc_state->sync_mode_slaves_mask =
4195b50a1aa6SManasi Navare 			port_sync_transcoders & ~BIT(crtc_state->cpu_transcoder);
4196b50a1aa6SManasi Navare 	}
4197b50a1aa6SManasi Navare 
4198b50a1aa6SManasi Navare 	return 0;
4199b50a1aa6SManasi Navare }
4200b50a1aa6SManasi Navare 
4201379bc100SJani Nikula static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
4202379bc100SJani Nikula {
42034a300e65SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->dev);
4204b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
42053e0abc76SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
4206379bc100SJani Nikula 
4207379bc100SJani Nikula 	intel_dp_encoder_flush_work(encoder);
42083e0abc76SImre Deak 	if (intel_phy_is_tc(i915, phy))
4209c5879999SImre Deak 		intel_tc_port_cleanup(dig_port);
42104a300e65SImre Deak 	intel_display_power_flush_work(i915);
4211379bc100SJani Nikula 
4212379bc100SJani Nikula 	drm_encoder_cleanup(encoder);
4213a6c6eac9SAnshuman Gupta 	kfree(dig_port->hdcp_port_data.streams);
4214379bc100SJani Nikula 	kfree(dig_port);
4215379bc100SJani Nikula }
4216379bc100SJani Nikula 
4217764f6729SVille Syrjälä static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
4218764f6729SVille Syrjälä {
4219a82796a2SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->dev);
4220764f6729SVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
4221a82796a2SImre Deak 	struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
4222a82796a2SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
4223764f6729SVille Syrjälä 
4224764f6729SVille Syrjälä 	intel_dp->reset_link_params = true;
4225764f6729SVille Syrjälä 
4226764f6729SVille Syrjälä 	intel_pps_encoder_reset(intel_dp);
4227a82796a2SImre Deak 
4228a82796a2SImre Deak 	if (intel_phy_is_tc(i915, phy))
4229a82796a2SImre Deak 		intel_tc_port_init_mode(dig_port);
4230764f6729SVille Syrjälä }
4231764f6729SVille Syrjälä 
4232379bc100SJani Nikula static const struct drm_encoder_funcs intel_ddi_funcs = {
4233764f6729SVille Syrjälä 	.reset = intel_ddi_encoder_reset,
4234379bc100SJani Nikula 	.destroy = intel_ddi_encoder_destroy,
4235379bc100SJani Nikula };
4236379bc100SJani Nikula 
4237379bc100SJani Nikula static struct intel_connector *
42387801f3b7SLucas De Marchi intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
4239379bc100SJani Nikula {
424023ef6194SJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
4241379bc100SJani Nikula 	struct intel_connector *connector;
42427801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4243379bc100SJani Nikula 
4244379bc100SJani Nikula 	connector = intel_connector_alloc();
4245379bc100SJani Nikula 	if (!connector)
4246379bc100SJani Nikula 		return NULL;
4247379bc100SJani Nikula 
42487801f3b7SLucas De Marchi 	dig_port->dp.output_reg = DDI_BUF_CTL(port);
424923ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(i915) >= 14)
425023ef6194SJosé Roberto de Souza 		dig_port->dp.prepare_link_retrain = mtl_ddi_prepare_link_retrain;
425123ef6194SJosé Roberto de Souza 	else
42527801f3b7SLucas De Marchi 		dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain;
42537801f3b7SLucas De Marchi 	dig_port->dp.set_link_train = intel_ddi_set_link_train;
42547801f3b7SLucas De Marchi 	dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train;
4255eee3f911SVille Syrjälä 
42567801f3b7SLucas De Marchi 	dig_port->dp.voltage_max = intel_ddi_dp_voltage_max;
42577801f3b7SLucas De Marchi 	dig_port->dp.preemph_max = intel_ddi_dp_preemph_max;
425853de0a20SVille Syrjälä 
42597801f3b7SLucas De Marchi 	if (!intel_dp_init_connector(dig_port, connector)) {
4260379bc100SJani Nikula 		kfree(connector);
4261379bc100SJani Nikula 		return NULL;
4262379bc100SJani Nikula 	}
4263379bc100SJani Nikula 
42646306d8dbSHans de Goede 	if (dig_port->base.type == INTEL_OUTPUT_EDP) {
42656306d8dbSHans de Goede 		struct drm_device *dev = dig_port->base.base.dev;
42666306d8dbSHans de Goede 		struct drm_privacy_screen *privacy_screen;
42676306d8dbSHans de Goede 
42686306d8dbSHans de Goede 		privacy_screen = drm_privacy_screen_get(dev->dev, NULL);
42696306d8dbSHans de Goede 		if (!IS_ERR(privacy_screen)) {
42706306d8dbSHans de Goede 			drm_connector_attach_privacy_screen_provider(&connector->base,
42716306d8dbSHans de Goede 								     privacy_screen);
42726306d8dbSHans de Goede 		} else if (PTR_ERR(privacy_screen) != -ENODEV) {
42736306d8dbSHans de Goede 			drm_warn(dev, "Error getting privacy-screen\n");
42746306d8dbSHans de Goede 		}
42756306d8dbSHans de Goede 	}
42766306d8dbSHans de Goede 
4277379bc100SJani Nikula 	return connector;
4278379bc100SJani Nikula }
4279379bc100SJani Nikula 
4280379bc100SJani Nikula static int modeset_pipe(struct drm_crtc *crtc,
4281379bc100SJani Nikula 			struct drm_modeset_acquire_ctx *ctx)
4282379bc100SJani Nikula {
4283379bc100SJani Nikula 	struct drm_atomic_state *state;
4284379bc100SJani Nikula 	struct drm_crtc_state *crtc_state;
4285379bc100SJani Nikula 	int ret;
4286379bc100SJani Nikula 
4287379bc100SJani Nikula 	state = drm_atomic_state_alloc(crtc->dev);
4288379bc100SJani Nikula 	if (!state)
4289379bc100SJani Nikula 		return -ENOMEM;
4290379bc100SJani Nikula 
4291379bc100SJani Nikula 	state->acquire_ctx = ctx;
429276ec6927SVille Syrjälä 	to_intel_atomic_state(state)->internal = true;
4293379bc100SJani Nikula 
4294379bc100SJani Nikula 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
4295379bc100SJani Nikula 	if (IS_ERR(crtc_state)) {
4296379bc100SJani Nikula 		ret = PTR_ERR(crtc_state);
4297379bc100SJani Nikula 		goto out;
4298379bc100SJani Nikula 	}
4299379bc100SJani Nikula 
4300379bc100SJani Nikula 	crtc_state->connectors_changed = true;
4301379bc100SJani Nikula 
4302379bc100SJani Nikula 	ret = drm_atomic_commit(state);
4303379bc100SJani Nikula out:
4304379bc100SJani Nikula 	drm_atomic_state_put(state);
4305379bc100SJani Nikula 
4306379bc100SJani Nikula 	return ret;
4307379bc100SJani Nikula }
4308379bc100SJani Nikula 
4309379bc100SJani Nikula static int intel_hdmi_reset_link(struct intel_encoder *encoder,
4310379bc100SJani Nikula 				 struct drm_modeset_acquire_ctx *ctx)
4311379bc100SJani Nikula {
4312379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4313b7d02c3aSVille Syrjälä 	struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
4314379bc100SJani Nikula 	struct intel_connector *connector = hdmi->attached_connector;
4315379bc100SJani Nikula 	struct i2c_adapter *adapter =
4316379bc100SJani Nikula 		intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
4317379bc100SJani Nikula 	struct drm_connector_state *conn_state;
4318379bc100SJani Nikula 	struct intel_crtc_state *crtc_state;
4319379bc100SJani Nikula 	struct intel_crtc *crtc;
4320379bc100SJani Nikula 	u8 config;
4321379bc100SJani Nikula 	int ret;
4322379bc100SJani Nikula 
4323379bc100SJani Nikula 	if (!connector || connector->base.status != connector_status_connected)
4324379bc100SJani Nikula 		return 0;
4325379bc100SJani Nikula 
4326379bc100SJani Nikula 	ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex,
4327379bc100SJani Nikula 			       ctx);
4328379bc100SJani Nikula 	if (ret)
4329379bc100SJani Nikula 		return ret;
4330379bc100SJani Nikula 
4331379bc100SJani Nikula 	conn_state = connector->base.state;
4332379bc100SJani Nikula 
4333379bc100SJani Nikula 	crtc = to_intel_crtc(conn_state->crtc);
4334379bc100SJani Nikula 	if (!crtc)
4335379bc100SJani Nikula 		return 0;
4336379bc100SJani Nikula 
4337379bc100SJani Nikula 	ret = drm_modeset_lock(&crtc->base.mutex, ctx);
4338379bc100SJani Nikula 	if (ret)
4339379bc100SJani Nikula 		return ret;
4340379bc100SJani Nikula 
4341379bc100SJani Nikula 	crtc_state = to_intel_crtc_state(crtc->base.state);
4342379bc100SJani Nikula 
43431de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm,
43441de143ccSPankaj Bharadiya 		    !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI));
4345379bc100SJani Nikula 
43461326a92cSMaarten Lankhorst 	if (!crtc_state->hw.active)
4347379bc100SJani Nikula 		return 0;
4348379bc100SJani Nikula 
4349379bc100SJani Nikula 	if (!crtc_state->hdmi_high_tmds_clock_ratio &&
4350379bc100SJani Nikula 	    !crtc_state->hdmi_scrambling)
4351379bc100SJani Nikula 		return 0;
4352379bc100SJani Nikula 
4353379bc100SJani Nikula 	if (conn_state->commit &&
4354379bc100SJani Nikula 	    !try_wait_for_completion(&conn_state->commit->hw_done))
4355379bc100SJani Nikula 		return 0;
4356379bc100SJani Nikula 
4357379bc100SJani Nikula 	ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
4358379bc100SJani Nikula 	if (ret < 0) {
435947bdb1caSJani Nikula 		drm_err(&dev_priv->drm, "Failed to read TMDS config: %d\n",
436047bdb1caSJani Nikula 			ret);
4361379bc100SJani Nikula 		return 0;
4362379bc100SJani Nikula 	}
4363379bc100SJani Nikula 
4364379bc100SJani Nikula 	if (!!(config & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) ==
4365379bc100SJani Nikula 	    crtc_state->hdmi_high_tmds_clock_ratio &&
4366379bc100SJani Nikula 	    !!(config & SCDC_SCRAMBLING_ENABLE) ==
4367379bc100SJani Nikula 	    crtc_state->hdmi_scrambling)
4368379bc100SJani Nikula 		return 0;
4369379bc100SJani Nikula 
4370379bc100SJani Nikula 	/*
4371379bc100SJani Nikula 	 * HDMI 2.0 says that one should not send scrambled data
4372379bc100SJani Nikula 	 * prior to configuring the sink scrambling, and that
4373379bc100SJani Nikula 	 * TMDS clock/data transmission should be suspended when
4374379bc100SJani Nikula 	 * changing the TMDS clock rate in the sink. So let's
4375379bc100SJani Nikula 	 * just do a full modeset here, even though some sinks
4376379bc100SJani Nikula 	 * would be perfectly happy if were to just reconfigure
4377379bc100SJani Nikula 	 * the SCDC settings on the fly.
4378379bc100SJani Nikula 	 */
4379379bc100SJani Nikula 	return modeset_pipe(&crtc->base, ctx);
4380379bc100SJani Nikula }
4381379bc100SJani Nikula 
43823944709dSImre Deak static enum intel_hotplug_state
43833944709dSImre Deak intel_ddi_hotplug(struct intel_encoder *encoder,
43848c8919c7SImre Deak 		  struct intel_connector *connector)
4385379bc100SJani Nikula {
4386b4df5405SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4387b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
4388699390f7SVille Syrjälä 	struct intel_dp *intel_dp = &dig_port->dp;
4389b4df5405SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4390b4df5405SImre Deak 	bool is_tc = intel_phy_is_tc(i915, phy);
4391379bc100SJani Nikula 	struct drm_modeset_acquire_ctx ctx;
43923944709dSImre Deak 	enum intel_hotplug_state state;
4393379bc100SJani Nikula 	int ret;
4394379bc100SJani Nikula 
4395699390f7SVille Syrjälä 	if (intel_dp->compliance.test_active &&
4396699390f7SVille Syrjälä 	    intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
4397699390f7SVille Syrjälä 		intel_dp_phy_test(encoder);
4398699390f7SVille Syrjälä 		/* just do the PHY test and nothing else */
4399699390f7SVille Syrjälä 		return INTEL_HOTPLUG_UNCHANGED;
4400699390f7SVille Syrjälä 	}
4401699390f7SVille Syrjälä 
44028c8919c7SImre Deak 	state = intel_encoder_hotplug(encoder, connector);
4403379bc100SJani Nikula 
4404379bc100SJani Nikula 	drm_modeset_acquire_init(&ctx, 0);
4405379bc100SJani Nikula 
4406379bc100SJani Nikula 	for (;;) {
4407379bc100SJani Nikula 		if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA)
4408379bc100SJani Nikula 			ret = intel_hdmi_reset_link(encoder, &ctx);
4409379bc100SJani Nikula 		else
4410379bc100SJani Nikula 			ret = intel_dp_retrain_link(encoder, &ctx);
4411379bc100SJani Nikula 
4412379bc100SJani Nikula 		if (ret == -EDEADLK) {
4413379bc100SJani Nikula 			drm_modeset_backoff(&ctx);
4414379bc100SJani Nikula 			continue;
4415379bc100SJani Nikula 		}
4416379bc100SJani Nikula 
4417379bc100SJani Nikula 		break;
4418379bc100SJani Nikula 	}
4419379bc100SJani Nikula 
4420379bc100SJani Nikula 	drm_modeset_drop_locks(&ctx);
4421379bc100SJani Nikula 	drm_modeset_acquire_fini(&ctx);
44223a47ae20SPankaj Bharadiya 	drm_WARN(encoder->base.dev, ret,
44233a47ae20SPankaj Bharadiya 		 "Acquiring modeset locks failed with %i\n", ret);
4424379bc100SJani Nikula 
4425bb80c925SJosé Roberto de Souza 	/*
4426bb80c925SJosé Roberto de Souza 	 * Unpowered type-c dongles can take some time to boot and be
4427bb80c925SJosé Roberto de Souza 	 * responsible, so here giving some time to those dongles to power up
4428bb80c925SJosé Roberto de Souza 	 * and then retrying the probe.
4429bb80c925SJosé Roberto de Souza 	 *
4430bb80c925SJosé Roberto de Souza 	 * On many platforms the HDMI live state signal is known to be
4431bb80c925SJosé Roberto de Souza 	 * unreliable, so we can't use it to detect if a sink is connected or
4432bb80c925SJosé Roberto de Souza 	 * not. Instead we detect if it's connected based on whether we can
4433bb80c925SJosé Roberto de Souza 	 * read the EDID or not. That in turn has a problem during disconnect,
4434bb80c925SJosé Roberto de Souza 	 * since the HPD interrupt may be raised before the DDC lines get
4435bb80c925SJosé Roberto de Souza 	 * disconnected (due to how the required length of DDC vs. HPD
4436bb80c925SJosé Roberto de Souza 	 * connector pins are specified) and so we'll still be able to get a
4437bb80c925SJosé Roberto de Souza 	 * valid EDID. To solve this schedule another detection cycle if this
4438bb80c925SJosé Roberto de Souza 	 * time around we didn't detect any change in the sink's connection
4439bb80c925SJosé Roberto de Souza 	 * status.
4440b4df5405SImre Deak 	 *
4441b4df5405SImre Deak 	 * Type-c connectors which get their HPD signal deasserted then
4442b4df5405SImre Deak 	 * reasserted, without unplugging/replugging the sink from the
4443b4df5405SImre Deak 	 * connector, introduce a delay until the AUX channel communication
4444b4df5405SImre Deak 	 * becomes functional. Retry the detection for 5 seconds on type-c
4445b4df5405SImre Deak 	 * connectors to account for this delay.
4446bb80c925SJosé Roberto de Souza 	 */
4447b4df5405SImre Deak 	if (state == INTEL_HOTPLUG_UNCHANGED &&
4448b4df5405SImre Deak 	    connector->hotplug_retries < (is_tc ? 5 : 1) &&
4449bb80c925SJosé Roberto de Souza 	    !dig_port->dp.is_mst)
4450bb80c925SJosé Roberto de Souza 		state = INTEL_HOTPLUG_RETRY;
4451bb80c925SJosé Roberto de Souza 
44523944709dSImre Deak 	return state;
4453379bc100SJani Nikula }
4454379bc100SJani Nikula 
4455edc0e09cSVille Syrjälä static bool lpt_digital_port_connected(struct intel_encoder *encoder)
4456edc0e09cSVille Syrjälä {
4457edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
44585a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin];
4459edc0e09cSVille Syrjälä 
4460edc0e09cSVille Syrjälä 	return intel_de_read(dev_priv, SDEISR) & bit;
4461edc0e09cSVille Syrjälä }
4462edc0e09cSVille Syrjälä 
4463edc0e09cSVille Syrjälä static bool hsw_digital_port_connected(struct intel_encoder *encoder)
4464edc0e09cSVille Syrjälä {
4465edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
44665a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4467edc0e09cSVille Syrjälä 
4468c7e8a3d6SVille Syrjälä 	return intel_de_read(dev_priv, DEISR) & bit;
4469edc0e09cSVille Syrjälä }
4470edc0e09cSVille Syrjälä 
4471edc0e09cSVille Syrjälä static bool bdw_digital_port_connected(struct intel_encoder *encoder)
4472edc0e09cSVille Syrjälä {
4473edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
44745a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4475edc0e09cSVille Syrjälä 
4476edc0e09cSVille Syrjälä 	return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit;
4477edc0e09cSVille Syrjälä }
4478edc0e09cSVille Syrjälä 
4479379bc100SJani Nikula static struct intel_connector *
44807801f3b7SLucas De Marchi intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port)
4481379bc100SJani Nikula {
4482379bc100SJani Nikula 	struct intel_connector *connector;
44837801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4484379bc100SJani Nikula 
4485379bc100SJani Nikula 	connector = intel_connector_alloc();
4486379bc100SJani Nikula 	if (!connector)
4487379bc100SJani Nikula 		return NULL;
4488379bc100SJani Nikula 
44897801f3b7SLucas De Marchi 	dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
44907801f3b7SLucas De Marchi 	intel_hdmi_init_connector(dig_port, connector);
4491379bc100SJani Nikula 
4492379bc100SJani Nikula 	return connector;
4493379bc100SJani Nikula }
4494379bc100SJani Nikula 
44957801f3b7SLucas De Marchi static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
4496379bc100SJani Nikula {
44977801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
4498379bc100SJani Nikula 
44997801f3b7SLucas De Marchi 	if (dig_port->base.port != PORT_A)
4500379bc100SJani Nikula 		return false;
4501379bc100SJani Nikula 
45027801f3b7SLucas De Marchi 	if (dig_port->saved_port_bits & DDI_A_4_LANES)
4503379bc100SJani Nikula 		return false;
4504379bc100SJani Nikula 
4505379bc100SJani Nikula 	/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
4506379bc100SJani Nikula 	 *                     supported configuration
4507379bc100SJani Nikula 	 */
45082446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4509379bc100SJani Nikula 		return true;
4510379bc100SJani Nikula 
4511379bc100SJani Nikula 	return false;
4512379bc100SJani Nikula }
4513379bc100SJani Nikula 
4514379bc100SJani Nikula static int
45157801f3b7SLucas De Marchi intel_ddi_max_lanes(struct intel_digital_port *dig_port)
4516379bc100SJani Nikula {
45177801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
45187801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4519379bc100SJani Nikula 	int max_lanes = 4;
4520379bc100SJani Nikula 
4521005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
4522379bc100SJani Nikula 		return max_lanes;
4523379bc100SJani Nikula 
4524379bc100SJani Nikula 	if (port == PORT_A || port == PORT_E) {
4525f7960e7fSJani Nikula 		if (intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
4526379bc100SJani Nikula 			max_lanes = port == PORT_A ? 4 : 0;
4527379bc100SJani Nikula 		else
4528379bc100SJani Nikula 			/* Both A and E share 2 lanes */
4529379bc100SJani Nikula 			max_lanes = 2;
4530379bc100SJani Nikula 	}
4531379bc100SJani Nikula 
4532379bc100SJani Nikula 	/*
4533379bc100SJani Nikula 	 * Some BIOS might fail to set this bit on port A if eDP
4534379bc100SJani Nikula 	 * wasn't lit up at boot.  Force this bit set when needed
4535379bc100SJani Nikula 	 * so we use the proper lane count for our calculations.
4536379bc100SJani Nikula 	 */
45377801f3b7SLucas De Marchi 	if (intel_ddi_a_force_4_lanes(dig_port)) {
453847bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
453947bdb1caSJani Nikula 			    "Forcing DDI_A_4_LANES for port A\n");
45407801f3b7SLucas De Marchi 		dig_port->saved_port_bits |= DDI_A_4_LANES;
4541379bc100SJani Nikula 		max_lanes = 4;
4542379bc100SJani Nikula 	}
4543379bc100SJani Nikula 
4544379bc100SJani Nikula 	return max_lanes;
4545379bc100SJani Nikula }
4546379bc100SJani Nikula 
4547ed2615a8SMatt Roper static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv,
4548ed2615a8SMatt Roper 				  enum port port)
4549ed2615a8SMatt Roper {
4550ed2615a8SMatt Roper 	if (port >= PORT_D_XELPD)
4551ed2615a8SMatt Roper 		return HPD_PORT_D + port - PORT_D_XELPD;
4552ed2615a8SMatt Roper 	else if (port >= PORT_TC1)
4553ed2615a8SMatt Roper 		return HPD_PORT_TC1 + port - PORT_TC1;
4554ed2615a8SMatt Roper 	else
4555ed2615a8SMatt Roper 		return HPD_PORT_A + port - PORT_A;
4556ed2615a8SMatt Roper }
4557ed2615a8SMatt Roper 
4558229f31e2SLucas De Marchi static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv,
4559229f31e2SLucas De Marchi 				enum port port)
4560229f31e2SLucas De Marchi {
45611d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
45621d8ca002SVille Syrjälä 		return HPD_PORT_C + port - PORT_TC1;
4563229f31e2SLucas De Marchi 	else
4564229f31e2SLucas De Marchi 		return HPD_PORT_A + port - PORT_A;
4565229f31e2SLucas De Marchi }
4566229f31e2SLucas De Marchi 
4567da51e4baSVille Syrjälä static enum hpd_pin tgl_hpd_pin(struct drm_i915_private *dev_priv,
4568da51e4baSVille Syrjälä 				enum port port)
4569da51e4baSVille Syrjälä {
45701d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
45711d8ca002SVille Syrjälä 		return HPD_PORT_TC1 + port - PORT_TC1;
4572da51e4baSVille Syrjälä 	else
4573da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4574da51e4baSVille Syrjälä }
4575da51e4baSVille Syrjälä 
4576da51e4baSVille Syrjälä static enum hpd_pin rkl_hpd_pin(struct drm_i915_private *dev_priv,
4577da51e4baSVille Syrjälä 				enum port port)
4578da51e4baSVille Syrjälä {
4579da51e4baSVille Syrjälä 	if (HAS_PCH_TGP(dev_priv))
4580da51e4baSVille Syrjälä 		return tgl_hpd_pin(dev_priv, port);
4581da51e4baSVille Syrjälä 
45821d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
45831d8ca002SVille Syrjälä 		return HPD_PORT_C + port - PORT_TC1;
4584da51e4baSVille Syrjälä 	else
4585da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4586da51e4baSVille Syrjälä }
4587da51e4baSVille Syrjälä 
4588da51e4baSVille Syrjälä static enum hpd_pin icl_hpd_pin(struct drm_i915_private *dev_priv,
4589da51e4baSVille Syrjälä 				enum port port)
4590da51e4baSVille Syrjälä {
4591da51e4baSVille Syrjälä 	if (port >= PORT_C)
4592da51e4baSVille Syrjälä 		return HPD_PORT_TC1 + port - PORT_C;
4593da51e4baSVille Syrjälä 	else
4594da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4595da51e4baSVille Syrjälä }
4596da51e4baSVille Syrjälä 
4597da51e4baSVille Syrjälä static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv,
4598da51e4baSVille Syrjälä 				enum port port)
4599da51e4baSVille Syrjälä {
4600da51e4baSVille Syrjälä 	if (port == PORT_D)
4601da51e4baSVille Syrjälä 		return HPD_PORT_A;
4602da51e4baSVille Syrjälä 
4603f24d1d45SVille Syrjälä 	if (HAS_PCH_TGP(dev_priv))
4604da51e4baSVille Syrjälä 		return icl_hpd_pin(dev_priv, port);
4605da51e4baSVille Syrjälä 
4606da51e4baSVille Syrjälä 	return HPD_PORT_A + port - PORT_A;
4607da51e4baSVille Syrjälä }
4608da51e4baSVille Syrjälä 
4609c8455098SLyude Paul static enum hpd_pin skl_hpd_pin(struct drm_i915_private *dev_priv, enum port port)
4610c8455098SLyude Paul {
4611c8455098SLyude Paul 	if (HAS_PCH_TGP(dev_priv))
4612c8455098SLyude Paul 		return icl_hpd_pin(dev_priv, port);
4613c8455098SLyude Paul 
4614c8455098SLyude Paul 	return HPD_PORT_A + port - PORT_A;
4615c8455098SLyude Paul }
4616c8455098SLyude Paul 
461736ecb0ecSVille Syrjälä static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port)
461836ecb0ecSVille Syrjälä {
4619005e9537SMatt Roper 	if (DISPLAY_VER(i915) >= 12)
462036ecb0ecSVille Syrjälä 		return port >= PORT_TC1;
4621005e9537SMatt Roper 	else if (DISPLAY_VER(i915) >= 11)
462236ecb0ecSVille Syrjälä 		return port >= PORT_C;
462336ecb0ecSVille Syrjälä 	else
462436ecb0ecSVille Syrjälä 		return false;
462536ecb0ecSVille Syrjälä }
462636ecb0ecSVille Syrjälä 
4627151ec347SImre Deak static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
4628151ec347SImre Deak {
4629151ec347SImre Deak 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4630151ec347SImre Deak 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
4631151ec347SImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4632151ec347SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4633151ec347SImre Deak 
4634151ec347SImre Deak 	intel_dp_encoder_suspend(encoder);
4635151ec347SImre Deak 
4636151ec347SImre Deak 	if (!intel_phy_is_tc(i915, phy))
4637151ec347SImre Deak 		return;
4638151ec347SImre Deak 
46393e0abc76SImre Deak 	intel_tc_port_flush_work(dig_port);
4640151ec347SImre Deak }
4641151ec347SImre Deak 
4642151ec347SImre Deak static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
4643151ec347SImre Deak {
4644151ec347SImre Deak 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4645151ec347SImre Deak 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
4646151ec347SImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4647151ec347SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4648151ec347SImre Deak 
4649151ec347SImre Deak 	intel_dp_encoder_shutdown(encoder);
465049c55f7bSVille Syrjälä 	intel_hdmi_encoder_shutdown(encoder);
4651151ec347SImre Deak 
4652151ec347SImre Deak 	if (!intel_phy_is_tc(i915, phy))
4653151ec347SImre Deak 		return;
4654151ec347SImre Deak 
4655c5879999SImre Deak 	intel_tc_port_cleanup(dig_port);
4656151ec347SImre Deak }
4657151ec347SImre Deak 
465883566d13SVille Syrjälä #define port_tc_name(port) ((port) - PORT_TC1 + '1')
465983566d13SVille Syrjälä #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1')
466083566d13SVille Syrjälä 
4661379bc100SJani Nikula void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
4662379bc100SJani Nikula {
46637801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port;
466470dfbc29SLucas De Marchi 	struct intel_encoder *encoder;
466545c0673aSJani Nikula 	const struct intel_bios_encoder_data *devdata;
4666f542d671SKai-Heng Feng 	bool init_hdmi, init_dp;
4667d8fe2ab6SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, port);
4668379bc100SJani Nikula 
4669ddff9a60SMatt Roper 	/*
4670ddff9a60SMatt Roper 	 * On platforms with HTI (aka HDPORT), if it's enabled at boot it may
4671ddff9a60SMatt Roper 	 * have taken over some of the PHYs and made them unavailable to the
4672ddff9a60SMatt Roper 	 * driver.  In that case we should skip initializing the corresponding
4673ddff9a60SMatt Roper 	 * outputs.
4674ddff9a60SMatt Roper 	 */
467503120fefSJani Nikula 	if (intel_hti_uses_phy(dev_priv, phy)) {
4676ddff9a60SMatt Roper 		drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n",
4677ddff9a60SMatt Roper 			    port_name(port), phy_name(phy));
4678ddff9a60SMatt Roper 		return;
4679ddff9a60SMatt Roper 	}
4680ddff9a60SMatt Roper 
468145c0673aSJani Nikula 	devdata = intel_bios_encoder_data_lookup(dev_priv, port);
468245c0673aSJani Nikula 	if (!devdata) {
468345c0673aSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
468445c0673aSJani Nikula 			    "VBT says port %c is not present\n",
468545c0673aSJani Nikula 			    port_name(port));
468645c0673aSJani Nikula 		return;
468745c0673aSJani Nikula 	}
468845c0673aSJani Nikula 
468945c0673aSJani Nikula 	init_hdmi = intel_bios_encoder_supports_dvi(devdata) ||
469045c0673aSJani Nikula 		intel_bios_encoder_supports_hdmi(devdata);
469145c0673aSJani Nikula 	init_dp = intel_bios_encoder_supports_dp(devdata);
4692379bc100SJani Nikula 
4693db5d650fSVille Syrjälä 	if (intel_bios_encoder_is_lspcon(devdata)) {
4694379bc100SJani Nikula 		/*
4695379bc100SJani Nikula 		 * Lspcon device needs to be driven with DP connector
4696379bc100SJani Nikula 		 * with special detection sequence. So make sure DP
4697379bc100SJani Nikula 		 * is initialized before lspcon.
4698379bc100SJani Nikula 		 */
4699379bc100SJani Nikula 		init_dp = true;
4700379bc100SJani Nikula 		init_hdmi = false;
470147bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm, "VBT says port %c has lspcon\n",
470247bdb1caSJani Nikula 			    port_name(port));
4703379bc100SJani Nikula 	}
4704379bc100SJani Nikula 
4705379bc100SJani Nikula 	if (!init_dp && !init_hdmi) {
470647bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
470747bdb1caSJani Nikula 			    "VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
4708379bc100SJani Nikula 			    port_name(port));
4709379bc100SJani Nikula 		return;
4710379bc100SJani Nikula 	}
4711379bc100SJani Nikula 
4712b4eb76d8SMatt Roper 	if (intel_phy_is_snps(dev_priv, phy) &&
47133a7e2d58SJani Nikula 	    dev_priv->display.snps.phy_failed_calibration & BIT(phy)) {
4714b4eb76d8SMatt Roper 		drm_dbg_kms(&dev_priv->drm,
471582c362f2SLucas De Marchi 			    "SNPS PHY %c failed to calibrate, proceeding anyway\n",
4716b4eb76d8SMatt Roper 			    phy_name(phy));
4717b4eb76d8SMatt Roper 	}
4718b4eb76d8SMatt Roper 
47197801f3b7SLucas De Marchi 	dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
47207801f3b7SLucas De Marchi 	if (!dig_port)
4721379bc100SJani Nikula 		return;
4722379bc100SJani Nikula 
47237801f3b7SLucas De Marchi 	encoder = &dig_port->base;
4724c0a950d1SJani Nikula 	encoder->devdata = devdata;
4725379bc100SJani Nikula 
4726ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) {
4727ed2615a8SMatt Roper 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
4728ed2615a8SMatt Roper 				 DRM_MODE_ENCODER_TMDS,
4729ed2615a8SMatt Roper 				 "DDI %c/PHY %c",
4730ed2615a8SMatt Roper 				 port_name(port - PORT_D_XELPD + PORT_D),
4731ed2615a8SMatt Roper 				 phy_name(phy));
4732ed2615a8SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 12) {
47332d709a5aSVille Syrjälä 		enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
47342d709a5aSVille Syrjälä 
473570dfbc29SLucas De Marchi 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
47362d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
47372d709a5aSVille Syrjälä 				 "DDI %s%c/PHY %s%c",
47382d709a5aSVille Syrjälä 				 port >= PORT_TC1 ? "TC" : "",
473983566d13SVille Syrjälä 				 port >= PORT_TC1 ? port_tc_name(port) : port_name(port),
47402d709a5aSVille Syrjälä 				 tc_port != TC_PORT_NONE ? "TC" : "",
474183566d13SVille Syrjälä 				 tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
4742005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
47432d709a5aSVille Syrjälä 		enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
47442d709a5aSVille Syrjälä 
47452d709a5aSVille Syrjälä 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
47462d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
47472d709a5aSVille Syrjälä 				 "DDI %c%s/PHY %s%c",
47482d709a5aSVille Syrjälä 				 port_name(port),
47492d709a5aSVille Syrjälä 				 port >= PORT_C ? " (TC)" : "",
47502d709a5aSVille Syrjälä 				 tc_port != TC_PORT_NONE ? "TC" : "",
475183566d13SVille Syrjälä 				 tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
47522d709a5aSVille Syrjälä 	} else {
47532d709a5aSVille Syrjälä 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
47542d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
47552d709a5aSVille Syrjälä 				 "DDI %c/PHY %c", port_name(port),  phy_name(phy));
47562d709a5aSVille Syrjälä 	}
4757379bc100SJani Nikula 
475836e5e704SSean Paul 	mutex_init(&dig_port->hdcp_mutex);
475936e5e704SSean Paul 	dig_port->num_hdcp_streams = 0;
476036e5e704SSean Paul 
476170dfbc29SLucas De Marchi 	encoder->hotplug = intel_ddi_hotplug;
476270dfbc29SLucas De Marchi 	encoder->compute_output_type = intel_ddi_compute_output_type;
476370dfbc29SLucas De Marchi 	encoder->compute_config = intel_ddi_compute_config;
4764b50a1aa6SManasi Navare 	encoder->compute_config_late = intel_ddi_compute_config_late;
476570dfbc29SLucas De Marchi 	encoder->enable = intel_enable_ddi;
476670dfbc29SLucas De Marchi 	encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
476770dfbc29SLucas De Marchi 	encoder->pre_enable = intel_ddi_pre_enable;
476870dfbc29SLucas De Marchi 	encoder->disable = intel_disable_ddi;
4769b108bdd0SImre Deak 	encoder->post_pll_disable = intel_ddi_post_pll_disable;
477070dfbc29SLucas De Marchi 	encoder->post_disable = intel_ddi_post_disable;
477170dfbc29SLucas De Marchi 	encoder->update_pipe = intel_ddi_update_pipe;
477270dfbc29SLucas De Marchi 	encoder->get_hw_state = intel_ddi_get_hw_state;
4773f9e76a6eSImre Deak 	encoder->sync_state = intel_ddi_sync_state;
4774b671d6efSImre Deak 	encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
4775151ec347SImre Deak 	encoder->suspend = intel_ddi_encoder_suspend;
4776151ec347SImre Deak 	encoder->shutdown = intel_ddi_encoder_shutdown;
477770dfbc29SLucas De Marchi 	encoder->get_power_domains = intel_ddi_get_power_domains;
477870dfbc29SLucas De Marchi 
477970dfbc29SLucas De Marchi 	encoder->type = INTEL_OUTPUT_DDI;
4780979e1b32SImre Deak 	encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
478170dfbc29SLucas De Marchi 	encoder->port = port;
478270dfbc29SLucas De Marchi 	encoder->cloneable = 0;
478370dfbc29SLucas De Marchi 	encoder->pipe_mask = ~0;
4784da51e4baSVille Syrjälä 
478551390cc0SRadhakrishna Sripada 	if (DISPLAY_VER(dev_priv) >= 14) {
478673fc3abcSMika Kahola 		encoder->enable_clock = intel_mtl_pll_enable;
478773fc3abcSMika Kahola 		encoder->disable_clock = intel_mtl_pll_disable;
47886f0423b0SMika Kahola 		encoder->port_pll_type = intel_mtl_port_pll_type;
478951390cc0SRadhakrishna Sripada 		encoder->get_config = mtl_ddi_get_config;
479051390cc0SRadhakrishna Sripada 	} else if (IS_DG2(dev_priv)) {
4791f82f2563SMatt Roper 		encoder->enable_clock = intel_mpllb_enable;
4792f82f2563SMatt Roper 		encoder->disable_clock = intel_mpllb_disable;
4793865b73eaSMatt Roper 		encoder->get_config = dg2_ddi_get_config;
4794865b73eaSMatt Roper 	} else if (IS_ALDERLAKE_S(dev_priv)) {
479540b316d4SVille Syrjälä 		encoder->enable_clock = adls_ddi_enable_clock;
479640b316d4SVille Syrjälä 		encoder->disable_clock = adls_ddi_disable_clock;
47970fbd8694SVille Syrjälä 		encoder->is_clock_enabled = adls_ddi_is_clock_enabled;
4798351221ffSVille Syrjälä 		encoder->get_config = adls_ddi_get_config;
479940b316d4SVille Syrjälä 	} else if (IS_ROCKETLAKE(dev_priv)) {
480040b316d4SVille Syrjälä 		encoder->enable_clock = rkl_ddi_enable_clock;
480140b316d4SVille Syrjälä 		encoder->disable_clock = rkl_ddi_disable_clock;
48020fbd8694SVille Syrjälä 		encoder->is_clock_enabled = rkl_ddi_is_clock_enabled;
4803351221ffSVille Syrjälä 		encoder->get_config = rkl_ddi_get_config;
480436ecb0ecSVille Syrjälä 	} else if (IS_DG1(dev_priv)) {
480535bb6b1aSVille Syrjälä 		encoder->enable_clock = dg1_ddi_enable_clock;
480635bb6b1aSVille Syrjälä 		encoder->disable_clock = dg1_ddi_disable_clock;
48070fbd8694SVille Syrjälä 		encoder->is_clock_enabled = dg1_ddi_is_clock_enabled;
4808351221ffSVille Syrjälä 		encoder->get_config = dg1_ddi_get_config;
480936ecb0ecSVille Syrjälä 	} else if (IS_JSL_EHL(dev_priv)) {
481036ecb0ecSVille Syrjälä 		if (intel_ddi_is_tc(dev_priv, port)) {
481136ecb0ecSVille Syrjälä 			encoder->enable_clock = jsl_ddi_tc_enable_clock;
481236ecb0ecSVille Syrjälä 			encoder->disable_clock = jsl_ddi_tc_disable_clock;
48130fbd8694SVille Syrjälä 			encoder->is_clock_enabled = jsl_ddi_tc_is_clock_enabled;
48147c1da068SImre Deak 			encoder->port_pll_type = icl_ddi_tc_port_pll_type;
4815351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
481636ecb0ecSVille Syrjälä 		} else {
481736ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_combo_enable_clock;
481836ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_combo_disable_clock;
48190fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
4820351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
482136ecb0ecSVille Syrjälä 		}
4822005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
482336ecb0ecSVille Syrjälä 		if (intel_ddi_is_tc(dev_priv, port)) {
482436ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_tc_enable_clock;
482536ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_tc_disable_clock;
48260fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_tc_is_clock_enabled;
48277c1da068SImre Deak 			encoder->port_pll_type = icl_ddi_tc_port_pll_type;
4828351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_tc_get_config;
482936ecb0ecSVille Syrjälä 		} else {
483036ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_combo_enable_clock;
483136ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_combo_disable_clock;
48320fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
4833351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
483436ecb0ecSVille Syrjälä 		}
48352446e1d6SMatt Roper 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
4836351221ffSVille Syrjälä 		/* BXT/GLK have fixed PLL->port mapping */
4837351221ffSVille Syrjälä 		encoder->get_config = bxt_ddi_get_config;
483893e7e61eSLucas De Marchi 	} else if (DISPLAY_VER(dev_priv) == 9) {
483938e31f1aSVille Syrjälä 		encoder->enable_clock = skl_ddi_enable_clock;
484038e31f1aSVille Syrjälä 		encoder->disable_clock = skl_ddi_disable_clock;
48410fbd8694SVille Syrjälä 		encoder->is_clock_enabled = skl_ddi_is_clock_enabled;
4842351221ffSVille Syrjälä 		encoder->get_config = skl_ddi_get_config;
484338e31f1aSVille Syrjälä 	} else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
4844d135368dSVille Syrjälä 		encoder->enable_clock = hsw_ddi_enable_clock;
4845d135368dSVille Syrjälä 		encoder->disable_clock = hsw_ddi_disable_clock;
48460fbd8694SVille Syrjälä 		encoder->is_clock_enabled = hsw_ddi_is_clock_enabled;
4847351221ffSVille Syrjälä 		encoder->get_config = hsw_ddi_get_config;
4848d135368dSVille Syrjälä 	}
4849d135368dSVille Syrjälä 
4850ea8af87aSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14) {
4851ea8af87aSMika Kahola 		encoder->set_signal_levels = intel_cx0_phy_set_signal_levels;
4852ea8af87aSMika Kahola 	} else if (IS_DG2(dev_priv)) {
4853193299adSVille Syrjälä 		encoder->set_signal_levels = intel_snps_phy_set_signal_levels;
4854193299adSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) >= 12) {
4855193299adSVille Syrjälä 		if (intel_phy_is_combo(dev_priv, phy))
4856193299adSVille Syrjälä 			encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
4857e722ab8bSVille Syrjälä 		else
4858193299adSVille Syrjälä 			encoder->set_signal_levels = tgl_dkl_phy_set_signal_levels;
4859193299adSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) >= 11) {
4860193299adSVille Syrjälä 		if (intel_phy_is_combo(dev_priv, phy))
4861193299adSVille Syrjälä 			encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
4862193299adSVille Syrjälä 		else
4863193299adSVille Syrjälä 			encoder->set_signal_levels = icl_mg_phy_set_signal_levels;
4864193299adSVille Syrjälä 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
48655f5ada0bSVille Syrjälä 		encoder->set_signal_levels = bxt_ddi_phy_set_signal_levels;
4866193299adSVille Syrjälä 	} else {
4867e722ab8bSVille Syrjälä 		encoder->set_signal_levels = hsw_set_signal_levels;
4868193299adSVille Syrjälä 	}
4869e722ab8bSVille Syrjälä 
4870c40a253bSVille Syrjälä 	intel_ddi_buf_trans_init(encoder);
4871c40a253bSVille Syrjälä 
4872ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
4873ed2615a8SMatt Roper 		encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port);
4874ed2615a8SMatt Roper 	else if (IS_DG1(dev_priv))
4875229f31e2SLucas De Marchi 		encoder->hpd_pin = dg1_hpd_pin(dev_priv, port);
4876229f31e2SLucas De Marchi 	else if (IS_ROCKETLAKE(dev_priv))
4877da51e4baSVille Syrjälä 		encoder->hpd_pin = rkl_hpd_pin(dev_priv, port);
4878005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
4879da51e4baSVille Syrjälä 		encoder->hpd_pin = tgl_hpd_pin(dev_priv, port);
488024ea098bSTejas Upadhyay 	else if (IS_JSL_EHL(dev_priv))
4881da51e4baSVille Syrjälä 		encoder->hpd_pin = ehl_hpd_pin(dev_priv, port);
488293e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 11)
4883da51e4baSVille Syrjälä 		encoder->hpd_pin = icl_hpd_pin(dev_priv, port);
488493e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
4885c8455098SLyude Paul 		encoder->hpd_pin = skl_hpd_pin(dev_priv, port);
4886da51e4baSVille Syrjälä 	else
488703c7e4f1SVille Syrjälä 		encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
4888379bc100SJani Nikula 
4889005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
48907801f3b7SLucas De Marchi 		dig_port->saved_port_bits =
48917801f3b7SLucas De Marchi 			intel_de_read(dev_priv, DDI_BUF_CTL(port))
48927801f3b7SLucas De Marchi 			& DDI_BUF_PORT_REVERSAL;
4893379bc100SJani Nikula 	else
48947801f3b7SLucas De Marchi 		dig_port->saved_port_bits =
48957801f3b7SLucas De Marchi 			intel_de_read(dev_priv, DDI_BUF_CTL(port))
48967801f3b7SLucas De Marchi 			& (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
489770dfbc29SLucas De Marchi 
48985f42196dSVille Syrjälä 	if (intel_bios_encoder_lane_reversal(devdata))
4899aaab24bbSUma Shankar 		dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
4900aaab24bbSUma Shankar 
49017801f3b7SLucas De Marchi 	dig_port->dp.output_reg = INVALID_MMIO_REG;
49027801f3b7SLucas De Marchi 	dig_port->max_lanes = intel_ddi_max_lanes(dig_port);
4903bb45217fSVille Syrjälä 	dig_port->aux_ch = intel_dp_aux_ch(encoder);
4904379bc100SJani Nikula 
4905d8fe2ab6SMatt Roper 	if (intel_phy_is_tc(dev_priv, phy)) {
4906c5faae5aSJani Nikula 		bool is_legacy =
4907f08fbe6aSJani Nikula 			!intel_bios_encoder_supports_typec_usb(devdata) &&
4908f08fbe6aSJani Nikula 			!intel_bios_encoder_supports_tbt(devdata);
4909379bc100SJani Nikula 
491040a55b84SImre Deak 		if (!is_legacy && init_hdmi) {
491140a55b84SImre Deak 			is_legacy = !init_dp;
491240a55b84SImre Deak 
491340a55b84SImre Deak 			drm_dbg_kms(&dev_priv->drm,
491440a55b84SImre Deak 				    "VBT says port %c is non-legacy TC and has HDMI (with DP: %s), assume it's %s\n",
491540a55b84SImre Deak 				    port_name(port),
491640a55b84SImre Deak 				    str_yes_no(init_dp),
491740a55b84SImre Deak 				    is_legacy ? "legacy" : "non-legacy");
491840a55b84SImre Deak 		}
491940a55b84SImre Deak 
4920c5879999SImre Deak 		if (intel_tc_port_init(dig_port, is_legacy) < 0)
4921c5879999SImre Deak 			goto err;
4922ab7bc4e1SImre Deak 	}
4923ab7bc4e1SImre Deak 
49241de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, port > PORT_I);
4925979e1b32SImre Deak 	dig_port->ddi_io_power_domain = intel_display_power_ddi_io_domain(dev_priv, port);
4926379bc100SJani Nikula 
4927005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
4928edc0e09cSVille Syrjälä 		if (intel_phy_is_tc(dev_priv, phy))
49297801f3b7SLucas De Marchi 			dig_port->connected = intel_tc_port_connected;
4930edc0e09cSVille Syrjälä 		else
49317801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4932dded35acSVille Syrjälä 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
4933dded35acSVille Syrjälä 		dig_port->connected = bdw_digital_port_connected;
4934dded35acSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) == 9) {
4935dded35acSVille Syrjälä 		dig_port->connected = lpt_digital_port_connected;
4936dded35acSVille Syrjälä 	} else if (IS_BROADWELL(dev_priv)) {
4937dded35acSVille Syrjälä 		if (port == PORT_A)
49387801f3b7SLucas De Marchi 			dig_port->connected = bdw_digital_port_connected;
4939edc0e09cSVille Syrjälä 		else
49407801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4941dded35acSVille Syrjälä 	} else if (IS_HASWELL(dev_priv)) {
4942c7e8a3d6SVille Syrjälä 		if (port == PORT_A)
49437801f3b7SLucas De Marchi 			dig_port->connected = hsw_digital_port_connected;
4944edc0e09cSVille Syrjälä 		else
49457801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4946edc0e09cSVille Syrjälä 	}
4947edc0e09cSVille Syrjälä 
49487801f3b7SLucas De Marchi 	intel_infoframe_init(dig_port);
4949379bc100SJani Nikula 
4950a98ffd6eSVille Syrjälä 	if (init_dp) {
4951a98ffd6eSVille Syrjälä 		if (!intel_ddi_init_dp_connector(dig_port))
4952a98ffd6eSVille Syrjälä 			goto err;
4953a98ffd6eSVille Syrjälä 
4954a98ffd6eSVille Syrjälä 		dig_port->hpd_pulse = intel_dp_hpd_pulse;
4955a98ffd6eSVille Syrjälä 
4956a98ffd6eSVille Syrjälä 		if (dig_port->dp.mso_link_count)
4957a98ffd6eSVille Syrjälä 			encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv);
4958a98ffd6eSVille Syrjälä 	}
4959a98ffd6eSVille Syrjälä 
4960a98ffd6eSVille Syrjälä 	/*
4961a98ffd6eSVille Syrjälä 	 * In theory we don't need the encoder->type check,
4962a98ffd6eSVille Syrjälä 	 * but leave it just in case we have some really bad VBTs...
4963a98ffd6eSVille Syrjälä 	 */
4964a98ffd6eSVille Syrjälä 	if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
4965a98ffd6eSVille Syrjälä 		if (!intel_ddi_init_hdmi_connector(dig_port))
4966a98ffd6eSVille Syrjälä 			goto err;
4967a98ffd6eSVille Syrjälä 	}
4968a98ffd6eSVille Syrjälä 
4969379bc100SJani Nikula 	return;
4970379bc100SJani Nikula 
4971379bc100SJani Nikula err:
497270dfbc29SLucas De Marchi 	drm_encoder_cleanup(&encoder->base);
49737801f3b7SLucas De Marchi 	kfree(dig_port);
4974379bc100SJani Nikula }
4975