xref: /linux/drivers/gpu/drm/i915/display/intel_ddi.c (revision 679df6f19f1ebf575f440a704bcb9fe5b6c1f7ed)
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"
6660ded7ccSImre Deak #include "intel_modeset_lock.h"
67abad6805SJani Nikula #include "intel_pps.h"
68379bc100SJani Nikula #include "intel_psr.h"
690c82118bSJani Nikula #include "intel_quirks.h"
70865b73eaSMatt Roper #include "intel_snps_phy.h"
71bc85328fSImre Deak #include "intel_tc.h"
72379bc100SJani Nikula #include "intel_vdsc.h"
73c3f05948SJani Nikula #include "intel_vdsc_regs.h"
74714b1cdbSDave Airlie #include "skl_scaler.h"
7546d12f91SDave Airlie #include "skl_universal_plane.h"
76379bc100SJani Nikula 
77379bc100SJani Nikula static const u8 index_to_dp_signal_levels[] = {
78379bc100SJani Nikula 	[0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
79379bc100SJani Nikula 	[1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1,
80379bc100SJani Nikula 	[2] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2,
81379bc100SJani Nikula 	[3] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3,
82379bc100SJani Nikula 	[4] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0,
83379bc100SJani Nikula 	[5] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1,
84379bc100SJani Nikula 	[6] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2,
85379bc100SJani Nikula 	[7] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0,
86379bc100SJani Nikula 	[8] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1,
87379bc100SJani Nikula 	[9] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0,
88379bc100SJani Nikula };
89379bc100SJani Nikula 
90a621860aSVille Syrjälä static int intel_ddi_hdmi_level(struct intel_encoder *encoder,
913e022c1fSVille Syrjälä 				const struct intel_ddi_buf_trans *trans)
92379bc100SJani Nikula {
933e022c1fSVille Syrjälä 	int level;
94379bc100SJani Nikula 
9502107ef1SVille Syrjälä 	level = intel_bios_hdmi_level_shift(encoder->devdata);
960aed3bdeSJani Nikula 	if (level < 0)
973e022c1fSVille Syrjälä 		level = trans->hdmi_default_entry;
98379bc100SJani Nikula 
99379bc100SJani Nikula 	return level;
100379bc100SJani Nikula }
101379bc100SJani Nikula 
1025bafd85dSVille Syrjälä static bool has_buf_trans_select(struct drm_i915_private *i915)
1035bafd85dSVille Syrjälä {
1045bafd85dSVille Syrjälä 	return DISPLAY_VER(i915) < 10 && !IS_BROXTON(i915);
1055bafd85dSVille Syrjälä }
1065bafd85dSVille Syrjälä 
107f820693bSVille Syrjälä static bool has_iboost(struct drm_i915_private *i915)
108f820693bSVille Syrjälä {
109f820693bSVille Syrjälä 	return DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915);
110f820693bSVille Syrjälä }
111f820693bSVille Syrjälä 
112379bc100SJani Nikula /*
113379bc100SJani Nikula  * Starting with Haswell, DDI port buffers must be programmed with correct
114379bc100SJani Nikula  * values in advance. This function programs the correct values for
115379bc100SJani Nikula  * DP/eDP/FDI use cases.
116379bc100SJani Nikula  */
117266152aeSVille Syrjälä void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
118379bc100SJani Nikula 				const struct intel_crtc_state *crtc_state)
119379bc100SJani Nikula {
120379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
121379bc100SJani Nikula 	u32 iboost_bit = 0;
122379bc100SJani Nikula 	int i, n_entries;
123379bc100SJani Nikula 	enum port port = encoder->port;
124e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
125379bc100SJani Nikula 
126e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
127e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
128d6b10b1aSVille Syrjälä 		return;
129379bc100SJani Nikula 
130379bc100SJani Nikula 	/* If we're boosting the current, set bit 31 of trans1 */
131f820693bSVille Syrjälä 	if (has_iboost(dev_priv) &&
13202107ef1SVille Syrjälä 	    intel_bios_dp_boost_level(encoder->devdata))
133379bc100SJani Nikula 		iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
134379bc100SJani Nikula 
135379bc100SJani Nikula 	for (i = 0; i < n_entries; i++) {
136f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, i),
137e505d764SVille Syrjälä 			       trans->entries[i].hsw.trans1 | iboost_bit);
138f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, i),
139e505d764SVille Syrjälä 			       trans->entries[i].hsw.trans2);
140379bc100SJani Nikula 	}
141379bc100SJani Nikula }
142379bc100SJani Nikula 
143379bc100SJani Nikula /*
144379bc100SJani Nikula  * Starting with Haswell, DDI port buffers must be programmed with correct
145379bc100SJani Nikula  * values in advance. This function programs the correct values for
146379bc100SJani Nikula  * HDMI/DVI use cases.
147379bc100SJani Nikula  */
148266152aeSVille Syrjälä static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
149e722ab8bSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
150379bc100SJani Nikula {
151379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
152d0920a45SVille Syrjälä 	int level = intel_ddi_level(encoder, crtc_state, 0);
153379bc100SJani Nikula 	u32 iboost_bit = 0;
154379bc100SJani Nikula 	int n_entries;
155379bc100SJani Nikula 	enum port port = encoder->port;
156e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
157379bc100SJani Nikula 
158e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
159e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
160379bc100SJani Nikula 		return;
161379bc100SJani Nikula 
162379bc100SJani Nikula 	/* If we're boosting the current, set bit 31 of trans1 */
163f820693bSVille Syrjälä 	if (has_iboost(dev_priv) &&
16402107ef1SVille Syrjälä 	    intel_bios_hdmi_boost_level(encoder->devdata))
165379bc100SJani Nikula 		iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
166379bc100SJani Nikula 
167379bc100SJani Nikula 	/* Entry 9 is for HDMI: */
168f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, 9),
169e505d764SVille Syrjälä 		       trans->entries[level].hsw.trans1 | iboost_bit);
170f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, 9),
171e505d764SVille Syrjälä 		       trans->entries[level].hsw.trans2);
172379bc100SJani Nikula }
173379bc100SJani Nikula 
17423ef6194SJosé Roberto de Souza static void mtl_wait_ddi_buf_idle(struct drm_i915_private *i915, enum port port)
17523ef6194SJosé Roberto de Souza {
17623ef6194SJosé Roberto de Souza 	int ret;
17723ef6194SJosé Roberto de Souza 
17823ef6194SJosé Roberto de Souza 	/* FIXME: find out why Bspec's 100us timeout is too short */
17923ef6194SJosé Roberto de Souza 	ret = wait_for_us((intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port)) &
18023ef6194SJosé Roberto de Souza 			   XELPDP_PORT_BUF_PHY_IDLE), 10000);
18123ef6194SJosé Roberto de Souza 	if (ret)
18223ef6194SJosé Roberto de Souza 		drm_err(&i915->drm, "Timeout waiting for DDI BUF %c to get idle\n",
18323ef6194SJosé Roberto de Souza 			port_name(port));
18423ef6194SJosé Roberto de Souza }
18523ef6194SJosé Roberto de Souza 
186dcb38f79SDave Airlie void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
187379bc100SJani Nikula 			     enum port port)
188379bc100SJani Nikula {
1895a2ad99bSManasi Navare 	if (IS_BROXTON(dev_priv)) {
1905a2ad99bSManasi Navare 		udelay(16);
191379bc100SJani Nikula 		return;
192379bc100SJani Nikula 	}
1935a2ad99bSManasi Navare 
1945a2ad99bSManasi Navare 	if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
1955a2ad99bSManasi Navare 			 DDI_BUF_IS_IDLE), 8))
1965a2ad99bSManasi Navare 		drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get idle\n",
19747bdb1caSJani Nikula 			port_name(port));
198379bc100SJani Nikula }
199379bc100SJani Nikula 
200e828da30SManasi Navare static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
201e828da30SManasi Navare 				      enum port port)
202e828da30SManasi Navare {
2035add4575SAnkit Nautiyal 	enum phy phy = intel_port_to_phy(dev_priv, port);
2045add4575SAnkit Nautiyal 	int timeout_us;
205f82f2563SMatt Roper 	int ret;
206f82f2563SMatt Roper 
207e828da30SManasi Navare 	/* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
208ad314fecSVille Syrjälä 	if (DISPLAY_VER(dev_priv) < 10) {
209e828da30SManasi Navare 		usleep_range(518, 1000);
210e828da30SManasi Navare 		return;
211e828da30SManasi Navare 	}
212e828da30SManasi Navare 
21323ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14) {
21423ef6194SJosé Roberto de Souza 		timeout_us = 10000;
21523ef6194SJosé Roberto de Souza 	} else if (IS_DG2(dev_priv)) {
2165add4575SAnkit Nautiyal 		timeout_us = 1200;
2175add4575SAnkit Nautiyal 	} else if (DISPLAY_VER(dev_priv) >= 12) {
2185add4575SAnkit Nautiyal 		if (intel_phy_is_tc(dev_priv, phy))
2195add4575SAnkit Nautiyal 			timeout_us = 3000;
2205add4575SAnkit Nautiyal 		else
2215add4575SAnkit Nautiyal 			timeout_us = 1000;
2225add4575SAnkit Nautiyal 	} else {
2235add4575SAnkit Nautiyal 		timeout_us = 500;
2245add4575SAnkit Nautiyal 	}
2255add4575SAnkit Nautiyal 
22623ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14)
22723ef6194SJosé Roberto de Souza 		ret = _wait_for(!(intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) & XELPDP_PORT_BUF_PHY_IDLE),
22823ef6194SJosé Roberto de Souza 				timeout_us, 10, 10);
22923ef6194SJosé Roberto de Souza 	else
23023ef6194SJosé Roberto de Souza 		ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & DDI_BUF_IS_IDLE),
23123ef6194SJosé Roberto de Souza 				timeout_us, 10, 10);
232f82f2563SMatt Roper 
233f82f2563SMatt Roper 	if (ret)
234e828da30SManasi Navare 		drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
235e828da30SManasi Navare 			port_name(port));
236e828da30SManasi Navare }
237e828da30SManasi Navare 
238ad952982SVille Syrjälä static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
239379bc100SJani Nikula {
240379bc100SJani Nikula 	switch (pll->info->id) {
241379bc100SJani Nikula 	case DPLL_ID_WRPLL1:
242379bc100SJani Nikula 		return PORT_CLK_SEL_WRPLL1;
243379bc100SJani Nikula 	case DPLL_ID_WRPLL2:
244379bc100SJani Nikula 		return PORT_CLK_SEL_WRPLL2;
245379bc100SJani Nikula 	case DPLL_ID_SPLL:
246379bc100SJani Nikula 		return PORT_CLK_SEL_SPLL;
247379bc100SJani Nikula 	case DPLL_ID_LCPLL_810:
248379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_810;
249379bc100SJani Nikula 	case DPLL_ID_LCPLL_1350:
250379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_1350;
251379bc100SJani Nikula 	case DPLL_ID_LCPLL_2700:
252379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_2700;
253379bc100SJani Nikula 	default:
254379bc100SJani Nikula 		MISSING_CASE(pll->info->id);
255379bc100SJani Nikula 		return PORT_CLK_SEL_NONE;
256379bc100SJani Nikula 	}
257379bc100SJani Nikula }
258379bc100SJani Nikula 
259379bc100SJani Nikula static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
260379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state)
261379bc100SJani Nikula {
262379bc100SJani Nikula 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
263379bc100SJani Nikula 	int clock = crtc_state->port_clock;
264379bc100SJani Nikula 	const enum intel_dpll_id id = pll->info->id;
265379bc100SJani Nikula 
266379bc100SJani Nikula 	switch (id) {
267379bc100SJani Nikula 	default:
268379bc100SJani Nikula 		/*
269379bc100SJani Nikula 		 * DPLL_ID_ICL_DPLL0 and DPLL_ID_ICL_DPLL1 should not be used
270379bc100SJani Nikula 		 * here, so do warn if this get passed in
271379bc100SJani Nikula 		 */
272379bc100SJani Nikula 		MISSING_CASE(id);
273379bc100SJani Nikula 		return DDI_CLK_SEL_NONE;
274379bc100SJani Nikula 	case DPLL_ID_ICL_TBTPLL:
275379bc100SJani Nikula 		switch (clock) {
276379bc100SJani Nikula 		case 162000:
277379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_162;
278379bc100SJani Nikula 		case 270000:
279379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_270;
280379bc100SJani Nikula 		case 540000:
281379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_540;
282379bc100SJani Nikula 		case 810000:
283379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_810;
284379bc100SJani Nikula 		default:
285379bc100SJani Nikula 			MISSING_CASE(clock);
286379bc100SJani Nikula 			return DDI_CLK_SEL_NONE;
287379bc100SJani Nikula 		}
288379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL1:
289379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL2:
290379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL3:
291379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL4:
2926677c3b1SJosé Roberto de Souza 	case DPLL_ID_TGL_MGPLL5:
2936677c3b1SJosé Roberto de Souza 	case DPLL_ID_TGL_MGPLL6:
294379bc100SJani Nikula 		return DDI_CLK_SEL_MG;
295379bc100SJani Nikula 	}
296379bc100SJani Nikula }
297379bc100SJani Nikula 
298414002f1SImre Deak static u32 ddi_buf_phy_link_rate(int port_clock)
299414002f1SImre Deak {
300414002f1SImre Deak 	switch (port_clock) {
301414002f1SImre Deak 	case 162000:
302414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(0);
303414002f1SImre Deak 	case 216000:
304414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(4);
305414002f1SImre Deak 	case 243000:
306414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(5);
307414002f1SImre Deak 	case 270000:
308414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(1);
309414002f1SImre Deak 	case 324000:
310414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(6);
311414002f1SImre Deak 	case 432000:
312414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(7);
313414002f1SImre Deak 	case 540000:
314414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(2);
315414002f1SImre Deak 	case 810000:
316414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(3);
317414002f1SImre Deak 	default:
318414002f1SImre Deak 		MISSING_CASE(port_clock);
319414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(0);
320414002f1SImre Deak 	}
321414002f1SImre Deak }
322414002f1SImre Deak 
323a621860aSVille Syrjälä static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
324a621860aSVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
325379bc100SJani Nikula {
32655ce306cSJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
327b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3287801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
32955ce306cSJosé Roberto de Souza 	enum phy phy = intel_port_to_phy(i915, encoder->port);
330379bc100SJani Nikula 
3319f620f1dSVille Syrjälä 	/* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */
3327801f3b7SLucas De Marchi 	intel_dp->DP = dig_port->saved_port_bits |
3339f620f1dSVille Syrjälä 		DDI_PORT_WIDTH(crtc_state->lane_count) |
3349f620f1dSVille Syrjälä 		DDI_BUF_TRANS_SELECT(0);
33555ce306cSJosé Roberto de Souza 
33623ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(i915) >= 14) {
33723ef6194SJosé Roberto de Souza 		if (intel_dp_is_uhbr(crtc_state))
33823ef6194SJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_PORT_DATA_40BIT;
33923ef6194SJosé Roberto de Souza 		else
34023ef6194SJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_PORT_DATA_10BIT;
34123ef6194SJosé Roberto de Souza 	}
34223ef6194SJosé Roberto de Souza 
343414002f1SImre Deak 	if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) {
344414002f1SImre Deak 		intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock);
34511a89708SImre Deak 		if (!intel_tc_port_in_tbt_alt_mode(dig_port))
34655ce306cSJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
347379bc100SJani Nikula 	}
348414002f1SImre Deak }
349379bc100SJani Nikula 
350379bc100SJani Nikula static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
351379bc100SJani Nikula 				 enum port port)
352379bc100SJani Nikula {
353f7960e7fSJani Nikula 	u32 val = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK;
354379bc100SJani Nikula 
355379bc100SJani Nikula 	switch (val) {
356379bc100SJani Nikula 	case DDI_CLK_SEL_NONE:
357379bc100SJani Nikula 		return 0;
358379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_162:
359379bc100SJani Nikula 		return 162000;
360379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_270:
361379bc100SJani Nikula 		return 270000;
362379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_540:
363379bc100SJani Nikula 		return 540000;
364379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_810:
365379bc100SJani Nikula 		return 810000;
366379bc100SJani Nikula 	default:
367379bc100SJani Nikula 		MISSING_CASE(val);
368379bc100SJani Nikula 		return 0;
369379bc100SJani Nikula 	}
370379bc100SJani Nikula }
371379bc100SJani Nikula 
372623411c2SVille Syrjälä static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
373623411c2SVille Syrjälä {
374623411c2SVille Syrjälä 	/* CRT dotclock is determined via other means */
375623411c2SVille Syrjälä 	if (pipe_config->has_pch_encoder)
376623411c2SVille Syrjälä 		return;
377623411c2SVille Syrjälä 
378623411c2SVille Syrjälä 	pipe_config->hw.adjusted_mode.crtc_clock =
379623411c2SVille Syrjälä 		intel_crtc_dotclock(pipe_config);
380379bc100SJani Nikula }
381379bc100SJani Nikula 
3820c06fa15SGwan-gyeong Mun void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
3830c06fa15SGwan-gyeong Mun 			  const struct drm_connector_state *conn_state)
384379bc100SJani Nikula {
3852225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
386379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
387379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
388379bc100SJani Nikula 	u32 temp;
389379bc100SJani Nikula 
390379bc100SJani Nikula 	if (!intel_crtc_has_dp_encoder(crtc_state))
391379bc100SJani Nikula 		return;
392379bc100SJani Nikula 
3931de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder));
394379bc100SJani Nikula 
3953e706dffSVille Syrjälä 	temp = DP_MSA_MISC_SYNC_CLOCK;
396379bc100SJani Nikula 
397379bc100SJani Nikula 	switch (crtc_state->pipe_bpp) {
398379bc100SJani Nikula 	case 18:
3993e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_6_BPC;
400379bc100SJani Nikula 		break;
401379bc100SJani Nikula 	case 24:
4023e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_8_BPC;
403379bc100SJani Nikula 		break;
404379bc100SJani Nikula 	case 30:
4053e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_10_BPC;
406379bc100SJani Nikula 		break;
407379bc100SJani Nikula 	case 36:
4083e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_12_BPC;
409379bc100SJani Nikula 		break;
410379bc100SJani Nikula 	default:
411379bc100SJani Nikula 		MISSING_CASE(crtc_state->pipe_bpp);
412379bc100SJani Nikula 		break;
413379bc100SJani Nikula 	}
414379bc100SJani Nikula 
415cae154fcSVille Syrjälä 	/* nonsense combination */
4161de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, crtc_state->limited_color_range &&
417cae154fcSVille Syrjälä 		    crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
418cae154fcSVille Syrjälä 
419cae154fcSVille Syrjälä 	if (crtc_state->limited_color_range)
4203e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_CEA_RGB;
421cae154fcSVille Syrjälä 
422379bc100SJani Nikula 	/*
423379bc100SJani Nikula 	 * As per DP 1.2 spec section 2.3.4.3 while sending
424379bc100SJani Nikula 	 * YCBCR 444 signals we should program MSA MISC1/0 fields with
425646d3dc8SVille Syrjälä 	 * colorspace information.
426379bc100SJani Nikula 	 */
427379bc100SJani Nikula 	if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
4283e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
429646d3dc8SVille Syrjälä 
430379bc100SJani Nikula 	/*
431379bc100SJani Nikula 	 * As per DP 1.4a spec section 2.2.4.3 [MSA Field for Indication
432379bc100SJani Nikula 	 * of Color Encoding Format and Content Color Gamut] while sending
4330c06fa15SGwan-gyeong Mun 	 * YCBCR 420, HDR BT.2020 signals we should program MSA MISC1 fields
4340c06fa15SGwan-gyeong Mun 	 * which indicate VSC SDP for the Pixel Encoding/Colorimetry Format.
435379bc100SJani Nikula 	 */
436bd8c9ccaSGwan-gyeong Mun 	if (intel_dp_needs_vsc_sdp(crtc_state, conn_state))
4373e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_VSC_SDP;
4380c06fa15SGwan-gyeong Mun 
439f7960e7fSJani Nikula 	intel_de_write(dev_priv, TRANS_MSA_MISC(cpu_transcoder), temp);
440379bc100SJani Nikula }
441379bc100SJani Nikula 
442dc5b8ed5SVille Syrjälä static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder)
443dc5b8ed5SVille Syrjälä {
444dc5b8ed5SVille Syrjälä 	if (master_transcoder == TRANSCODER_EDP)
445dc5b8ed5SVille Syrjälä 		return 0;
446dc5b8ed5SVille Syrjälä 	else
447dc5b8ed5SVille Syrjälä 		return master_transcoder + 1;
448dc5b8ed5SVille Syrjälä }
449dc5b8ed5SVille Syrjälä 
45079ac2b1bSJani Nikula static void
45179ac2b1bSJani Nikula intel_ddi_config_transcoder_dp2(struct intel_encoder *encoder,
45279ac2b1bSJani Nikula 				const struct intel_crtc_state *crtc_state)
45379ac2b1bSJani Nikula {
45479ac2b1bSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
45579ac2b1bSJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
45679ac2b1bSJani Nikula 	u32 val = 0;
45779ac2b1bSJani Nikula 
45879ac2b1bSJani Nikula 	if (intel_dp_is_uhbr(crtc_state))
45979ac2b1bSJani Nikula 		val = TRANS_DP2_128B132B_CHANNEL_CODING;
46079ac2b1bSJani Nikula 
46179ac2b1bSJani Nikula 	intel_de_write(i915, TRANS_DP2_CTL(cpu_transcoder), val);
46279ac2b1bSJani Nikula }
46379ac2b1bSJani Nikula 
46499389390SJosé Roberto de Souza /*
46599389390SJosé Roberto de Souza  * Returns the TRANS_DDI_FUNC_CTL value based on CRTC state.
46699389390SJosé Roberto de Souza  *
46799389390SJosé Roberto de Souza  * Only intended to be used by intel_ddi_enable_transcoder_func() and
46899389390SJosé Roberto de Souza  * intel_ddi_config_transcoder_func().
46999389390SJosé Roberto de Souza  */
47099389390SJosé Roberto de Souza static u32
471eed22a46SVille Syrjälä intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
472eed22a46SVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
473379bc100SJani Nikula {
4742225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
475379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
476379bc100SJani Nikula 	enum pipe pipe = crtc->pipe;
477379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
478379bc100SJani Nikula 	enum port port = encoder->port;
479379bc100SJani Nikula 	u32 temp;
480379bc100SJani Nikula 
481379bc100SJani Nikula 	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
482379bc100SJani Nikula 	temp = TRANS_DDI_FUNC_ENABLE;
483005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
484df16b636SMahesh Kumar 		temp |= TGL_TRANS_DDI_SELECT_PORT(port);
485df16b636SMahesh Kumar 	else
486379bc100SJani Nikula 		temp |= TRANS_DDI_SELECT_PORT(port);
487379bc100SJani Nikula 
488379bc100SJani Nikula 	switch (crtc_state->pipe_bpp) {
48904514c14SJani Nikula 	default:
49004514c14SJani Nikula 		MISSING_CASE(crtc_state->pipe_bpp);
49104514c14SJani Nikula 		fallthrough;
492379bc100SJani Nikula 	case 18:
493379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_6;
494379bc100SJani Nikula 		break;
495379bc100SJani Nikula 	case 24:
496379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_8;
497379bc100SJani Nikula 		break;
498379bc100SJani Nikula 	case 30:
499379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_10;
500379bc100SJani Nikula 		break;
501379bc100SJani Nikula 	case 36:
502379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_12;
503379bc100SJani Nikula 		break;
504379bc100SJani Nikula 	}
505379bc100SJani Nikula 
5061326a92cSMaarten Lankhorst 	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
507379bc100SJani Nikula 		temp |= TRANS_DDI_PVSYNC;
5081326a92cSMaarten Lankhorst 	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
509379bc100SJani Nikula 		temp |= TRANS_DDI_PHSYNC;
510379bc100SJani Nikula 
511379bc100SJani Nikula 	if (cpu_transcoder == TRANSCODER_EDP) {
512379bc100SJani Nikula 		switch (pipe) {
51304514c14SJani Nikula 		default:
51404514c14SJani Nikula 			MISSING_CASE(pipe);
51504514c14SJani Nikula 			fallthrough;
516379bc100SJani Nikula 		case PIPE_A:
517379bc100SJani Nikula 			/* On Haswell, can only use the always-on power well for
518379bc100SJani Nikula 			 * eDP when not using the panel fitter, and when not
519379bc100SJani Nikula 			 * using motion blur mitigation (which we don't
520379bc100SJani Nikula 			 * support). */
521379bc100SJani Nikula 			if (crtc_state->pch_pfit.force_thru)
522379bc100SJani Nikula 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
523379bc100SJani Nikula 			else
524379bc100SJani Nikula 				temp |= TRANS_DDI_EDP_INPUT_A_ON;
525379bc100SJani Nikula 			break;
526379bc100SJani Nikula 		case PIPE_B:
527379bc100SJani Nikula 			temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
528379bc100SJani Nikula 			break;
529379bc100SJani Nikula 		case PIPE_C:
530379bc100SJani Nikula 			temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
531379bc100SJani Nikula 			break;
532379bc100SJani Nikula 		}
533379bc100SJani Nikula 	}
534379bc100SJani Nikula 
535379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
536379bc100SJani Nikula 		if (crtc_state->has_hdmi_sink)
537379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_HDMI;
538379bc100SJani Nikula 		else
539379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_DVI;
540379bc100SJani Nikula 
541379bc100SJani Nikula 		if (crtc_state->hdmi_scrambling)
542379bc100SJani Nikula 			temp |= TRANS_DDI_HDMI_SCRAMBLING;
543379bc100SJani Nikula 		if (crtc_state->hdmi_high_tmds_clock_ratio)
544379bc100SJani Nikula 			temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
545b66a8abaSAnkit Nautiyal 		if (DISPLAY_VER(dev_priv) >= 14)
546b66a8abaSAnkit Nautiyal 			temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
547379bc100SJani Nikula 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
5487bb97db8SJani Nikula 		temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
549379bc100SJani Nikula 		temp |= (crtc_state->fdi_lanes - 1) << 1;
550379bc100SJani Nikula 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
55165213594SJani Nikula 		if (intel_dp_is_uhbr(crtc_state))
55265213594SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
55365213594SJani Nikula 		else
554379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
555379bc100SJani Nikula 		temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
556b3545e08SLucas De Marchi 
557005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
5586671c367SJosé Roberto de Souza 			enum transcoder master;
5596671c367SJosé Roberto de Souza 
5606671c367SJosé Roberto de Souza 			master = crtc_state->mst_master_transcoder;
5611de143ccSPankaj Bharadiya 			drm_WARN_ON(&dev_priv->drm,
5621de143ccSPankaj Bharadiya 				    master == INVALID_TRANSCODER);
5636671c367SJosé Roberto de Souza 			temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master);
5646671c367SJosé Roberto de Souza 		}
565379bc100SJani Nikula 	} else {
566379bc100SJani Nikula 		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
567379bc100SJani Nikula 		temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
568379bc100SJani Nikula 	}
569379bc100SJani Nikula 
57093e7e61eSLucas De Marchi 	if (IS_DISPLAY_VER(dev_priv, 8, 10) &&
571dc5b8ed5SVille Syrjälä 	    crtc_state->master_transcoder != INVALID_TRANSCODER) {
572dc5b8ed5SVille Syrjälä 		u8 master_select =
573dc5b8ed5SVille Syrjälä 			bdw_trans_port_sync_master_select(crtc_state->master_transcoder);
574dc5b8ed5SVille Syrjälä 
575dc5b8ed5SVille Syrjälä 		temp |= TRANS_DDI_PORT_SYNC_ENABLE |
576dc5b8ed5SVille Syrjälä 			TRANS_DDI_PORT_SYNC_MASTER_SELECT(master_select);
577dc5b8ed5SVille Syrjälä 	}
578dc5b8ed5SVille Syrjälä 
57999389390SJosé Roberto de Souza 	return temp;
58099389390SJosé Roberto de Souza }
58199389390SJosé Roberto de Souza 
582eed22a46SVille Syrjälä void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
583eed22a46SVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
58499389390SJosé Roberto de Souza {
5852225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
58699389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
58799389390SJosé Roberto de Souza 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
58899389390SJosé Roberto de Souza 
589005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
590589a4cd6SVille Syrjälä 		enum transcoder master_transcoder = crtc_state->master_transcoder;
591589a4cd6SVille Syrjälä 		u32 ctl2 = 0;
592589a4cd6SVille Syrjälä 
593589a4cd6SVille Syrjälä 		if (master_transcoder != INVALID_TRANSCODER) {
594dc5b8ed5SVille Syrjälä 			u8 master_select =
595dc5b8ed5SVille Syrjälä 				bdw_trans_port_sync_master_select(master_transcoder);
596589a4cd6SVille Syrjälä 
597589a4cd6SVille Syrjälä 			ctl2 |= PORT_SYNC_MODE_ENABLE |
598d4d7d9caSVille Syrjälä 				PORT_SYNC_MODE_MASTER_SELECT(master_select);
599589a4cd6SVille Syrjälä 		}
600589a4cd6SVille Syrjälä 
601589a4cd6SVille Syrjälä 		intel_de_write(dev_priv,
602589a4cd6SVille Syrjälä 			       TRANS_DDI_FUNC_CTL2(cpu_transcoder), ctl2);
603589a4cd6SVille Syrjälä 	}
604589a4cd6SVille Syrjälä 
605580fbdc5SImre Deak 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
606580fbdc5SImre Deak 		       intel_ddi_transcoder_func_reg_val_get(encoder,
607580fbdc5SImre Deak 							     crtc_state));
60899389390SJosé Roberto de Souza }
60999389390SJosé Roberto de Souza 
61099389390SJosé Roberto de Souza /*
61199389390SJosé Roberto de Souza  * Same as intel_ddi_enable_transcoder_func(), but it does not set the enable
61299389390SJosé Roberto de Souza  * bit.
61399389390SJosé Roberto de Souza  */
61499389390SJosé Roberto de Souza static void
615eed22a46SVille Syrjälä intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
616eed22a46SVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
61799389390SJosé Roberto de Souza {
6182225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
61999389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
62099389390SJosé Roberto de Souza 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
621589a4cd6SVille Syrjälä 	u32 ctl;
62299389390SJosé Roberto de Souza 
623eed22a46SVille Syrjälä 	ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state);
624589a4cd6SVille Syrjälä 	ctl &= ~TRANS_DDI_FUNC_ENABLE;
625589a4cd6SVille Syrjälä 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl);
626379bc100SJani Nikula }
627379bc100SJani Nikula 
628379bc100SJani Nikula void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
629379bc100SJani Nikula {
6302225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
631379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
632379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
633589a4cd6SVille Syrjälä 	u32 ctl;
634c59053dcSJosé Roberto de Souza 
635005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
636589a4cd6SVille Syrjälä 		intel_de_write(dev_priv,
637589a4cd6SVille Syrjälä 			       TRANS_DDI_FUNC_CTL2(cpu_transcoder), 0);
638589a4cd6SVille Syrjälä 
639589a4cd6SVille Syrjälä 	ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
640dc5b8ed5SVille Syrjälä 
6411cfcdbf3SSean Paul 	drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING);
6421cfcdbf3SSean Paul 
643589a4cd6SVille Syrjälä 	ctl &= ~TRANS_DDI_FUNC_ENABLE;
644379bc100SJani Nikula 
64593e7e61eSLucas De Marchi 	if (IS_DISPLAY_VER(dev_priv, 8, 10))
646dc5b8ed5SVille Syrjälä 		ctl &= ~(TRANS_DDI_PORT_SYNC_ENABLE |
647dc5b8ed5SVille Syrjälä 			 TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK);
648dc5b8ed5SVille Syrjälä 
649005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
650919e4f07SJosé Roberto de Souza 		if (!intel_dp_mst_is_master_trans(crtc_state)) {
651589a4cd6SVille Syrjälä 			ctl &= ~(TGL_TRANS_DDI_PORT_MASK |
652919e4f07SJosé Roberto de Souza 				 TRANS_DDI_MODE_SELECT_MASK);
653919e4f07SJosé Roberto de Souza 		}
654df16b636SMahesh Kumar 	} else {
655589a4cd6SVille Syrjälä 		ctl &= ~(TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK);
656df16b636SMahesh Kumar 	}
657dc5b8ed5SVille Syrjälä 
658589a4cd6SVille Syrjälä 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl);
659379bc100SJani Nikula 
6600c82118bSJani Nikula 	if (intel_has_quirk(dev_priv, QUIRK_INCREASE_DDI_DISABLED_TIME) &&
661379bc100SJani Nikula 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
66247bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
66347bdb1caSJani Nikula 			    "Quirk Increase DDI disabled time\n");
664379bc100SJani Nikula 		/* Quirk time at 100ms for reliable operation */
665379bc100SJani Nikula 		msleep(100);
666379bc100SJani Nikula 	}
667379bc100SJani Nikula }
668379bc100SJani Nikula 
6691a67a168SAnshuman Gupta int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
6700b9c9290SSean Paul 			       enum transcoder cpu_transcoder,
6711a67a168SAnshuman Gupta 			       bool enable, u32 hdcp_mask)
672379bc100SJani Nikula {
673379bc100SJani Nikula 	struct drm_device *dev = intel_encoder->base.dev;
674379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
675379bc100SJani Nikula 	intel_wakeref_t wakeref;
676379bc100SJani Nikula 	int ret = 0;
677379bc100SJani Nikula 
678379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
679379bc100SJani Nikula 						     intel_encoder->power_domain);
6801de143ccSPankaj Bharadiya 	if (drm_WARN_ON(dev, !wakeref))
681379bc100SJani Nikula 		return -ENXIO;
682379bc100SJani Nikula 
6838910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
6848910d8b7SAndrzej Hajda 		     hdcp_mask, enable ? hdcp_mask : 0);
685379bc100SJani Nikula 	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
686379bc100SJani Nikula 	return ret;
687379bc100SJani Nikula }
688379bc100SJani Nikula 
689379bc100SJani Nikula bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
690379bc100SJani Nikula {
691379bc100SJani Nikula 	struct drm_device *dev = intel_connector->base.dev;
692379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
693fa7edcd2SVille Syrjälä 	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
694379bc100SJani Nikula 	int type = intel_connector->base.connector_type;
695379bc100SJani Nikula 	enum port port = encoder->port;
696379bc100SJani Nikula 	enum transcoder cpu_transcoder;
697379bc100SJani Nikula 	intel_wakeref_t wakeref;
698379bc100SJani Nikula 	enum pipe pipe = 0;
699379bc100SJani Nikula 	u32 tmp;
700379bc100SJani Nikula 	bool ret;
701379bc100SJani Nikula 
702379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
703379bc100SJani Nikula 						     encoder->power_domain);
704379bc100SJani Nikula 	if (!wakeref)
705379bc100SJani Nikula 		return false;
706379bc100SJani Nikula 
707379bc100SJani Nikula 	if (!encoder->get_hw_state(encoder, &pipe)) {
708379bc100SJani Nikula 		ret = false;
709379bc100SJani Nikula 		goto out;
710379bc100SJani Nikula 	}
711379bc100SJani Nikula 
71210cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
713379bc100SJani Nikula 		cpu_transcoder = TRANSCODER_EDP;
714379bc100SJani Nikula 	else
715379bc100SJani Nikula 		cpu_transcoder = (enum transcoder) pipe;
716379bc100SJani Nikula 
717f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
718379bc100SJani Nikula 
719379bc100SJani Nikula 	switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
720379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_HDMI:
721379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DVI:
722379bc100SJani Nikula 		ret = type == DRM_MODE_CONNECTOR_HDMIA;
723379bc100SJani Nikula 		break;
724379bc100SJani Nikula 
725379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_SST:
726379bc100SJani Nikula 		ret = type == DRM_MODE_CONNECTOR_eDP ||
727379bc100SJani Nikula 		      type == DRM_MODE_CONNECTOR_DisplayPort;
728379bc100SJani Nikula 		break;
729379bc100SJani Nikula 
730379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_MST:
731379bc100SJani Nikula 		/* if the transcoder is in MST state then
732379bc100SJani Nikula 		 * connector isn't connected */
733379bc100SJani Nikula 		ret = false;
734379bc100SJani Nikula 		break;
735379bc100SJani Nikula 
7367bb97db8SJani Nikula 	case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
73765213594SJani Nikula 		if (HAS_DP20(dev_priv))
73865213594SJani Nikula 			/* 128b/132b */
73965213594SJani Nikula 			ret = false;
74065213594SJani Nikula 		else
74165213594SJani Nikula 			/* FDI */
742379bc100SJani Nikula 			ret = type == DRM_MODE_CONNECTOR_VGA;
743379bc100SJani Nikula 		break;
744379bc100SJani Nikula 
745379bc100SJani Nikula 	default:
746379bc100SJani Nikula 		ret = false;
747379bc100SJani Nikula 		break;
748379bc100SJani Nikula 	}
749379bc100SJani Nikula 
750379bc100SJani Nikula out:
751379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
752379bc100SJani Nikula 
753379bc100SJani Nikula 	return ret;
754379bc100SJani Nikula }
755379bc100SJani Nikula 
756379bc100SJani Nikula static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
757379bc100SJani Nikula 					u8 *pipe_mask, bool *is_dp_mst)
758379bc100SJani Nikula {
759379bc100SJani Nikula 	struct drm_device *dev = encoder->base.dev;
760379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
761379bc100SJani Nikula 	enum port port = encoder->port;
762379bc100SJani Nikula 	intel_wakeref_t wakeref;
763379bc100SJani Nikula 	enum pipe p;
764379bc100SJani Nikula 	u32 tmp;
765379bc100SJani Nikula 	u8 mst_pipe_mask;
766379bc100SJani Nikula 
767379bc100SJani Nikula 	*pipe_mask = 0;
768379bc100SJani Nikula 	*is_dp_mst = false;
769379bc100SJani Nikula 
770379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
771379bc100SJani Nikula 						     encoder->power_domain);
772379bc100SJani Nikula 	if (!wakeref)
773379bc100SJani Nikula 		return;
774379bc100SJani Nikula 
775f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, DDI_BUF_CTL(port));
776379bc100SJani Nikula 	if (!(tmp & DDI_BUF_CTL_ENABLE))
777379bc100SJani Nikula 		goto out;
778379bc100SJani Nikula 
77910cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A) {
780f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv,
781f7960e7fSJani Nikula 				    TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
782379bc100SJani Nikula 
783379bc100SJani Nikula 		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
784379bc100SJani Nikula 		default:
785379bc100SJani Nikula 			MISSING_CASE(tmp & TRANS_DDI_EDP_INPUT_MASK);
786df561f66SGustavo A. R. Silva 			fallthrough;
787379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ON:
788379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ONOFF:
789379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_A);
790379bc100SJani Nikula 			break;
791379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_B_ONOFF:
792379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_B);
793379bc100SJani Nikula 			break;
794379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_C_ONOFF:
795379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_C);
796379bc100SJani Nikula 			break;
797379bc100SJani Nikula 		}
798379bc100SJani Nikula 
799379bc100SJani Nikula 		goto out;
800379bc100SJani Nikula 	}
801379bc100SJani Nikula 
802379bc100SJani Nikula 	mst_pipe_mask = 0;
803379bc100SJani Nikula 	for_each_pipe(dev_priv, p) {
804379bc100SJani Nikula 		enum transcoder cpu_transcoder = (enum transcoder)p;
805df16b636SMahesh Kumar 		unsigned int port_mask, ddi_select;
8066aa3bef1SJosé Roberto de Souza 		intel_wakeref_t trans_wakeref;
8076aa3bef1SJosé Roberto de Souza 
8086aa3bef1SJosé Roberto de Souza 		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
8096aa3bef1SJosé Roberto de Souza 								   POWER_DOMAIN_TRANSCODER(cpu_transcoder));
8106aa3bef1SJosé Roberto de Souza 		if (!trans_wakeref)
8116aa3bef1SJosé Roberto de Souza 			continue;
812df16b636SMahesh Kumar 
813005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
814df16b636SMahesh Kumar 			port_mask = TGL_TRANS_DDI_PORT_MASK;
815df16b636SMahesh Kumar 			ddi_select = TGL_TRANS_DDI_SELECT_PORT(port);
816df16b636SMahesh Kumar 		} else {
817df16b636SMahesh Kumar 			port_mask = TRANS_DDI_PORT_MASK;
818df16b636SMahesh Kumar 			ddi_select = TRANS_DDI_SELECT_PORT(port);
819df16b636SMahesh Kumar 		}
820379bc100SJani Nikula 
821f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv,
822f7960e7fSJani Nikula 				    TRANS_DDI_FUNC_CTL(cpu_transcoder));
8236aa3bef1SJosé Roberto de Souza 		intel_display_power_put(dev_priv, POWER_DOMAIN_TRANSCODER(cpu_transcoder),
8246aa3bef1SJosé Roberto de Souza 					trans_wakeref);
825379bc100SJani Nikula 
826df16b636SMahesh Kumar 		if ((tmp & port_mask) != ddi_select)
827379bc100SJani Nikula 			continue;
828379bc100SJani Nikula 
82965213594SJani Nikula 		if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST ||
83065213594SJani Nikula 		    (HAS_DP20(dev_priv) &&
83165213594SJani Nikula 		     (tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B))
832379bc100SJani Nikula 			mst_pipe_mask |= BIT(p);
833379bc100SJani Nikula 
834379bc100SJani Nikula 		*pipe_mask |= BIT(p);
835379bc100SJani Nikula 	}
836379bc100SJani Nikula 
837379bc100SJani Nikula 	if (!*pipe_mask)
83847bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
83947bdb1caSJani Nikula 			    "No pipe for [ENCODER:%d:%s] found\n",
84066a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name);
841379bc100SJani Nikula 
842379bc100SJani Nikula 	if (!mst_pipe_mask && hweight8(*pipe_mask) > 1) {
84347bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
84447bdb1caSJani Nikula 			    "Multiple pipes for [ENCODER:%d:%s] (pipe_mask %02x)\n",
84566a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name,
84666a990ddSVille Syrjälä 			    *pipe_mask);
847379bc100SJani Nikula 		*pipe_mask = BIT(ffs(*pipe_mask) - 1);
848379bc100SJani Nikula 	}
849379bc100SJani Nikula 
850379bc100SJani Nikula 	if (mst_pipe_mask && mst_pipe_mask != *pipe_mask)
85147bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
85247bdb1caSJani Nikula 			    "Conflicting MST and non-MST state for [ENCODER:%d:%s] (pipe_mask %02x mst_pipe_mask %02x)\n",
85366a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name,
85466a990ddSVille Syrjälä 			    *pipe_mask, mst_pipe_mask);
855379bc100SJani Nikula 	else
856379bc100SJani Nikula 		*is_dp_mst = mst_pipe_mask;
857379bc100SJani Nikula 
858379bc100SJani Nikula out:
8592446e1d6SMatt Roper 	if (*pipe_mask && (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))) {
860f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv, BXT_PHY_CTL(port));
861379bc100SJani Nikula 		if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
862379bc100SJani Nikula 			    BXT_PHY_LANE_POWERDOWN_ACK |
863379bc100SJani Nikula 			    BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED)
86447bdb1caSJani Nikula 			drm_err(&dev_priv->drm,
86547bdb1caSJani Nikula 				"[ENCODER:%d:%s] enabled but PHY powered down? (PHY_CTL %08x)\n",
86647bdb1caSJani Nikula 				encoder->base.base.id, encoder->base.name, tmp);
867379bc100SJani Nikula 	}
868379bc100SJani Nikula 
869379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
870379bc100SJani Nikula }
871379bc100SJani Nikula 
872379bc100SJani Nikula bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
873379bc100SJani Nikula 			    enum pipe *pipe)
874379bc100SJani Nikula {
875379bc100SJani Nikula 	u8 pipe_mask;
876379bc100SJani Nikula 	bool is_mst;
877379bc100SJani Nikula 
878379bc100SJani Nikula 	intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
879379bc100SJani Nikula 
880379bc100SJani Nikula 	if (is_mst || !pipe_mask)
881379bc100SJani Nikula 		return false;
882379bc100SJani Nikula 
883379bc100SJani Nikula 	*pipe = ffs(pipe_mask) - 1;
884379bc100SJani Nikula 
885379bc100SJani Nikula 	return true;
886379bc100SJani Nikula }
887379bc100SJani Nikula 
88881b55ef1SJani Nikula static enum intel_display_power_domain
889637c7aa2SImre Deak intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port,
890637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
891379bc100SJani Nikula {
892f645cbdaSImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
893637c7aa2SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
894f645cbdaSImre Deak 
895637c7aa2SImre Deak 	/*
896637c7aa2SImre Deak 	 * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
897379bc100SJani Nikula 	 * DC states enabled at the same time, while for driver initiated AUX
898379bc100SJani Nikula 	 * transfers we need the same AUX IOs to be powered but with DC states
899637c7aa2SImre Deak 	 * disabled. Accordingly use the AUX_IO_<port> power domain here which
900637c7aa2SImre Deak 	 * leaves DC states enabled.
901637c7aa2SImre Deak 	 *
902637c7aa2SImre Deak 	 * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require
903637c7aa2SImre Deak 	 * AUX IO to be enabled, but all these require DC_OFF to be enabled as
904637c7aa2SImre Deak 	 * well, so we can acquire a wider AUX_<port> power domain reference
905637c7aa2SImre Deak 	 * instead of a specific AUX_IO_<port> reference without powering up any
906637c7aa2SImre Deak 	 * extra wells.
907379bc100SJani Nikula 	 */
908f645cbdaSImre Deak 	if (intel_encoder_can_psr(&dig_port->base))
909f645cbdaSImre Deak 		return intel_display_power_aux_io_domain(i915, dig_port->aux_ch);
9101acefacaSImre Deak 	else if (DISPLAY_VER(i915) < 14 &&
9111acefacaSImre Deak 		 (intel_crtc_has_dp_encoder(crtc_state) ||
9121acefacaSImre Deak 		  intel_phy_is_tc(i915, phy)))
913b2e00dd3SImre Deak 		return intel_aux_power_domain(dig_port);
914637c7aa2SImre Deak 	else
915637c7aa2SImre Deak 		return POWER_DOMAIN_INVALID;
916637c7aa2SImre Deak }
917637c7aa2SImre Deak 
918637c7aa2SImre Deak static void
919637c7aa2SImre Deak main_link_aux_power_domain_get(struct intel_digital_port *dig_port,
920637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
921637c7aa2SImre Deak {
922637c7aa2SImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
923637c7aa2SImre Deak 	enum intel_display_power_domain domain =
924637c7aa2SImre Deak 		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
925637c7aa2SImre Deak 
926637c7aa2SImre Deak 	drm_WARN_ON(&i915->drm, dig_port->aux_wakeref);
927637c7aa2SImre Deak 
928637c7aa2SImre Deak 	if (domain == POWER_DOMAIN_INVALID)
929637c7aa2SImre Deak 		return;
930637c7aa2SImre Deak 
931637c7aa2SImre Deak 	dig_port->aux_wakeref = intel_display_power_get(i915, domain);
932637c7aa2SImre Deak }
933637c7aa2SImre Deak 
934637c7aa2SImre Deak static void
935637c7aa2SImre Deak main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
936637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
937637c7aa2SImre Deak {
938637c7aa2SImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
939637c7aa2SImre Deak 	enum intel_display_power_domain domain =
940637c7aa2SImre Deak 		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
941637c7aa2SImre Deak 	intel_wakeref_t wf;
942637c7aa2SImre Deak 
943637c7aa2SImre Deak 	wf = fetch_and_zero(&dig_port->aux_wakeref);
944637c7aa2SImre Deak 	if (!wf)
945637c7aa2SImre Deak 		return;
946637c7aa2SImre Deak 
947637c7aa2SImre Deak 	intel_display_power_put(i915, domain, wf);
948379bc100SJani Nikula }
949379bc100SJani Nikula 
950379bc100SJani Nikula static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
951379bc100SJani Nikula 					struct intel_crtc_state *crtc_state)
952379bc100SJani Nikula {
953379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
954379bc100SJani Nikula 	struct intel_digital_port *dig_port;
955379bc100SJani Nikula 
956379bc100SJani Nikula 	/*
957379bc100SJani Nikula 	 * TODO: Add support for MST encoders. Atm, the following should never
958379bc100SJani Nikula 	 * happen since fake-MST encoders don't set their get_power_domains()
959379bc100SJani Nikula 	 * hook.
960379bc100SJani Nikula 	 */
9611de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
9621de143ccSPankaj Bharadiya 			intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
963379bc100SJani Nikula 		return;
964379bc100SJani Nikula 
965b7d02c3aSVille Syrjälä 	dig_port = enc_to_dig_port(encoder);
966f77a2db2SImre Deak 
96711a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
968a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
969a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
970f77a2db2SImre Deak 								   dig_port->ddi_io_power_domain);
971a4550977SImre Deak 	}
972379bc100SJani Nikula 
973637c7aa2SImre Deak 	main_link_aux_power_domain_get(dig_port, crtc_state);
974162e68e1SImre Deak }
975379bc100SJani Nikula 
97655a4679eSVille Syrjälä void intel_ddi_enable_transcoder_clock(struct intel_encoder *encoder,
97702a715c3SVille Syrjälä 				       const struct intel_crtc_state *crtc_state)
978379bc100SJani Nikula {
9792225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
980379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
981379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
982ed2615a8SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
983ed2615a8SMatt Roper 	u32 val;
984379bc100SJani Nikula 
98548630a31SVille Syrjälä 	if (cpu_transcoder == TRANSCODER_EDP)
98648630a31SVille Syrjälä 		return;
98748630a31SVille Syrjälä 
988ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
989ed2615a8SMatt Roper 		val = TGL_TRANS_CLK_SEL_PORT(phy);
990ed2615a8SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
991ed2615a8SMatt Roper 		val = TGL_TRANS_CLK_SEL_PORT(encoder->port);
992df16b636SMahesh Kumar 	else
993ed2615a8SMatt Roper 		val = TRANS_CLK_SEL_PORT(encoder->port);
994ed2615a8SMatt Roper 
995ed2615a8SMatt Roper 	intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
996379bc100SJani Nikula }
997379bc100SJani Nikula 
99855a4679eSVille Syrjälä void intel_ddi_disable_transcoder_clock(const struct intel_crtc_state *crtc_state)
999379bc100SJani Nikula {
10002225f3c6SMaarten Lankhorst 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1001379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
100248630a31SVille Syrjälä 	u32 val;
1003379bc100SJani Nikula 
100448630a31SVille Syrjälä 	if (cpu_transcoder == TRANSCODER_EDP)
100548630a31SVille Syrjälä 		return;
100648630a31SVille Syrjälä 
1007005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
100848630a31SVille Syrjälä 		val = TGL_TRANS_CLK_SEL_DISABLED;
1009df16b636SMahesh Kumar 	else
101048630a31SVille Syrjälä 		val = TRANS_CLK_SEL_DISABLED;
101148630a31SVille Syrjälä 
101248630a31SVille Syrjälä 	intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
1013df16b636SMahesh Kumar }
1014379bc100SJani Nikula 
1015379bc100SJani Nikula static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
1016379bc100SJani Nikula 				enum port port, u8 iboost)
1017379bc100SJani Nikula {
1018379bc100SJani Nikula 	u32 tmp;
1019379bc100SJani Nikula 
1020f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, DISPIO_CR_TX_BMU_CR0);
1021379bc100SJani Nikula 	tmp &= ~(BALANCE_LEG_MASK(port) | BALANCE_LEG_DISABLE(port));
1022379bc100SJani Nikula 	if (iboost)
1023379bc100SJani Nikula 		tmp |= iboost << BALANCE_LEG_SHIFT(port);
1024379bc100SJani Nikula 	else
1025379bc100SJani Nikula 		tmp |= BALANCE_LEG_DISABLE(port);
1026f7960e7fSJani Nikula 	intel_de_write(dev_priv, DISPIO_CR_TX_BMU_CR0, tmp);
1027379bc100SJani Nikula }
1028379bc100SJani Nikula 
1029379bc100SJani Nikula static void skl_ddi_set_iboost(struct intel_encoder *encoder,
1030a621860aSVille Syrjälä 			       const struct intel_crtc_state *crtc_state,
1031a621860aSVille Syrjälä 			       int level)
1032379bc100SJani Nikula {
10337801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1034379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1035379bc100SJani Nikula 	u8 iboost;
1036379bc100SJani Nikula 
1037a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
103802107ef1SVille Syrjälä 		iboost = intel_bios_hdmi_boost_level(encoder->devdata);
1039379bc100SJani Nikula 	else
104002107ef1SVille Syrjälä 		iboost = intel_bios_dp_boost_level(encoder->devdata);
1041379bc100SJani Nikula 
1042379bc100SJani Nikula 	if (iboost == 0) {
1043e505d764SVille Syrjälä 		const struct intel_ddi_buf_trans *trans;
1044379bc100SJani Nikula 		int n_entries;
1045379bc100SJani Nikula 
1046e505d764SVille Syrjälä 		trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1047e505d764SVille Syrjälä 		if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
1048379bc100SJani Nikula 			return;
1049379bc100SJani Nikula 
1050e505d764SVille Syrjälä 		iboost = trans->entries[level].hsw.i_boost;
1051379bc100SJani Nikula 	}
1052379bc100SJani Nikula 
1053379bc100SJani Nikula 	/* Make sure that the requested I_boost is valid */
1054379bc100SJani Nikula 	if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) {
105547bdb1caSJani Nikula 		drm_err(&dev_priv->drm, "Invalid I_boost value %u\n", iboost);
1056379bc100SJani Nikula 		return;
1057379bc100SJani Nikula 	}
1058379bc100SJani Nikula 
1059f0e86e05SJosé Roberto de Souza 	_skl_ddi_set_iboost(dev_priv, encoder->port, iboost);
1060379bc100SJani Nikula 
1061f0e86e05SJosé Roberto de Souza 	if (encoder->port == PORT_A && dig_port->max_lanes == 4)
1062379bc100SJani Nikula 		_skl_ddi_set_iboost(dev_priv, PORT_E, iboost);
1063379bc100SJani Nikula }
1064379bc100SJani Nikula 
1065a621860aSVille Syrjälä static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
1066a621860aSVille Syrjälä 				   const struct intel_crtc_state *crtc_state)
1067379bc100SJani Nikula {
106853de0a20SVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
1069379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1070379bc100SJani Nikula 	int n_entries;
1071379bc100SJani Nikula 
1072c40a253bSVille Syrjälä 	encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1073379bc100SJani Nikula 
10741de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, n_entries < 1))
1075379bc100SJani Nikula 		n_entries = 1;
10761de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
10771de143ccSPankaj Bharadiya 			n_entries > ARRAY_SIZE(index_to_dp_signal_levels)))
1078379bc100SJani Nikula 		n_entries = ARRAY_SIZE(index_to_dp_signal_levels);
1079379bc100SJani Nikula 
1080379bc100SJani Nikula 	return index_to_dp_signal_levels[n_entries - 1] &
1081379bc100SJani Nikula 		DP_TRAIN_VOLTAGE_SWING_MASK;
1082379bc100SJani Nikula }
1083379bc100SJani Nikula 
1084379bc100SJani Nikula /*
1085379bc100SJani Nikula  * We assume that the full set of pre-emphasis values can be
1086379bc100SJani Nikula  * used on all DDI platforms. Should that change we need to
1087379bc100SJani Nikula  * rethink this code.
1088379bc100SJani Nikula  */
108953de0a20SVille Syrjälä static u8 intel_ddi_dp_preemph_max(struct intel_dp *intel_dp)
1090379bc100SJani Nikula {
1091379bc100SJani Nikula 	return DP_TRAIN_PRE_EMPH_LEVEL_3;
1092379bc100SJani Nikula }
1093379bc100SJani Nikula 
10945e7fe4d9SVille Syrjälä static u32 icl_combo_phy_loadgen_select(const struct intel_crtc_state *crtc_state,
10955e7fe4d9SVille Syrjälä 					int lane)
10965e7fe4d9SVille Syrjälä {
10975e7fe4d9SVille Syrjälä 	if (crtc_state->port_clock > 600000)
10985e7fe4d9SVille Syrjälä 		return 0;
10995e7fe4d9SVille Syrjälä 
11005e7fe4d9SVille Syrjälä 	if (crtc_state->lane_count == 4)
11015e7fe4d9SVille Syrjälä 		return lane >= 1 ? LOADGEN_SELECT : 0;
11025e7fe4d9SVille Syrjälä 	else
11035e7fe4d9SVille Syrjälä 		return lane == 1 || lane == 2 ? LOADGEN_SELECT : 0;
11045e7fe4d9SVille Syrjälä }
11055e7fe4d9SVille Syrjälä 
1106a8143150SJosé Roberto de Souza static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
1107193299adSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
1108379bc100SJani Nikula {
1109a8143150SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1110e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1111f0e86e05SJosé Roberto de Souza 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
1112a621860aSVille Syrjälä 	int n_entries, ln;
1113a621860aSVille Syrjälä 	u32 val;
1114379bc100SJani Nikula 
1115e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1116e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
111785da0292SVille Syrjälä 		return;
1118379bc100SJani Nikula 
1119a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
112081619f4aSJosé Roberto de Souza 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
112181619f4aSJosé Roberto de Souza 
112281619f4aSJosé Roberto de Souza 		val = EDP4K2K_MODE_OVRD_EN | EDP4K2K_MODE_OVRD_OPTIMIZED;
1123e505d764SVille Syrjälä 		intel_dp->hobl_active = is_hobl_buf_trans(trans);
112481619f4aSJosé Roberto de Souza 		intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy), val,
112581619f4aSJosé Roberto de Souza 			     intel_dp->hobl_active ? val : 0);
112681619f4aSJosé Roberto de Souza 	}
112781619f4aSJosé Roberto de Souza 
1128379bc100SJani Nikula 	/* Set PORT_TX_DW5 */
1129e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1130379bc100SJani Nikula 	val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
1131379bc100SJani Nikula 		  TAP2_DISABLE | TAP3_DISABLE);
1132379bc100SJani Nikula 	val |= SCALING_MODE_SEL(0x2);
1133379bc100SJani Nikula 	val |= RTERM_SELECT(0x6);
1134379bc100SJani Nikula 	val |= TAP3_DISABLE;
1135f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1136379bc100SJani Nikula 
1137379bc100SJani Nikula 	/* Program PORT_TX_DW2 */
1138f20ca899SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
113931e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
114031e914a2SVille Syrjälä 
1141c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy),
1142c1d53cbdSVille Syrjälä 			     SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK | RCOMP_SCALAR_MASK,
1143c1d53cbdSVille Syrjälä 			     SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel) |
1144c1d53cbdSVille Syrjälä 			     SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel) |
1145c1d53cbdSVille Syrjälä 			     RCOMP_SCALAR(0x98));
1146f20ca899SVille Syrjälä 	}
1147379bc100SJani Nikula 
1148379bc100SJani Nikula 	/* Program PORT_TX_DW4 */
1149379bc100SJani Nikula 	/* We cannot write to GRP. It would overwrite individual loadgen. */
1150a1f01768SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
115131e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
115231e914a2SVille Syrjälä 
1153c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1154c1d53cbdSVille Syrjälä 			     POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK,
1155c1d53cbdSVille Syrjälä 			     POST_CURSOR_1(trans->entries[level].icl.dw4_post_cursor_1) |
1156c1d53cbdSVille Syrjälä 			     POST_CURSOR_2(trans->entries[level].icl.dw4_post_cursor_2) |
1157c1d53cbdSVille Syrjälä 			     CURSOR_COEFF(trans->entries[level].icl.dw4_cursor_coeff));
1158379bc100SJani Nikula 	}
1159379bc100SJani Nikula 
1160379bc100SJani Nikula 	/* Program PORT_TX_DW7 */
1161f20ca899SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
116231e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
116331e914a2SVille Syrjälä 
1164c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy),
1165c1d53cbdSVille Syrjälä 			     N_SCALAR_MASK,
1166c1d53cbdSVille Syrjälä 			     N_SCALAR(trans->entries[level].icl.dw7_n_scalar));
1167f20ca899SVille Syrjälä 	}
1168379bc100SJani Nikula }
1169379bc100SJani Nikula 
1170193299adSVille Syrjälä static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder,
1171193299adSVille Syrjälä 					    const struct intel_crtc_state *crtc_state)
1172379bc100SJani Nikula {
1173379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1174dc867bc7SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
1175379bc100SJani Nikula 	u32 val;
11765e7fe4d9SVille Syrjälä 	int ln;
1177379bc100SJani Nikula 
1178379bc100SJani Nikula 	/*
1179379bc100SJani Nikula 	 * 1. If port type is eDP or DP,
1180379bc100SJani Nikula 	 * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
1181379bc100SJani Nikula 	 * else clear to 0b.
1182379bc100SJani Nikula 	 */
1183e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
1184a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1185379bc100SJani Nikula 		val &= ~COMMON_KEEPER_EN;
1186379bc100SJani Nikula 	else
1187379bc100SJani Nikula 		val |= COMMON_KEEPER_EN;
1188f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
1189379bc100SJani Nikula 
1190379bc100SJani Nikula 	/* 2. Program loadgen select */
1191379bc100SJani Nikula 	/*
1192e6908588SVille Syrjälä 	 * Program PORT_TX_DW4 depending on Bit rate and used lanes
1193379bc100SJani Nikula 	 * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
1194379bc100SJani Nikula 	 * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
1195379bc100SJani Nikula 	 * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
1196379bc100SJani Nikula 	 */
1197a1f01768SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
1198c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1199c1d53cbdSVille Syrjälä 			     LOADGEN_SELECT,
1200c1d53cbdSVille Syrjälä 			     icl_combo_phy_loadgen_select(crtc_state, ln));
1201379bc100SJani Nikula 	}
1202379bc100SJani Nikula 
1203379bc100SJani Nikula 	/* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
1204c1d53cbdSVille Syrjälä 	intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy),
1205c1d53cbdSVille Syrjälä 		     0, SUS_CLOCK_CONFIG);
1206379bc100SJani Nikula 
1207379bc100SJani Nikula 	/* 4. Clear training enable to change swing values */
1208e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1209379bc100SJani Nikula 	val &= ~TX_TRAINING_EN;
1210f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1211379bc100SJani Nikula 
1212379bc100SJani Nikula 	/* 5. Program swing and de-emphasis */
1213193299adSVille Syrjälä 	icl_ddi_combo_vswing_program(encoder, crtc_state);
1214379bc100SJani Nikula 
1215379bc100SJani Nikula 	/* 6. Set training enable to trigger update */
1216e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1217379bc100SJani Nikula 	val |= TX_TRAINING_EN;
1218f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1219379bc100SJani Nikula }
1220379bc100SJani Nikula 
1221193299adSVille Syrjälä static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder,
1222193299adSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
1223379bc100SJani Nikula {
1224379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1225f21e8b80SJosé Roberto de Souza 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
1226e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1227a621860aSVille Syrjälä 	int n_entries, ln;
1228379bc100SJani Nikula 
122911a89708SImre Deak 	if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1230f8c6b615SVille Syrjälä 		return;
1231f8c6b615SVille Syrjälä 
1232e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1233e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
123485da0292SVille Syrjälä 		return;
1235379bc100SJani Nikula 
1236379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1237d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port),
1238d4e0f163SVille Syrjälä 			     CRI_USE_FS32, 0);
1239d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port),
1240d4e0f163SVille Syrjälä 			     CRI_USE_FS32, 0);
1241379bc100SJani Nikula 	}
1242379bc100SJani Nikula 
1243379bc100SJani Nikula 	/* Program MG_TX_SWINGCTRL with values from vswing table */
1244379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1245305448e5SVille Syrjälä 		int level;
1246305448e5SVille Syrjälä 
1247305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1248305448e5SVille Syrjälä 
1249d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port),
1250d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1251d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1252379bc100SJani Nikula 
1253305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1254305448e5SVille Syrjälä 
1255d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port),
1256d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1257d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1258379bc100SJani Nikula 	}
1259379bc100SJani Nikula 
1260379bc100SJani Nikula 	/* Program MG_TX_DRVCTRL with values from vswing table */
1261379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1262305448e5SVille Syrjälä 		int level;
1263305448e5SVille Syrjälä 
1264305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1265305448e5SVille Syrjälä 
1266d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_DRVCTRL(ln, tc_port),
1267d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1268d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1269d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1270d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1271d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_EN);
1272379bc100SJani Nikula 
1273305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1274305448e5SVille Syrjälä 
1275d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_DRVCTRL(ln, tc_port),
1276d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1277d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1278d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1279d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1280d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_EN);
1281379bc100SJani Nikula 
1282379bc100SJani Nikula 		/* FIXME: Program CRI_LOADGEN_SEL after the spec is updated */
1283379bc100SJani Nikula 	}
1284379bc100SJani Nikula 
1285379bc100SJani Nikula 	/*
1286379bc100SJani Nikula 	 * Program MG_CLKHUB<LN, port being used> with value from frequency table
1287379bc100SJani Nikula 	 * In case of Legacy mode on MG PHY, both TX1 and TX2 enabled so use the
1288379bc100SJani Nikula 	 * values from table for which TX1 and TX2 enabled.
1289379bc100SJani Nikula 	 */
1290379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1291d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_CLKHUB(ln, tc_port),
1292d4e0f163SVille Syrjälä 			     CFG_LOW_RATE_LKREN_EN,
1293d4e0f163SVille Syrjälä 			     crtc_state->port_clock < 300000 ? CFG_LOW_RATE_LKREN_EN : 0);
1294379bc100SJani Nikula 	}
1295379bc100SJani Nikula 
1296379bc100SJani Nikula 	/* Program the MG_TX_DCC<LN, port being used> based on the link frequency */
1297379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1298d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_DCC(ln, tc_port),
1299d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1300d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN,
1301d4e0f163SVille Syrjälä 			     crtc_state->port_clock > 500000 ?
1302d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1303d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1304379bc100SJani Nikula 
1305d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_DCC(ln, tc_port),
1306d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1307d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN,
1308d4e0f163SVille Syrjälä 			     crtc_state->port_clock > 500000 ?
1309d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1310d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1311379bc100SJani Nikula 	}
1312379bc100SJani Nikula 
1313379bc100SJani Nikula 	/* Program MG_TX_PISO_READLOAD with values from vswing table */
1314379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1315d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_PISO_READLOAD(ln, tc_port),
1316d4e0f163SVille Syrjälä 			     0, CRI_CALCINIT);
1317d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_PISO_READLOAD(ln, tc_port),
1318d4e0f163SVille Syrjälä 			     0, CRI_CALCINIT);
1319379bc100SJani Nikula 	}
1320379bc100SJani Nikula }
1321379bc100SJani Nikula 
1322193299adSVille Syrjälä static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
1323193299adSVille Syrjälä 					  const struct intel_crtc_state *crtc_state)
1324978c3e53SClinton A Taylor {
1325978c3e53SClinton A Taylor 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1326978c3e53SClinton A Taylor 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
1327e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1328a621860aSVille Syrjälä 	int n_entries, ln;
1329978c3e53SClinton A Taylor 
133011a89708SImre Deak 	if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1331f8c6b615SVille Syrjälä 		return;
1332f8c6b615SVille Syrjälä 
1333e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1334e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
133585da0292SVille Syrjälä 		return;
1336978c3e53SClinton A Taylor 
1337978c3e53SClinton A Taylor 	for (ln = 0; ln < 2; ln++) {
1338a905ced6SVille Syrjälä 		int level;
1339a905ced6SVille Syrjälä 
1340b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0);
13412d69c42eSJosé Roberto de Souza 
1342a905ced6SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1343a905ced6SVille Syrjälä 
1344b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln),
1345c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF_MASK |
1346a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1347c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL_MASK,
1348c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1349a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1350c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1351978c3e53SClinton A Taylor 
1352a905ced6SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1353a905ced6SVille Syrjälä 
1354b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln),
1355c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF_MASK |
1356a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1357c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL_MASK,
1358c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1359a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1360c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1361978c3e53SClinton A Taylor 
1362b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
1363c86e1873SVille Syrjälä 				  DKL_TX_DP20BITMODE, 0);
13645ff59dddSJosé Roberto de Souza 
13655ff59dddSJosé Roberto de Souza 		if (IS_ALDERLAKE_P(dev_priv)) {
13665ff59dddSJosé Roberto de Souza 			u32 val;
13675ff59dddSJosé Roberto de Souza 
13685ff59dddSJosé Roberto de Souza 			if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
13695ff59dddSJosé Roberto de Souza 				if (ln == 0) {
13705ff59dddSJosé Roberto de Souza 					val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13715ff59dddSJosé Roberto de Souza 					val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(2);
13725ff59dddSJosé Roberto de Souza 				} else {
13735ff59dddSJosé Roberto de Souza 					val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(3);
13745ff59dddSJosé Roberto de Souza 					val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(3);
13755ff59dddSJosé Roberto de Souza 				}
13765ff59dddSJosé Roberto de Souza 			} else {
13775ff59dddSJosé Roberto de Souza 				val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13785ff59dddSJosé Roberto de Souza 				val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0);
13795ff59dddSJosé Roberto de Souza 			}
13805ff59dddSJosé Roberto de Souza 
1381b8ed5533SImre Deak 			intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
13825ff59dddSJosé Roberto de Souza 					  DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
13835ff59dddSJosé Roberto de Souza 					  DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
13845ff59dddSJosé Roberto de Souza 					  val);
13855ff59dddSJosé Roberto de Souza 		}
1386978c3e53SClinton A Taylor 	}
1387978c3e53SClinton A Taylor }
1388978c3e53SClinton A Taylor 
1389a621860aSVille Syrjälä static int translate_signal_level(struct intel_dp *intel_dp,
1390a621860aSVille Syrjälä 				  u8 signal_levels)
1391379bc100SJani Nikula {
13928b4f2137SPankaj Bharadiya 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
1393379bc100SJani Nikula 	int i;
1394379bc100SJani Nikula 
1395379bc100SJani Nikula 	for (i = 0; i < ARRAY_SIZE(index_to_dp_signal_levels); i++) {
1396379bc100SJani Nikula 		if (index_to_dp_signal_levels[i] == signal_levels)
1397379bc100SJani Nikula 			return i;
1398379bc100SJani Nikula 	}
1399379bc100SJani Nikula 
14008b4f2137SPankaj Bharadiya 	drm_WARN(&i915->drm, 1,
14018b4f2137SPankaj Bharadiya 		 "Unsupported voltage swing/pre-emphasis level: 0x%x\n",
1402379bc100SJani Nikula 		 signal_levels);
1403379bc100SJani Nikula 
1404379bc100SJani Nikula 	return 0;
1405379bc100SJani Nikula }
1406379bc100SJani Nikula 
14075c31e9d0SJani Nikula static int intel_ddi_dp_level(struct intel_dp *intel_dp,
14085c31e9d0SJani Nikula 			      const struct intel_crtc_state *crtc_state,
14095c31e9d0SJani Nikula 			      int lane)
1410379bc100SJani Nikula {
1411d0920a45SVille Syrjälä 	u8 train_set = intel_dp->train_set[lane];
14125c31e9d0SJani Nikula 
14135c31e9d0SJani Nikula 	if (intel_dp_is_uhbr(crtc_state)) {
14145c31e9d0SJani Nikula 		return train_set & DP_TX_FFE_PRESET_VALUE_MASK;
14155c31e9d0SJani Nikula 	} else {
1416a621860aSVille Syrjälä 		u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
1417379bc100SJani Nikula 						DP_TRAIN_PRE_EMPHASIS_MASK);
1418379bc100SJani Nikula 
14198b4f2137SPankaj Bharadiya 		return translate_signal_level(intel_dp, signal_levels);
1420379bc100SJani Nikula 	}
14215c31e9d0SJani Nikula }
1422379bc100SJani Nikula 
1423193299adSVille Syrjälä int intel_ddi_level(struct intel_encoder *encoder,
1424d0920a45SVille Syrjälä 		    const struct intel_crtc_state *crtc_state,
1425d0920a45SVille Syrjälä 		    int lane)
1426a046a0daSMatt Roper {
14272c63e0f9SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
14282c63e0f9SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
14292c63e0f9SVille Syrjälä 	int level, n_entries;
14302c63e0f9SVille Syrjälä 
14312c63e0f9SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
14322c63e0f9SVille Syrjälä 	if (drm_WARN_ON_ONCE(&i915->drm, !trans))
14332c63e0f9SVille Syrjälä 		return 0;
14342c63e0f9SVille Syrjälä 
1435e722ab8bSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
14363e022c1fSVille Syrjälä 		level = intel_ddi_hdmi_level(encoder, trans);
1437e722ab8bSVille Syrjälä 	else
14385c31e9d0SJani Nikula 		level = intel_ddi_dp_level(enc_to_intel_dp(encoder), crtc_state,
14395c31e9d0SJani Nikula 					   lane);
14402c63e0f9SVille Syrjälä 
14412c63e0f9SVille Syrjälä 	if (drm_WARN_ON_ONCE(&i915->drm, level >= n_entries))
14422c63e0f9SVille Syrjälä 		level = n_entries - 1;
14432c63e0f9SVille Syrjälä 
14442c63e0f9SVille Syrjälä 	return level;
1445e722ab8bSVille Syrjälä }
1446e722ab8bSVille Syrjälä 
1447e722ab8bSVille Syrjälä static void
1448e722ab8bSVille Syrjälä hsw_set_signal_levels(struct intel_encoder *encoder,
1449a621860aSVille Syrjälä 		      const struct intel_crtc_state *crtc_state)
1450fb83f72cSVille Syrjälä {
1451fb83f72cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1452e722ab8bSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1453d0920a45SVille Syrjälä 	int level = intel_ddi_level(encoder, crtc_state, 0);
1454fb83f72cSVille Syrjälä 	enum port port = encoder->port;
1455fb83f72cSVille Syrjälä 	u32 signal_levels;
1456fb83f72cSVille Syrjälä 
1457e722ab8bSVille Syrjälä 	if (has_iboost(dev_priv))
1458e722ab8bSVille Syrjälä 		skl_ddi_set_iboost(encoder, crtc_state, level);
1459e722ab8bSVille Syrjälä 
1460e722ab8bSVille Syrjälä 	/* HDMI ignores the rest */
1461e722ab8bSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1462e722ab8bSVille Syrjälä 		return;
1463e722ab8bSVille Syrjälä 
1464fb83f72cSVille Syrjälä 	signal_levels = DDI_BUF_TRANS_SELECT(level);
1465fb83f72cSVille Syrjälä 
1466fb83f72cSVille Syrjälä 	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
1467fb83f72cSVille Syrjälä 		    signal_levels);
1468fb83f72cSVille Syrjälä 
1469fb83f72cSVille Syrjälä 	intel_dp->DP &= ~DDI_BUF_EMP_MASK;
1470fb83f72cSVille Syrjälä 	intel_dp->DP |= signal_levels;
1471fb83f72cSVille Syrjälä 
1472fb83f72cSVille Syrjälä 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
1473fb83f72cSVille Syrjälä 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
1474379bc100SJani Nikula }
1475379bc100SJani Nikula 
14764da27d5dSLucas De Marchi static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14779c6a5c35SVille Syrjälä 				  u32 clk_sel_mask, u32 clk_sel, u32 clk_off)
14789c6a5c35SVille Syrjälä {
147936d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
14809c6a5c35SVille Syrjälä 
14819c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, clk_sel_mask, clk_sel);
14829c6a5c35SVille Syrjälä 
14839c6a5c35SVille Syrjälä 	/*
14849c6a5c35SVille Syrjälä 	 * "This step and the step before must be
14859c6a5c35SVille Syrjälä 	 *  done with separate register writes."
14869c6a5c35SVille Syrjälä 	 */
14879c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, clk_off, 0);
14889c6a5c35SVille Syrjälä 
148936d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
14909c6a5c35SVille Syrjälä }
14919c6a5c35SVille Syrjälä 
14924da27d5dSLucas De Marchi static void _icl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14939c6a5c35SVille Syrjälä 				   u32 clk_off)
14949c6a5c35SVille Syrjälä {
149536d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
14969c6a5c35SVille Syrjälä 
14979c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, 0, clk_off);
14989c6a5c35SVille Syrjälä 
149936d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
15009c6a5c35SVille Syrjälä }
15019c6a5c35SVille Syrjälä 
15024da27d5dSLucas De Marchi static bool _icl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg,
15030fbd8694SVille Syrjälä 				      u32 clk_off)
15040fbd8694SVille Syrjälä {
15050fbd8694SVille Syrjälä 	return !(intel_de_read(i915, reg) & clk_off);
15060fbd8694SVille Syrjälä }
15070fbd8694SVille Syrjälä 
1508351221ffSVille Syrjälä static struct intel_shared_dpll *
15094da27d5dSLucas De Marchi _icl_ddi_get_pll(struct drm_i915_private *i915, i915_reg_t reg,
1510351221ffSVille Syrjälä 		 u32 clk_sel_mask, u32 clk_sel_shift)
1511351221ffSVille Syrjälä {
1512351221ffSVille Syrjälä 	enum intel_dpll_id id;
1513351221ffSVille Syrjälä 
1514351221ffSVille Syrjälä 	id = (intel_de_read(i915, reg) & clk_sel_mask) >> clk_sel_shift;
1515351221ffSVille Syrjälä 
1516351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1517351221ffSVille Syrjälä }
1518351221ffSVille Syrjälä 
151940b316d4SVille Syrjälä static void adls_ddi_enable_clock(struct intel_encoder *encoder,
152040b316d4SVille Syrjälä 				  const struct intel_crtc_state *crtc_state)
152140b316d4SVille Syrjälä {
152240b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
152340b316d4SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
152440b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
152540b316d4SVille Syrjälä 
152640b316d4SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
152740b316d4SVille Syrjälä 		return;
152840b316d4SVille Syrjälä 
15294da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
153040b316d4SVille Syrjälä 			      ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
153140b316d4SVille Syrjälä 			      pll->info->id << ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy),
153240b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
153340b316d4SVille Syrjälä }
153440b316d4SVille Syrjälä 
153540b316d4SVille Syrjälä static void adls_ddi_disable_clock(struct intel_encoder *encoder)
153640b316d4SVille Syrjälä {
153740b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
153840b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
153940b316d4SVille Syrjälä 
15404da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
154140b316d4SVille Syrjälä 			       ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
154240b316d4SVille Syrjälä }
154340b316d4SVille Syrjälä 
15440fbd8694SVille Syrjälä static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder)
15450fbd8694SVille Syrjälä {
15460fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15470fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
15480fbd8694SVille Syrjälä 
15494da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy),
15500fbd8694SVille Syrjälä 					 ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15510fbd8694SVille Syrjälä }
15520fbd8694SVille Syrjälä 
1553351221ffSVille Syrjälä static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
1554351221ffSVille Syrjälä {
1555351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1556351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1557351221ffSVille Syrjälä 
15584da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy),
1559351221ffSVille Syrjälä 				ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
1560351221ffSVille Syrjälä 				ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy));
1561351221ffSVille Syrjälä }
1562351221ffSVille Syrjälä 
156340b316d4SVille Syrjälä static void rkl_ddi_enable_clock(struct intel_encoder *encoder,
156440b316d4SVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
156540b316d4SVille Syrjälä {
156640b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
156740b316d4SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
156840b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
156940b316d4SVille Syrjälä 
157040b316d4SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
157140b316d4SVille Syrjälä 		return;
157240b316d4SVille Syrjälä 
15734da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
157440b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
157540b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
157640b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
157740b316d4SVille Syrjälä }
157840b316d4SVille Syrjälä 
157940b316d4SVille Syrjälä static void rkl_ddi_disable_clock(struct intel_encoder *encoder)
158040b316d4SVille Syrjälä {
158140b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
158240b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
158340b316d4SVille Syrjälä 
15844da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
158540b316d4SVille Syrjälä 			       RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
158640b316d4SVille Syrjälä }
158740b316d4SVille Syrjälä 
15880fbd8694SVille Syrjälä static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder)
15890fbd8694SVille Syrjälä {
15900fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15910fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
15920fbd8694SVille Syrjälä 
15934da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
15940fbd8694SVille Syrjälä 					 RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15950fbd8694SVille Syrjälä }
15960fbd8694SVille Syrjälä 
1597351221ffSVille Syrjälä static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
1598351221ffSVille Syrjälä {
1599351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1600351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1601351221ffSVille Syrjälä 
16024da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1603351221ffSVille Syrjälä 				RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1604351221ffSVille Syrjälä 				RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1605351221ffSVille Syrjälä }
1606351221ffSVille Syrjälä 
160735bb6b1aSVille Syrjälä static void dg1_ddi_enable_clock(struct intel_encoder *encoder,
160811ffe972SLucas De Marchi 				 const struct intel_crtc_state *crtc_state)
160911ffe972SLucas De Marchi {
161097a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16119c6a5c35SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
161297a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
161311ffe972SLucas De Marchi 
161497a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1615f67a008eSVille Syrjälä 		return;
1616f67a008eSVille Syrjälä 
161711ffe972SLucas De Marchi 	/*
161811ffe972SLucas De Marchi 	 * If we fail this, something went very wrong: first 2 PLLs should be
161911ffe972SLucas De Marchi 	 * used by first 2 phys and last 2 PLLs by last phys
162011ffe972SLucas De Marchi 	 */
162197a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm,
162211ffe972SLucas De Marchi 			(pll->info->id < DPLL_ID_DG1_DPLL2 && phy >= PHY_C) ||
162311ffe972SLucas De Marchi 			(pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C)))
162411ffe972SLucas De Marchi 		return;
162511ffe972SLucas De Marchi 
16264da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16277815ed88SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
16289c6a5c35SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
16299c6a5c35SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
163011ffe972SLucas De Marchi }
163111ffe972SLucas De Marchi 
163235bb6b1aSVille Syrjälä static void dg1_ddi_disable_clock(struct intel_encoder *encoder)
163335bb6b1aSVille Syrjälä {
163497a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
163597a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
163635bb6b1aSVille Syrjälä 
16374da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16389c6a5c35SVille Syrjälä 			       DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
163935bb6b1aSVille Syrjälä }
164035bb6b1aSVille Syrjälä 
16410fbd8694SVille Syrjälä static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder)
16420fbd8694SVille Syrjälä {
16430fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16440fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16450fbd8694SVille Syrjälä 
16464da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy),
16470fbd8694SVille Syrjälä 					 DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
16480fbd8694SVille Syrjälä }
16490fbd8694SVille Syrjälä 
1650351221ffSVille Syrjälä static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
1651351221ffSVille Syrjälä {
1652351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1653351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16543352d86dSJosé Roberto de Souza 	enum intel_dpll_id id;
16553352d86dSJosé Roberto de Souza 	u32 val;
1656351221ffSVille Syrjälä 
16573352d86dSJosé Roberto de Souza 	val = intel_de_read(i915, DG1_DPCLKA_CFGCR0(phy));
16583352d86dSJosé Roberto de Souza 	val &= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
16593352d86dSJosé Roberto de Souza 	val >>= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
16603352d86dSJosé Roberto de Souza 	id = val;
16613352d86dSJosé Roberto de Souza 
16623352d86dSJosé Roberto de Souza 	/*
16633352d86dSJosé Roberto de Souza 	 * _DG1_DPCLKA0_CFGCR0 maps between DPLL 0 and 1 with one bit for phy A
16643352d86dSJosé Roberto de Souza 	 * and B while _DG1_DPCLKA1_CFGCR0 maps between DPLL 2 and 3 with one
16653352d86dSJosé Roberto de Souza 	 * bit for phy C and D.
16663352d86dSJosé Roberto de Souza 	 */
16673352d86dSJosé Roberto de Souza 	if (phy >= PHY_C)
16683352d86dSJosé Roberto de Souza 		id += DPLL_ID_DG1_DPLL2;
16693352d86dSJosé Roberto de Souza 
16703352d86dSJosé Roberto de Souza 	return intel_get_shared_dpll_by_id(i915, id);
1671351221ffSVille Syrjälä }
1672351221ffSVille Syrjälä 
167336ecb0ecSVille Syrjälä static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder,
1674379bc100SJani Nikula 				       const struct intel_crtc_state *crtc_state)
1675379bc100SJani Nikula {
167697a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16779c6a5c35SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
167897a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1679cd803bb4SMatt Roper 
168097a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1681f67a008eSVille Syrjälä 		return;
1682f67a008eSVille Syrjälä 
16834da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
168440b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
168540b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
168640b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1687379bc100SJani Nikula }
1688379bc100SJani Nikula 
168936ecb0ecSVille Syrjälä static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder)
1690379bc100SJani Nikula {
169197a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
169297a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1693379bc100SJani Nikula 
16944da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
169540b316d4SVille Syrjälä 			       ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1696379bc100SJani Nikula }
1697379bc100SJani Nikula 
16980fbd8694SVille Syrjälä static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder)
16990fbd8694SVille Syrjälä {
17000fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17010fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
17020fbd8694SVille Syrjälä 
17034da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
17040fbd8694SVille Syrjälä 					 ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
17050fbd8694SVille Syrjälä }
17060fbd8694SVille Syrjälä 
1707351221ffSVille Syrjälä struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
1708351221ffSVille Syrjälä {
1709351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1710351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1711351221ffSVille Syrjälä 
17124da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1713351221ffSVille Syrjälä 				ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1714351221ffSVille Syrjälä 				ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1715351221ffSVille Syrjälä }
1716351221ffSVille Syrjälä 
171736ecb0ecSVille Syrjälä static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder,
1718379bc100SJani Nikula 				    const struct intel_crtc_state *crtc_state)
1719379bc100SJani Nikula {
172036ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1721379bc100SJani Nikula 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
172236ecb0ecSVille Syrjälä 	enum port port = encoder->port;
1723379bc100SJani Nikula 
172436ecb0ecSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1725379bc100SJani Nikula 		return;
1726379bc100SJani Nikula 
1727c2052d6eSJosé Roberto de Souza 	/*
172836ecb0ecSVille Syrjälä 	 * "For DDIC and DDID, program DDI_CLK_SEL to map the MG clock to the port.
172936ecb0ecSVille Syrjälä 	 *  MG does not exist, but the programming is required to ungate DDIC and DDID."
1730c2052d6eSJosé Roberto de Souza 	 */
173136ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_MG);
173236ecb0ecSVille Syrjälä 
173336ecb0ecSVille Syrjälä 	icl_ddi_combo_enable_clock(encoder, crtc_state);
1734379bc100SJani Nikula }
1735379bc100SJani Nikula 
173636ecb0ecSVille Syrjälä static void jsl_ddi_tc_disable_clock(struct intel_encoder *encoder)
1737379bc100SJani Nikula {
173836ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1739379bc100SJani Nikula 	enum port port = encoder->port;
1740379bc100SJani Nikula 
174136ecb0ecSVille Syrjälä 	icl_ddi_combo_disable_clock(encoder);
174236ecb0ecSVille Syrjälä 
174336ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1744379bc100SJani Nikula }
174536ecb0ecSVille Syrjälä 
17460fbd8694SVille Syrjälä static bool jsl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17470fbd8694SVille Syrjälä {
17480fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17490fbd8694SVille Syrjälä 	enum port port = encoder->port;
17500fbd8694SVille Syrjälä 	u32 tmp;
17510fbd8694SVille Syrjälä 
17520fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
17530fbd8694SVille Syrjälä 
17540fbd8694SVille Syrjälä 	if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
17550fbd8694SVille Syrjälä 		return false;
17560fbd8694SVille Syrjälä 
17570fbd8694SVille Syrjälä 	return icl_ddi_combo_is_clock_enabled(encoder);
17580fbd8694SVille Syrjälä }
17590fbd8694SVille Syrjälä 
176036ecb0ecSVille Syrjälä static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder,
176136ecb0ecSVille Syrjälä 				    const struct intel_crtc_state *crtc_state)
176236ecb0ecSVille Syrjälä {
176336ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
176436ecb0ecSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
176536ecb0ecSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
176636ecb0ecSVille Syrjälä 	enum port port = encoder->port;
176736ecb0ecSVille Syrjälä 
176836ecb0ecSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
176936ecb0ecSVille Syrjälä 		return;
177036ecb0ecSVille Syrjälä 
177136ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port),
177236ecb0ecSVille Syrjälä 		       icl_pll_to_ddi_clk_sel(encoder, crtc_state));
177336ecb0ecSVille Syrjälä 
177436d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
177536ecb0ecSVille Syrjälä 
177636ecb0ecSVille Syrjälä 	intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
177736ecb0ecSVille Syrjälä 		     ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port), 0);
177836ecb0ecSVille Syrjälä 
177936d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
178036ecb0ecSVille Syrjälä }
178136ecb0ecSVille Syrjälä 
178236ecb0ecSVille Syrjälä static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder)
178336ecb0ecSVille Syrjälä {
178436ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
178536ecb0ecSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
178636ecb0ecSVille Syrjälä 	enum port port = encoder->port;
178736ecb0ecSVille Syrjälä 
178836d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
178936ecb0ecSVille Syrjälä 
179036ecb0ecSVille Syrjälä 	intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
179136ecb0ecSVille Syrjälä 		     0, ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
179236ecb0ecSVille Syrjälä 
179336d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
179436ecb0ecSVille Syrjälä 
179536ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1796379bc100SJani Nikula }
1797379bc100SJani Nikula 
17980fbd8694SVille Syrjälä static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17990fbd8694SVille Syrjälä {
18000fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
18010fbd8694SVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
18020fbd8694SVille Syrjälä 	enum port port = encoder->port;
18030fbd8694SVille Syrjälä 	u32 tmp;
18040fbd8694SVille Syrjälä 
18050fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
18060fbd8694SVille Syrjälä 
18070fbd8694SVille Syrjälä 	if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
18080fbd8694SVille Syrjälä 		return false;
18090fbd8694SVille Syrjälä 
18100fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, ICL_DPCLKA_CFGCR0);
18110fbd8694SVille Syrjälä 
18120fbd8694SVille Syrjälä 	return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
18130fbd8694SVille Syrjälä }
18140fbd8694SVille Syrjälä 
1815351221ffSVille Syrjälä static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder)
1816351221ffSVille Syrjälä {
1817351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1818351221ffSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
1819351221ffSVille Syrjälä 	enum port port = encoder->port;
1820351221ffSVille Syrjälä 	enum intel_dpll_id id;
1821351221ffSVille Syrjälä 	u32 tmp;
1822351221ffSVille Syrjälä 
1823351221ffSVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
1824351221ffSVille Syrjälä 
1825351221ffSVille Syrjälä 	switch (tmp & DDI_CLK_SEL_MASK) {
1826351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_162:
1827351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_270:
1828351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_540:
1829351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_810:
1830351221ffSVille Syrjälä 		id = DPLL_ID_ICL_TBTPLL;
1831351221ffSVille Syrjälä 		break;
1832351221ffSVille Syrjälä 	case DDI_CLK_SEL_MG:
1833351221ffSVille Syrjälä 		id = icl_tc_port_to_pll_id(tc_port);
1834351221ffSVille Syrjälä 		break;
1835351221ffSVille Syrjälä 	default:
1836351221ffSVille Syrjälä 		MISSING_CASE(tmp);
1837351221ffSVille Syrjälä 		fallthrough;
1838351221ffSVille Syrjälä 	case DDI_CLK_SEL_NONE:
1839351221ffSVille Syrjälä 		return NULL;
1840351221ffSVille Syrjälä 	}
1841351221ffSVille Syrjälä 
1842351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1843351221ffSVille Syrjälä }
1844351221ffSVille Syrjälä 
1845351221ffSVille Syrjälä static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
1846351221ffSVille Syrjälä {
1847351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1848351221ffSVille Syrjälä 	enum intel_dpll_id id;
1849351221ffSVille Syrjälä 
1850351221ffSVille Syrjälä 	switch (encoder->port) {
1851351221ffSVille Syrjälä 	case PORT_A:
1852351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL0;
1853351221ffSVille Syrjälä 		break;
1854351221ffSVille Syrjälä 	case PORT_B:
1855351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL1;
1856351221ffSVille Syrjälä 		break;
1857351221ffSVille Syrjälä 	case PORT_C:
1858351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL2;
1859351221ffSVille Syrjälä 		break;
1860351221ffSVille Syrjälä 	default:
1861351221ffSVille Syrjälä 		MISSING_CASE(encoder->port);
1862351221ffSVille Syrjälä 		return NULL;
1863351221ffSVille Syrjälä 	}
1864351221ffSVille Syrjälä 
1865351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1866351221ffSVille Syrjälä }
1867351221ffSVille Syrjälä 
186838e31f1aSVille Syrjälä static void skl_ddi_enable_clock(struct intel_encoder *encoder,
186938e31f1aSVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
187038e31f1aSVille Syrjälä {
187138e31f1aSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
187238e31f1aSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
187338e31f1aSVille Syrjälä 	enum port port = encoder->port;
187438e31f1aSVille Syrjälä 
187538e31f1aSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
187638e31f1aSVille Syrjälä 		return;
187738e31f1aSVille Syrjälä 
187836d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
187938e31f1aSVille Syrjälä 
18807815ed88SVille Syrjälä 	intel_de_rmw(i915, DPLL_CTRL2,
18817815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_OFF(port) |
18827815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_SEL_MASK(port),
18837815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_SEL(pll->info->id, port) |
188438e31f1aSVille Syrjälä 		     DPLL_CTRL2_DDI_SEL_OVERRIDE(port));
188538e31f1aSVille Syrjälä 
188636d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
188738e31f1aSVille Syrjälä }
188838e31f1aSVille Syrjälä 
188938e31f1aSVille Syrjälä static void skl_ddi_disable_clock(struct intel_encoder *encoder)
189038e31f1aSVille Syrjälä {
189138e31f1aSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
189238e31f1aSVille Syrjälä 	enum port port = encoder->port;
189338e31f1aSVille Syrjälä 
189436d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
1895be317ca0SVille Syrjälä 
18967815ed88SVille Syrjälä 	intel_de_rmw(i915, DPLL_CTRL2,
18977815ed88SVille Syrjälä 		     0, DPLL_CTRL2_DDI_CLK_OFF(port));
1898be317ca0SVille Syrjälä 
189936d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
190038e31f1aSVille Syrjälä }
190138e31f1aSVille Syrjälä 
19020fbd8694SVille Syrjälä static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder)
19030fbd8694SVille Syrjälä {
19040fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19050fbd8694SVille Syrjälä 	enum port port = encoder->port;
19060fbd8694SVille Syrjälä 
19070fbd8694SVille Syrjälä 	/*
19080fbd8694SVille Syrjälä 	 * FIXME Not sure if the override affects both
19090fbd8694SVille Syrjälä 	 * the PLL selection and the CLK_OFF bit.
19100fbd8694SVille Syrjälä 	 */
19110fbd8694SVille Syrjälä 	return !(intel_de_read(i915, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port));
19120fbd8694SVille Syrjälä }
19130fbd8694SVille Syrjälä 
1914351221ffSVille Syrjälä static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
1915351221ffSVille Syrjälä {
1916351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1917351221ffSVille Syrjälä 	enum port port = encoder->port;
1918351221ffSVille Syrjälä 	enum intel_dpll_id id;
1919351221ffSVille Syrjälä 	u32 tmp;
1920351221ffSVille Syrjälä 
1921351221ffSVille Syrjälä 	tmp = intel_de_read(i915, DPLL_CTRL2);
1922351221ffSVille Syrjälä 
1923351221ffSVille Syrjälä 	/*
1924351221ffSVille Syrjälä 	 * FIXME Not sure if the override affects both
1925351221ffSVille Syrjälä 	 * the PLL selection and the CLK_OFF bit.
1926351221ffSVille Syrjälä 	 */
1927351221ffSVille Syrjälä 	if ((tmp & DPLL_CTRL2_DDI_SEL_OVERRIDE(port)) == 0)
1928351221ffSVille Syrjälä 		return NULL;
1929351221ffSVille Syrjälä 
1930351221ffSVille Syrjälä 	id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >>
1931351221ffSVille Syrjälä 		DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port);
1932351221ffSVille Syrjälä 
1933351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1934351221ffSVille Syrjälä }
1935351221ffSVille Syrjälä 
1936d135368dSVille Syrjälä void hsw_ddi_enable_clock(struct intel_encoder *encoder,
1937d135368dSVille Syrjälä 			  const struct intel_crtc_state *crtc_state)
1938d135368dSVille Syrjälä {
1939d135368dSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1940d135368dSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
1941d135368dSVille Syrjälä 	enum port port = encoder->port;
1942d135368dSVille Syrjälä 
1943d135368dSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1944d135368dSVille Syrjälä 		return;
1945d135368dSVille Syrjälä 
1946d135368dSVille Syrjälä 	intel_de_write(i915, PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll));
1947d135368dSVille Syrjälä }
1948d135368dSVille Syrjälä 
1949d135368dSVille Syrjälä void hsw_ddi_disable_clock(struct intel_encoder *encoder)
1950d135368dSVille Syrjälä {
1951d135368dSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1952d135368dSVille Syrjälä 	enum port port = encoder->port;
1953d135368dSVille Syrjälä 
1954d135368dSVille Syrjälä 	intel_de_write(i915, PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
1955d135368dSVille Syrjälä }
1956d135368dSVille Syrjälä 
19570fbd8694SVille Syrjälä bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder)
19580fbd8694SVille Syrjälä {
19590fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19600fbd8694SVille Syrjälä 	enum port port = encoder->port;
19610fbd8694SVille Syrjälä 
19620fbd8694SVille Syrjälä 	return intel_de_read(i915, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE;
19630fbd8694SVille Syrjälä }
19640fbd8694SVille Syrjälä 
1965351221ffSVille Syrjälä static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
1966351221ffSVille Syrjälä {
1967351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1968351221ffSVille Syrjälä 	enum port port = encoder->port;
1969351221ffSVille Syrjälä 	enum intel_dpll_id id;
1970351221ffSVille Syrjälä 	u32 tmp;
1971351221ffSVille Syrjälä 
1972351221ffSVille Syrjälä 	tmp = intel_de_read(i915, PORT_CLK_SEL(port));
1973351221ffSVille Syrjälä 
1974351221ffSVille Syrjälä 	switch (tmp & PORT_CLK_SEL_MASK) {
1975351221ffSVille Syrjälä 	case PORT_CLK_SEL_WRPLL1:
1976351221ffSVille Syrjälä 		id = DPLL_ID_WRPLL1;
1977351221ffSVille Syrjälä 		break;
1978351221ffSVille Syrjälä 	case PORT_CLK_SEL_WRPLL2:
1979351221ffSVille Syrjälä 		id = DPLL_ID_WRPLL2;
1980351221ffSVille Syrjälä 		break;
1981351221ffSVille Syrjälä 	case PORT_CLK_SEL_SPLL:
1982351221ffSVille Syrjälä 		id = DPLL_ID_SPLL;
1983351221ffSVille Syrjälä 		break;
1984351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_810:
1985351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_810;
1986351221ffSVille Syrjälä 		break;
1987351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_1350:
1988351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_1350;
1989351221ffSVille Syrjälä 		break;
1990351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_2700:
1991351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_2700;
1992351221ffSVille Syrjälä 		break;
1993351221ffSVille Syrjälä 	default:
1994351221ffSVille Syrjälä 		MISSING_CASE(tmp);
1995351221ffSVille Syrjälä 		fallthrough;
1996351221ffSVille Syrjälä 	case PORT_CLK_SEL_NONE:
1997351221ffSVille Syrjälä 		return NULL;
1998351221ffSVille Syrjälä 	}
1999351221ffSVille Syrjälä 
2000351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
2001351221ffSVille Syrjälä }
2002351221ffSVille Syrjälä 
2003c133df69SVille Syrjälä void intel_ddi_enable_clock(struct intel_encoder *encoder,
2004c133df69SVille Syrjälä 			    const struct intel_crtc_state *crtc_state)
2005c133df69SVille Syrjälä {
2006c133df69SVille Syrjälä 	if (encoder->enable_clock)
2007c133df69SVille Syrjälä 		encoder->enable_clock(encoder, crtc_state);
2008c133df69SVille Syrjälä }
2009c133df69SVille Syrjälä 
2010d39ef5d5SVille Syrjälä void intel_ddi_disable_clock(struct intel_encoder *encoder)
2011c133df69SVille Syrjälä {
2012c133df69SVille Syrjälä 	if (encoder->disable_clock)
2013c133df69SVille Syrjälä 		encoder->disable_clock(encoder);
2014c133df69SVille Syrjälä }
2015c133df69SVille Syrjälä 
2016aaca50efSVille Syrjälä void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
2017dc1ddac6SVille Syrjälä {
201897a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2019dc1ddac6SVille Syrjälä 	u32 port_mask;
2020dc1ddac6SVille Syrjälä 	bool ddi_clk_needed;
2021dc1ddac6SVille Syrjälä 
2022dc1ddac6SVille Syrjälä 	/*
2023dc1ddac6SVille Syrjälä 	 * In case of DP MST, we sanitize the primary encoder only, not the
2024dc1ddac6SVille Syrjälä 	 * virtual ones.
2025dc1ddac6SVille Syrjälä 	 */
2026dc1ddac6SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_DP_MST)
2027dc1ddac6SVille Syrjälä 		return;
2028dc1ddac6SVille Syrjälä 
2029dc1ddac6SVille Syrjälä 	if (!encoder->base.crtc && intel_encoder_is_dp(encoder)) {
2030dc1ddac6SVille Syrjälä 		u8 pipe_mask;
2031dc1ddac6SVille Syrjälä 		bool is_mst;
2032dc1ddac6SVille Syrjälä 
2033dc1ddac6SVille Syrjälä 		intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
2034dc1ddac6SVille Syrjälä 		/*
2035dc1ddac6SVille Syrjälä 		 * In the unlikely case that BIOS enables DP in MST mode, just
2036dc1ddac6SVille Syrjälä 		 * warn since our MST HW readout is incomplete.
2037dc1ddac6SVille Syrjälä 		 */
203897a24a70SVille Syrjälä 		if (drm_WARN_ON(&i915->drm, is_mst))
2039dc1ddac6SVille Syrjälä 			return;
2040dc1ddac6SVille Syrjälä 	}
2041dc1ddac6SVille Syrjälä 
2042dc1ddac6SVille Syrjälä 	port_mask = BIT(encoder->port);
2043dc1ddac6SVille Syrjälä 	ddi_clk_needed = encoder->base.crtc;
2044dc1ddac6SVille Syrjälä 
2045dc1ddac6SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_DSI) {
2046dc1ddac6SVille Syrjälä 		struct intel_encoder *other_encoder;
2047dc1ddac6SVille Syrjälä 
2048dc1ddac6SVille Syrjälä 		port_mask = intel_dsi_encoder_ports(encoder);
2049dc1ddac6SVille Syrjälä 		/*
2050dc1ddac6SVille Syrjälä 		 * Sanity check that we haven't incorrectly registered another
2051dc1ddac6SVille Syrjälä 		 * encoder using any of the ports of this DSI encoder.
2052dc1ddac6SVille Syrjälä 		 */
205397a24a70SVille Syrjälä 		for_each_intel_encoder(&i915->drm, other_encoder) {
2054dc1ddac6SVille Syrjälä 			if (other_encoder == encoder)
2055dc1ddac6SVille Syrjälä 				continue;
2056dc1ddac6SVille Syrjälä 
205797a24a70SVille Syrjälä 			if (drm_WARN_ON(&i915->drm,
2058dc1ddac6SVille Syrjälä 					port_mask & BIT(other_encoder->port)))
2059dc1ddac6SVille Syrjälä 				return;
2060dc1ddac6SVille Syrjälä 		}
2061dc1ddac6SVille Syrjälä 		/*
2062dc1ddac6SVille Syrjälä 		 * For DSI we keep the ddi clocks gated
2063dc1ddac6SVille Syrjälä 		 * except during enable/disable sequence.
2064dc1ddac6SVille Syrjälä 		 */
2065dc1ddac6SVille Syrjälä 		ddi_clk_needed = false;
2066dc1ddac6SVille Syrjälä 	}
2067dc1ddac6SVille Syrjälä 
2068f82f2563SMatt Roper 	if (ddi_clk_needed || !encoder->is_clock_enabled ||
20690fbd8694SVille Syrjälä 	    !encoder->is_clock_enabled(encoder))
20700fbd8694SVille Syrjälä 		return;
20710fbd8694SVille Syrjälä 
20720fbd8694SVille Syrjälä 	drm_notice(&i915->drm,
20730fbd8694SVille Syrjälä 		   "[ENCODER:%d:%s] is disabled/in DSI mode with an ungated DDI clock, gate it\n",
20740fbd8694SVille Syrjälä 		   encoder->base.base.id, encoder->base.name);
20750fbd8694SVille Syrjälä 
2076dc1ddac6SVille Syrjälä 	encoder->disable_clock(encoder);
2077dc1ddac6SVille Syrjälä }
2078dc1ddac6SVille Syrjälä 
20798aaf5cbdSJosé Roberto de Souza static void
20807801f3b7SLucas De Marchi icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
20813b51be4eSClinton A Taylor 		       const struct intel_crtc_state *crtc_state)
2082379bc100SJani Nikula {
20837801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
20847801f3b7SLucas De Marchi 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
20855b6a9ba9SVille Syrjälä 	enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
20863b51be4eSClinton A Taylor 	u32 ln0, ln1, pin_assignment;
20873b51be4eSClinton A Taylor 	u8 width;
2088379bc100SJani Nikula 
20895b6a9ba9SVille Syrjälä 	if (!intel_phy_is_tc(dev_priv, phy) ||
209011a89708SImre Deak 	    intel_tc_port_in_tbt_alt_mode(dig_port))
2091379bc100SJani Nikula 		return;
2092379bc100SJani Nikula 
2093005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2094b8ed5533SImre Deak 		ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0));
2095b8ed5533SImre Deak 		ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1));
2096978c3e53SClinton A Taylor 	} else {
2097f7960e7fSJani Nikula 		ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port));
2098f7960e7fSJani Nikula 		ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
2099978c3e53SClinton A Taylor 	}
2100379bc100SJani Nikula 
21014f72a8eeSKhaled Almahallawy 	ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2102379bc100SJani Nikula 	ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2103379bc100SJani Nikula 
21043b51be4eSClinton A Taylor 	/* DPPATC */
21057801f3b7SLucas De Marchi 	pin_assignment = intel_tc_port_get_pin_assignment_mask(dig_port);
21063b51be4eSClinton A Taylor 	width = crtc_state->lane_count;
2107379bc100SJani Nikula 
21083b51be4eSClinton A Taylor 	switch (pin_assignment) {
21093b51be4eSClinton A Taylor 	case 0x0:
21101de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm,
211111a89708SImre Deak 			    !intel_tc_port_in_legacy_mode(dig_port));
21123b51be4eSClinton A Taylor 		if (width == 1) {
2113379bc100SJani Nikula 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21143b51be4eSClinton A Taylor 		} else {
21153b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21163b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
2117379bc100SJani Nikula 		}
2118379bc100SJani Nikula 		break;
21193b51be4eSClinton A Taylor 	case 0x1:
21203b51be4eSClinton A Taylor 		if (width == 4) {
21213b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21223b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21233b51be4eSClinton A Taylor 		}
2124379bc100SJani Nikula 		break;
21253b51be4eSClinton A Taylor 	case 0x2:
21263b51be4eSClinton A Taylor 		if (width == 2) {
21273b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21283b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21293b51be4eSClinton A Taylor 		}
21303b51be4eSClinton A Taylor 		break;
21313b51be4eSClinton A Taylor 	case 0x3:
21323b51be4eSClinton A Taylor 	case 0x5:
21333b51be4eSClinton A Taylor 		if (width == 1) {
21343b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21353b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21363b51be4eSClinton A Taylor 		} else {
21373b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21383b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21393b51be4eSClinton A Taylor 		}
21403b51be4eSClinton A Taylor 		break;
21413b51be4eSClinton A Taylor 	case 0x4:
21423b51be4eSClinton A Taylor 	case 0x6:
21433b51be4eSClinton A Taylor 		if (width == 1) {
21443b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21453b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21463b51be4eSClinton A Taylor 		} else {
21473b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21483b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21493b51be4eSClinton A Taylor 		}
21503b51be4eSClinton A Taylor 		break;
2151379bc100SJani Nikula 	default:
21523b51be4eSClinton A Taylor 		MISSING_CASE(pin_assignment);
2153379bc100SJani Nikula 	}
2154379bc100SJani Nikula 
2155005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2156b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0);
2157b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1);
2158978c3e53SClinton A Taylor 	} else {
2159f7960e7fSJani Nikula 		intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0);
2160f7960e7fSJani Nikula 		intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1);
2161379bc100SJani Nikula 	}
2162978c3e53SClinton A Taylor }
2163379bc100SJani Nikula 
2164ef79fafeSVille Syrjälä static enum transcoder
2165ef79fafeSVille Syrjälä tgl_dp_tp_transcoder(const struct intel_crtc_state *crtc_state)
2166ef79fafeSVille Syrjälä {
2167ef79fafeSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
2168ef79fafeSVille Syrjälä 		return crtc_state->mst_master_transcoder;
2169ef79fafeSVille Syrjälä 	else
2170ef79fafeSVille Syrjälä 		return crtc_state->cpu_transcoder;
2171ef79fafeSVille Syrjälä }
2172ef79fafeSVille Syrjälä 
2173ef79fafeSVille Syrjälä i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
2174ef79fafeSVille Syrjälä 			 const struct intel_crtc_state *crtc_state)
2175ef79fafeSVille Syrjälä {
2176ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2177ef79fafeSVille Syrjälä 
2178005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
2179ef79fafeSVille Syrjälä 		return TGL_DP_TP_CTL(tgl_dp_tp_transcoder(crtc_state));
2180ef79fafeSVille Syrjälä 	else
2181ef79fafeSVille Syrjälä 		return DP_TP_CTL(encoder->port);
2182ef79fafeSVille Syrjälä }
2183ef79fafeSVille Syrjälä 
2184ef79fafeSVille Syrjälä i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
2185ef79fafeSVille Syrjälä 			    const struct intel_crtc_state *crtc_state)
2186ef79fafeSVille Syrjälä {
2187ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2188ef79fafeSVille Syrjälä 
2189005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
2190ef79fafeSVille Syrjälä 		return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state));
2191ef79fafeSVille Syrjälä 	else
2192ef79fafeSVille Syrjälä 		return DP_TP_STATUS(encoder->port);
2193ef79fafeSVille Syrjälä }
2194ef79fafeSVille Syrjälä 
21951639406aSManasi Navare static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
21961639406aSManasi Navare 							  const struct intel_crtc_state *crtc_state,
21971639406aSManasi Navare 							  bool enable)
21981639406aSManasi Navare {
21991639406aSManasi Navare 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
22001639406aSManasi Navare 
22011639406aSManasi Navare 	if (!crtc_state->vrr.enable)
22021639406aSManasi Navare 		return;
22031639406aSManasi Navare 
22041639406aSManasi Navare 	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL,
22051639406aSManasi Navare 			       enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
22061639406aSManasi Navare 		drm_dbg_kms(&i915->drm,
22070868b1ceSVille Syrjälä 			    "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
2208707c3a7dSLucas De Marchi 			    str_enable_disable(enable));
22091639406aSManasi Navare }
22101639406aSManasi Navare 
2211379bc100SJani Nikula static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
2212379bc100SJani Nikula 					const struct intel_crtc_state *crtc_state)
2213379bc100SJani Nikula {
221447bdb1caSJani Nikula 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
221547bdb1caSJani Nikula 
2216379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2217379bc100SJani Nikula 		return;
2218379bc100SJani Nikula 
2219379bc100SJani Nikula 	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION, DP_FEC_READY) <= 0)
222047bdb1caSJani Nikula 		drm_dbg_kms(&i915->drm,
222147bdb1caSJani Nikula 			    "Failed to set FEC_READY in the sink\n");
2222379bc100SJani Nikula }
2223379bc100SJani Nikula 
2224379bc100SJani Nikula static void intel_ddi_enable_fec(struct intel_encoder *encoder,
2225379bc100SJani Nikula 				 const struct intel_crtc_state *crtc_state)
2226379bc100SJani Nikula {
2227379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2228379bc100SJani Nikula 
2229379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2230379bc100SJani Nikula 		return;
2231379bc100SJani Nikula 
22328910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
22338910d8b7SAndrzej Hajda 		     0, DP_TP_CTL_FEC_ENABLE);
2234379bc100SJani Nikula }
2235379bc100SJani Nikula 
2236379bc100SJani Nikula static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
2237379bc100SJani Nikula 					const struct intel_crtc_state *crtc_state)
2238379bc100SJani Nikula {
2239379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2240379bc100SJani Nikula 
2241379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2242379bc100SJani Nikula 		return;
2243379bc100SJani Nikula 
22448910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
22458910d8b7SAndrzej Hajda 		     DP_TP_CTL_FEC_ENABLE, 0);
2246ef79fafeSVille Syrjälä 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
2247379bc100SJani Nikula }
2248379bc100SJani Nikula 
22495cdf706fSVille Syrjälä static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
22505cdf706fSVille Syrjälä 				     const struct intel_crtc_state *crtc_state)
22515cdf706fSVille Syrjälä {
22525cdf706fSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
22535cdf706fSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
22545cdf706fSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
22555cdf706fSVille Syrjälä 
22565cdf706fSVille Syrjälä 	if (intel_phy_is_combo(i915, phy)) {
22575cdf706fSVille Syrjälä 		bool lane_reversal =
22585cdf706fSVille Syrjälä 			dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
22595cdf706fSVille Syrjälä 
22605cdf706fSVille Syrjälä 		intel_combo_phy_power_up_lanes(i915, phy, false,
22615cdf706fSVille Syrjälä 					       crtc_state->lane_count,
22625cdf706fSVille Syrjälä 					       lane_reversal);
22635cdf706fSVille Syrjälä 	}
22645cdf706fSVille Syrjälä }
22655cdf706fSVille Syrjälä 
2266f6864b27SJani Nikula /* Splitter enable for eDP MSO is limited to certain pipes. */
2267f6864b27SJani Nikula static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915)
2268f6864b27SJani Nikula {
2269f6864b27SJani Nikula 	if (IS_ALDERLAKE_P(i915))
2270f6864b27SJani Nikula 		return BIT(PIPE_A) | BIT(PIPE_B);
2271f6864b27SJani Nikula 	else
2272f6864b27SJani Nikula 		return BIT(PIPE_A);
2273f6864b27SJani Nikula }
2274f6864b27SJani Nikula 
22755b616a29SJani Nikula static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
22765b616a29SJani Nikula 				     struct intel_crtc_state *pipe_config)
22775b616a29SJani Nikula {
22785b616a29SJani Nikula 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
22795b616a29SJani Nikula 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
22805b616a29SJani Nikula 	enum pipe pipe = crtc->pipe;
22815b616a29SJani Nikula 	u32 dss1;
22825b616a29SJani Nikula 
22835b616a29SJani Nikula 	if (!HAS_MSO(i915))
22845b616a29SJani Nikula 		return;
22855b616a29SJani Nikula 
22865b616a29SJani Nikula 	dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe));
22875b616a29SJani Nikula 
22885b616a29SJani Nikula 	pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE;
22895b616a29SJani Nikula 	if (!pipe_config->splitter.enable)
22905b616a29SJani Nikula 		return;
22915b616a29SJani Nikula 
2292f6864b27SJani Nikula 	if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) {
22935b616a29SJani Nikula 		pipe_config->splitter.enable = false;
22945b616a29SJani Nikula 		return;
22955b616a29SJani Nikula 	}
22965b616a29SJani Nikula 
22975b616a29SJani Nikula 	switch (dss1 & SPLITTER_CONFIGURATION_MASK) {
22985b616a29SJani Nikula 	default:
22995b616a29SJani Nikula 		drm_WARN(&i915->drm, true,
23005b616a29SJani Nikula 			 "Invalid splitter configuration, dss1=0x%08x\n", dss1);
23015b616a29SJani Nikula 		fallthrough;
23025b616a29SJani Nikula 	case SPLITTER_CONFIGURATION_2_SEGMENT:
23035b616a29SJani Nikula 		pipe_config->splitter.link_count = 2;
23045b616a29SJani Nikula 		break;
23055b616a29SJani Nikula 	case SPLITTER_CONFIGURATION_4_SEGMENT:
23065b616a29SJani Nikula 		pipe_config->splitter.link_count = 4;
23075b616a29SJani Nikula 		break;
23085b616a29SJani Nikula 	}
23095b616a29SJani Nikula 
23105b616a29SJani Nikula 	pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1);
23115b616a29SJani Nikula }
23125b616a29SJani Nikula 
2313bc71194eSJani Nikula static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
2314bc71194eSJani Nikula {
2315bc71194eSJani Nikula 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2316bc71194eSJani Nikula 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2317bc71194eSJani Nikula 	enum pipe pipe = crtc->pipe;
2318bc71194eSJani Nikula 	u32 dss1 = 0;
2319bc71194eSJani Nikula 
2320bc71194eSJani Nikula 	if (!HAS_MSO(i915))
2321bc71194eSJani Nikula 		return;
2322bc71194eSJani Nikula 
2323bc71194eSJani Nikula 	if (crtc_state->splitter.enable) {
2324bc71194eSJani Nikula 		dss1 |= SPLITTER_ENABLE;
2325bc71194eSJani Nikula 		dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
2326bc71194eSJani Nikula 		if (crtc_state->splitter.link_count == 2)
2327bc71194eSJani Nikula 			dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT;
2328bc71194eSJani Nikula 		else
2329bc71194eSJani Nikula 			dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT;
2330bc71194eSJani Nikula 	}
2331bc71194eSJani Nikula 
2332bc71194eSJani Nikula 	intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe),
2333bc71194eSJani Nikula 		     SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK |
2334bc71194eSJani Nikula 		     OVERLAP_PIXELS_MASK, dss1);
2335bc71194eSJani Nikula }
2336bc71194eSJani Nikula 
233723ef6194SJosé Roberto de Souza static u8 mtl_get_port_width(u8 lane_count)
233823ef6194SJosé Roberto de Souza {
233923ef6194SJosé Roberto de Souza 	switch (lane_count) {
234023ef6194SJosé Roberto de Souza 	case 1:
234123ef6194SJosé Roberto de Souza 		return 0;
234223ef6194SJosé Roberto de Souza 	case 2:
234323ef6194SJosé Roberto de Souza 		return 1;
234423ef6194SJosé Roberto de Souza 	case 3:
234523ef6194SJosé Roberto de Souza 		return 4;
234623ef6194SJosé Roberto de Souza 	case 4:
234723ef6194SJosé Roberto de Souza 		return 3;
234823ef6194SJosé Roberto de Souza 	default:
234923ef6194SJosé Roberto de Souza 		MISSING_CASE(lane_count);
235023ef6194SJosé Roberto de Souza 		return 4;
235123ef6194SJosé Roberto de Souza 	}
235223ef6194SJosé Roberto de Souza }
235323ef6194SJosé Roberto de Souza 
235423ef6194SJosé Roberto de Souza static void
235523ef6194SJosé Roberto de Souza mtl_ddi_enable_d2d(struct intel_encoder *encoder)
235623ef6194SJosé Roberto de Souza {
235723ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
235823ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
235923ef6194SJosé Roberto de Souza 
236023ef6194SJosé Roberto de Souza 	intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port), 0,
236123ef6194SJosé Roberto de Souza 		     XELPDP_PORT_BUF_D2D_LINK_ENABLE);
236223ef6194SJosé Roberto de Souza 
236323ef6194SJosé Roberto de Souza 	if (wait_for_us((intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) &
236423ef6194SJosé Roberto de Souza 			 XELPDP_PORT_BUF_D2D_LINK_STATE), 100)) {
236523ef6194SJosé Roberto de Souza 		drm_err(&dev_priv->drm, "Timeout waiting for D2D Link enable for PORT_BUF_CTL %c\n",
236623ef6194SJosé Roberto de Souza 			port_name(port));
236723ef6194SJosé Roberto de Souza 	}
236823ef6194SJosé Roberto de Souza }
236923ef6194SJosé Roberto de Souza 
237023ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_program(struct intel_encoder *encoder,
237123ef6194SJosé Roberto de Souza 				     const struct intel_crtc_state *crtc_state)
237223ef6194SJosé Roberto de Souza {
237323ef6194SJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
237423ef6194SJosé Roberto de Souza 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
237523ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
237623ef6194SJosé Roberto de Souza 	u32 val;
237723ef6194SJosé Roberto de Souza 
237823ef6194SJosé Roberto de Souza 	val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(port));
237923ef6194SJosé Roberto de Souza 	val &= ~XELPDP_PORT_WIDTH_MASK;
238023ef6194SJosé Roberto de Souza 	val |= XELPDP_PORT_WIDTH(mtl_get_port_width(crtc_state->lane_count));
238123ef6194SJosé Roberto de Souza 
238223ef6194SJosé Roberto de Souza 	val &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK;
238323ef6194SJosé Roberto de Souza 	if (intel_dp_is_uhbr(crtc_state))
238423ef6194SJosé Roberto de Souza 		val |= XELPDP_PORT_BUF_PORT_DATA_40BIT;
238523ef6194SJosé Roberto de Souza 	else
238623ef6194SJosé Roberto de Souza 		val |= XELPDP_PORT_BUF_PORT_DATA_10BIT;
238723ef6194SJosé Roberto de Souza 
238823ef6194SJosé Roberto de Souza 	if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
238923ef6194SJosé Roberto de Souza 		val |= XELPDP_PORT_REVERSAL;
239023ef6194SJosé Roberto de Souza 
239123ef6194SJosé Roberto de Souza 	intel_de_write(i915, XELPDP_PORT_BUF_CTL1(port), val);
239223ef6194SJosé Roberto de Souza }
239323ef6194SJosé Roberto de Souza 
239423ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_io_selection(struct intel_encoder *encoder)
239523ef6194SJosé Roberto de Souza {
239623ef6194SJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
239723ef6194SJosé Roberto de Souza 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
239823ef6194SJosé Roberto de Souza 	u32 val;
239923ef6194SJosé Roberto de Souza 
240023ef6194SJosé Roberto de Souza 	val = intel_tc_port_in_tbt_alt_mode(dig_port) ?
240123ef6194SJosé Roberto de Souza 	      XELPDP_PORT_BUF_IO_SELECT_TBT : 0;
240223ef6194SJosé Roberto de Souza 	intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(encoder->port),
240323ef6194SJosé Roberto de Souza 		     XELPDP_PORT_BUF_IO_SELECT_TBT, val);
240423ef6194SJosé Roberto de Souza }
240523ef6194SJosé Roberto de Souza 
240623ef6194SJosé Roberto de Souza static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
240723ef6194SJosé Roberto de Souza 				  struct intel_encoder *encoder,
240823ef6194SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state,
240923ef6194SJosé Roberto de Souza 				  const struct drm_connector_state *conn_state)
241023ef6194SJosé Roberto de Souza {
241123ef6194SJosé Roberto de Souza 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
241223ef6194SJosé Roberto de Souza 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
241323ef6194SJosé Roberto de Souza 
241423ef6194SJosé Roberto de Souza 	intel_dp_set_link_params(intel_dp,
241523ef6194SJosé Roberto de Souza 				 crtc_state->port_clock,
241623ef6194SJosé Roberto de Souza 				 crtc_state->lane_count);
241723ef6194SJosé Roberto de Souza 
241823ef6194SJosé Roberto de Souza 	/*
241923ef6194SJosé Roberto de Souza 	 * We only configure what the register value will be here.  Actual
242023ef6194SJosé Roberto de Souza 	 * enabling happens during link training farther down.
242123ef6194SJosé Roberto de Souza 	 */
242223ef6194SJosé Roberto de Souza 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
242323ef6194SJosé Roberto de Souza 
242423ef6194SJosé Roberto de Souza 	/*
242523ef6194SJosé Roberto de Souza 	 * 1. Enable Power Wells
242623ef6194SJosé Roberto de Souza 	 *
242723ef6194SJosé Roberto de Souza 	 * This was handled at the beginning of intel_atomic_commit_tail(),
242823ef6194SJosé Roberto de Souza 	 * before we called down into this function.
242923ef6194SJosé Roberto de Souza 	 */
243023ef6194SJosé Roberto de Souza 
243123ef6194SJosé Roberto de Souza 	/* 2. PMdemand was already set */
243223ef6194SJosé Roberto de Souza 
243323ef6194SJosé Roberto de Souza 	/* 3. Select Thunderbolt */
243423ef6194SJosé Roberto de Souza 	mtl_port_buf_ctl_io_selection(encoder);
243523ef6194SJosé Roberto de Souza 
243623ef6194SJosé Roberto de Souza 	/* 4. Enable Panel Power if PPS is required */
243723ef6194SJosé Roberto de Souza 	intel_pps_on(intel_dp);
243823ef6194SJosé Roberto de Souza 
243923ef6194SJosé Roberto de Souza 	/* 5. Enable the port PLL */
244023ef6194SJosé Roberto de Souza 	intel_ddi_enable_clock(encoder, crtc_state);
244123ef6194SJosé Roberto de Souza 
244223ef6194SJosé Roberto de Souza 	/*
244323ef6194SJosé Roberto de Souza 	 * 6.a Configure Transcoder Clock Select to direct the Port clock to the
244423ef6194SJosé Roberto de Souza 	 * Transcoder.
244523ef6194SJosé Roberto de Souza 	 */
244623ef6194SJosé Roberto de Souza 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
244723ef6194SJosé Roberto de Souza 
244823ef6194SJosé Roberto de Souza 	/*
244923ef6194SJosé Roberto de Souza 	 * 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings.
245023ef6194SJosé Roberto de Souza 	 */
245123ef6194SJosé Roberto de Souza 	intel_ddi_config_transcoder_dp2(encoder, crtc_state);
245223ef6194SJosé Roberto de Souza 
245323ef6194SJosé Roberto de Souza 	/*
245423ef6194SJosé Roberto de Souza 	 * 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
245523ef6194SJosé Roberto de Souza 	 * Transport Select
245623ef6194SJosé Roberto de Souza 	 */
245723ef6194SJosé Roberto de Souza 	intel_ddi_config_transcoder_func(encoder, crtc_state);
245823ef6194SJosé Roberto de Souza 
245923ef6194SJosé Roberto de Souza 	/*
246023ef6194SJosé Roberto de Souza 	 * 6.e Program CoG/MSO configuration bits in DSS_CTL1 if selected.
246123ef6194SJosé Roberto de Souza 	 */
246223ef6194SJosé Roberto de Souza 	intel_ddi_mso_configure(crtc_state);
246323ef6194SJosé Roberto de Souza 
246423ef6194SJosé Roberto de Souza 	if (!is_mst)
246523ef6194SJosé Roberto de Souza 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
246623ef6194SJosé Roberto de Souza 
246723ef6194SJosé Roberto de Souza 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
246823ef6194SJosé Roberto de Souza 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
246923ef6194SJosé Roberto de Souza 	/*
247023ef6194SJosé Roberto de Souza 	 * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
247123ef6194SJosé Roberto de Souza 	 * in the FEC_CONFIGURATION register to 1 before initiating link
247223ef6194SJosé Roberto de Souza 	 * training
247323ef6194SJosé Roberto de Souza 	 */
247423ef6194SJosé Roberto de Souza 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
247523ef6194SJosé Roberto de Souza 
247623ef6194SJosé Roberto de Souza 	intel_dp_check_frl_training(intel_dp);
247723ef6194SJosé Roberto de Souza 	intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
247823ef6194SJosé Roberto de Souza 
247923ef6194SJosé Roberto de Souza 	/*
248023ef6194SJosé Roberto de Souza 	 * 6. The rest of the below are substeps under the bspec's "Enable and
248123ef6194SJosé Roberto de Souza 	 * Train Display Port" step.  Note that steps that are specific to
248223ef6194SJosé Roberto de Souza 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
248323ef6194SJosé Roberto de Souza 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
248423ef6194SJosé Roberto de Souza 	 * us when active_mst_links==0, so any steps designated for "single
248523ef6194SJosé Roberto de Souza 	 * stream or multi-stream master transcoder" can just be performed
248623ef6194SJosé Roberto de Souza 	 * unconditionally here.
248723ef6194SJosé Roberto de Souza 	 *
248823ef6194SJosé Roberto de Souza 	 * mtl_ddi_prepare_link_retrain() that is called by
248923ef6194SJosé Roberto de Souza 	 * intel_dp_start_link_train() will execute steps: 6.d, 6.f, 6.g, 6.h,
249023ef6194SJosé Roberto de Souza 	 * 6.i and 6.j
249123ef6194SJosé Roberto de Souza 	 *
249223ef6194SJosé Roberto de Souza 	 * 6.k Follow DisplayPort specification training sequence (see notes for
249323ef6194SJosé Roberto de Souza 	 *     failure handling)
249423ef6194SJosé Roberto de Souza 	 * 6.m If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
249523ef6194SJosé Roberto de Souza 	 *     Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
249623ef6194SJosé Roberto de Souza 	 *     (timeout after 800 us)
249723ef6194SJosé Roberto de Souza 	 */
249823ef6194SJosé Roberto de Souza 	intel_dp_start_link_train(intel_dp, crtc_state);
249923ef6194SJosé Roberto de Souza 
250023ef6194SJosé Roberto de Souza 	/* 6.n Set DP_TP_CTL link training to Normal */
250123ef6194SJosé Roberto de Souza 	if (!is_trans_port_sync_mode(crtc_state))
250223ef6194SJosé Roberto de Souza 		intel_dp_stop_link_train(intel_dp, crtc_state);
250323ef6194SJosé Roberto de Souza 
250423ef6194SJosé Roberto de Souza 	/* 6.o Configure and enable FEC if needed */
250523ef6194SJosé Roberto de Souza 	intel_ddi_enable_fec(encoder, crtc_state);
250623ef6194SJosé Roberto de Souza 
250723ef6194SJosé Roberto de Souza 	intel_dsc_dp_pps_write(encoder, crtc_state);
250823ef6194SJosé Roberto de Souza }
250923ef6194SJosé Roberto de Souza 
2510ede9771dSVille Syrjälä static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
2511ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
251299389390SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state,
251399389390SJosé Roberto de Souza 				  const struct drm_connector_state *conn_state)
251499389390SJosé Roberto de Souza {
2515b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
251699389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2517b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
251899389390SJosé Roberto de Souza 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
251999389390SJosé Roberto de Souza 
2520a621860aSVille Syrjälä 	intel_dp_set_link_params(intel_dp,
2521a621860aSVille Syrjälä 				 crtc_state->port_clock,
2522a621860aSVille Syrjälä 				 crtc_state->lane_count);
252399389390SJosé Roberto de Souza 
25245e19c0b0SMatt Roper 	/*
25259f620f1dSVille Syrjälä 	 * We only configure what the register value will be here.  Actual
25269f620f1dSVille Syrjälä 	 * enabling happens during link training farther down.
25279f620f1dSVille Syrjälä 	 */
25289f620f1dSVille Syrjälä 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
25299f620f1dSVille Syrjälä 
25309f620f1dSVille Syrjälä 	/*
25315e19c0b0SMatt Roper 	 * 1. Enable Power Wells
25325e19c0b0SMatt Roper 	 *
25335e19c0b0SMatt Roper 	 * This was handled at the beginning of intel_atomic_commit_tail(),
25345e19c0b0SMatt Roper 	 * before we called down into this function.
25355e19c0b0SMatt Roper 	 */
253699389390SJosé Roberto de Souza 
25375e19c0b0SMatt Roper 	/* 2. Enable Panel Power if PPS is required */
2538eb46f498SJani Nikula 	intel_pps_on(intel_dp);
253999389390SJosé Roberto de Souza 
254099389390SJosé Roberto de Souza 	/*
25415e19c0b0SMatt Roper 	 * 3. For non-TBT Type-C ports, set FIA lane count
25425e19c0b0SMatt Roper 	 * (DFLEXDPSP.DPX4TXLATC)
25435e19c0b0SMatt Roper 	 *
25445e19c0b0SMatt Roper 	 * This was done before tgl_ddi_pre_enable_dp by
25451e98f88cSLucas De Marchi 	 * hsw_crtc_enable()->intel_encoders_pre_pll_enable().
254699389390SJosé Roberto de Souza 	 */
254799389390SJosé Roberto de Souza 
25485e19c0b0SMatt Roper 	/*
25495e19c0b0SMatt Roper 	 * 4. Enable the port PLL.
25505e19c0b0SMatt Roper 	 *
25515e19c0b0SMatt Roper 	 * The PLL enabling itself was already done before this function by
25521e98f88cSLucas De Marchi 	 * hsw_crtc_enable()->intel_enable_shared_dpll().  We need only
25535e19c0b0SMatt Roper 	 * configure the PLL to port mapping here.
25545e19c0b0SMatt Roper 	 */
2555c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
25566171e58bSClinton A Taylor 
25575e19c0b0SMatt Roper 	/* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */
255811a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2559a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2560a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
256199389390SJosé Roberto de Souza 								   dig_port->ddi_io_power_domain);
2562a4550977SImre Deak 	}
256399389390SJosé Roberto de Souza 
25645e19c0b0SMatt Roper 	/* 6. Program DP_MODE */
25653b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
256699389390SJosé Roberto de Souza 
256799389390SJosé Roberto de Souza 	/*
25685e19c0b0SMatt Roper 	 * 7. The rest of the below are substeps under the bspec's "Enable and
25695e19c0b0SMatt Roper 	 * Train Display Port" step.  Note that steps that are specific to
25705e19c0b0SMatt Roper 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
25715e19c0b0SMatt Roper 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
25725e19c0b0SMatt Roper 	 * us when active_mst_links==0, so any steps designated for "single
25735e19c0b0SMatt Roper 	 * stream or multi-stream master transcoder" can just be performed
25745e19c0b0SMatt Roper 	 * unconditionally here.
25755e19c0b0SMatt Roper 	 */
25765e19c0b0SMatt Roper 
25775e19c0b0SMatt Roper 	/*
25785e19c0b0SMatt Roper 	 * 7.a Configure Transcoder Clock Select to direct the Port clock to the
25795e19c0b0SMatt Roper 	 * Transcoder.
258099389390SJosé Roberto de Souza 	 */
258155a4679eSVille Syrjälä 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
258299389390SJosé Roberto de Souza 
2583fe6959a6SVille Syrjälä 	if (HAS_DP20(dev_priv))
2584fe6959a6SVille Syrjälä 		intel_ddi_config_transcoder_dp2(encoder, crtc_state);
2585fe6959a6SVille Syrjälä 
25865e19c0b0SMatt Roper 	/*
25875e19c0b0SMatt Roper 	 * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
25885e19c0b0SMatt Roper 	 * Transport Select
25895e19c0b0SMatt Roper 	 */
2590eed22a46SVille Syrjälä 	intel_ddi_config_transcoder_func(encoder, crtc_state);
259199389390SJosé Roberto de Souza 
25925e19c0b0SMatt Roper 	/*
25935e19c0b0SMatt Roper 	 * 7.c Configure & enable DP_TP_CTL with link training pattern 1
25945e19c0b0SMatt Roper 	 * selected
25955e19c0b0SMatt Roper 	 *
25965e19c0b0SMatt Roper 	 * This will be handled by the intel_dp_start_link_train() farther
25975e19c0b0SMatt Roper 	 * down this function.
25985e19c0b0SMatt Roper 	 */
25995e19c0b0SMatt Roper 
26005e19c0b0SMatt Roper 	/* 7.e Configure voltage swing and related IO settings */
2601e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
260299389390SJosé Roberto de Souza 
26035e19c0b0SMatt Roper 	/*
26045e19c0b0SMatt Roper 	 * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up
26055e19c0b0SMatt Roper 	 * the used lanes of the DDI.
26065e19c0b0SMatt Roper 	 */
26075cdf706fSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
260899389390SJosé Roberto de Souza 
26095e19c0b0SMatt Roper 	/*
2610bc71194eSJani Nikula 	 * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected.
2611bc71194eSJani Nikula 	 */
2612bc71194eSJani Nikula 	intel_ddi_mso_configure(crtc_state);
2613bc71194eSJani Nikula 
261499389390SJosé Roberto de Souza 	if (!is_mst)
26150e634efdSVille Syrjälä 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
261699389390SJosé Roberto de Souza 
2617522508b6SAnkit Nautiyal 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
261899389390SJosé Roberto de Souza 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
261999389390SJosé Roberto de Souza 	/*
262099389390SJosé Roberto de Souza 	 * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
262199389390SJosé Roberto de Souza 	 * in the FEC_CONFIGURATION register to 1 before initiating link
262299389390SJosé Roberto de Souza 	 * training
262399389390SJosé Roberto de Souza 	 */
262499389390SJosé Roberto de Souza 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
26255e19c0b0SMatt Roper 
26264f3dd47aSAnkit Nautiyal 	intel_dp_check_frl_training(intel_dp);
262710fec80bSAnkit Nautiyal 	intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
26284f3dd47aSAnkit Nautiyal 
26295e19c0b0SMatt Roper 	/*
26305e19c0b0SMatt Roper 	 * 7.i Follow DisplayPort specification training sequence (see notes for
26315e19c0b0SMatt Roper 	 *     failure handling)
26325e19c0b0SMatt Roper 	 * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
26335e19c0b0SMatt Roper 	 *     Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
26345e19c0b0SMatt Roper 	 *     (timeout after 800 us)
26355e19c0b0SMatt Roper 	 */
2636a621860aSVille Syrjälä 	intel_dp_start_link_train(intel_dp, crtc_state);
263799389390SJosé Roberto de Souza 
26385e19c0b0SMatt Roper 	/* 7.k Set DP_TP_CTL link training to Normal */
2639eadf6f91SManasi Navare 	if (!is_trans_port_sync_mode(crtc_state))
2640a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
264199389390SJosé Roberto de Souza 
26425e19c0b0SMatt Roper 	/* 7.l Configure and enable FEC if needed */
264399389390SJosé Roberto de Souza 	intel_ddi_enable_fec(encoder, crtc_state);
26443126977dSVille Syrjälä 
26453126977dSVille Syrjälä 	intel_dsc_dp_pps_write(encoder, crtc_state);
264699389390SJosé Roberto de Souza }
264799389390SJosé Roberto de Souza 
2648ede9771dSVille Syrjälä static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
2649ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
2650379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state,
2651379bc100SJani Nikula 				  const struct drm_connector_state *conn_state)
2652379bc100SJani Nikula {
2653b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2654379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2655379bc100SJani Nikula 	enum port port = encoder->port;
2656b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2657379bc100SJani Nikula 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
2658379bc100SJani Nikula 
2659005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) < 11)
26601de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm,
26611de143ccSPankaj Bharadiya 			    is_mst && (port == PORT_A || port == PORT_E));
2662542dfab5SJosé Roberto de Souza 	else
26631de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm, is_mst && port == PORT_A);
2664379bc100SJani Nikula 
2665a621860aSVille Syrjälä 	intel_dp_set_link_params(intel_dp,
2666a621860aSVille Syrjälä 				 crtc_state->port_clock,
2667a621860aSVille Syrjälä 				 crtc_state->lane_count);
2668379bc100SJani Nikula 
26699f620f1dSVille Syrjälä 	/*
26709f620f1dSVille Syrjälä 	 * We only configure what the register value will be here.  Actual
26719f620f1dSVille Syrjälä 	 * enabling happens during link training farther down.
26729f620f1dSVille Syrjälä 	 */
26739f620f1dSVille Syrjälä 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
26749f620f1dSVille Syrjälä 
2675eb46f498SJani Nikula 	intel_pps_on(intel_dp);
2676379bc100SJani Nikula 
2677c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
2678379bc100SJani Nikula 
267911a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2680a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2681a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
26823b2ed431SImre Deak 								   dig_port->ddi_io_power_domain);
2683a4550977SImre Deak 	}
2684379bc100SJani Nikula 
26853b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
2686379bc100SJani Nikula 
26875bafd85dSVille Syrjälä 	if (has_buf_trans_select(dev_priv))
2688266152aeSVille Syrjälä 		hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
2689379bc100SJani Nikula 
2690e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
2691e722ab8bSVille Syrjälä 
26925cdf706fSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
2693379bc100SJani Nikula 
2694379bc100SJani Nikula 	if (!is_mst)
26950e634efdSVille Syrjälä 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
2696522508b6SAnkit Nautiyal 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
2697379bc100SJani Nikula 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
2698379bc100SJani Nikula 					      true);
2699379bc100SJani Nikula 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
2700a621860aSVille Syrjälä 	intel_dp_start_link_train(intel_dp, crtc_state);
2701005e9537SMatt Roper 	if ((port != PORT_A || DISPLAY_VER(dev_priv) >= 9) &&
2702eadf6f91SManasi Navare 	    !is_trans_port_sync_mode(crtc_state))
2703a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
2704379bc100SJani Nikula 
2705379bc100SJani Nikula 	intel_ddi_enable_fec(encoder, crtc_state);
2706379bc100SJani Nikula 
2707379bc100SJani Nikula 	if (!is_mst)
270855a4679eSVille Syrjälä 		intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2709379bc100SJani Nikula 
27103126977dSVille Syrjälä 	intel_dsc_dp_pps_write(encoder, crtc_state);
2711379bc100SJani Nikula }
2712379bc100SJani Nikula 
2713ede9771dSVille Syrjälä static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
2714ede9771dSVille Syrjälä 				    struct intel_encoder *encoder,
271599389390SJosé Roberto de Souza 				    const struct intel_crtc_state *crtc_state,
271699389390SJosé Roberto de Souza 				    const struct drm_connector_state *conn_state)
271799389390SJosé Roberto de Souza {
271899389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
271999389390SJosé Roberto de Souza 
27201a324a40SArun R Murthy 	if (HAS_DP20(dev_priv))
27211a324a40SArun R Murthy 		intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
27221a324a40SArun R Murthy 					    crtc_state);
27231a324a40SArun R Murthy 
272423ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14)
272523ef6194SJosé Roberto de Souza 		mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
272623ef6194SJosé Roberto de Souza 	else if (DISPLAY_VER(dev_priv) >= 12)
2727ede9771dSVille Syrjälä 		tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
272899389390SJosé Roberto de Souza 	else
2729ede9771dSVille Syrjälä 		hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
27300c06fa15SGwan-gyeong Mun 
2731bd8c9ccaSGwan-gyeong Mun 	/* MST will call a setting of MSA after an allocating of Virtual Channel
2732bd8c9ccaSGwan-gyeong Mun 	 * from MST encoder pre_enable callback.
2733bd8c9ccaSGwan-gyeong Mun 	 */
27348de5df3bSVille Syrjälä 	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
27350c06fa15SGwan-gyeong Mun 		intel_ddi_set_dp_msa(crtc_state, conn_state);
27361fc1e8d4SJosé Roberto de Souza }
273799389390SJosé Roberto de Souza 
2738ede9771dSVille Syrjälä static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
2739ede9771dSVille Syrjälä 				      struct intel_encoder *encoder,
2740379bc100SJani Nikula 				      const struct intel_crtc_state *crtc_state,
2741379bc100SJani Nikula 				      const struct drm_connector_state *conn_state)
2742379bc100SJani Nikula {
27430ba7ffeaSLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
27440ba7ffeaSLucas De Marchi 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
2745379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2746379bc100SJani Nikula 
2747379bc100SJani Nikula 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
2748c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
2749379bc100SJani Nikula 
2750a4550977SImre Deak 	drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2751a4550977SImre Deak 	dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
2752a4550977SImre Deak 							   dig_port->ddi_io_power_domain);
2753379bc100SJani Nikula 
27543b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
2755379bc100SJani Nikula 
275655a4679eSVille Syrjälä 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2757379bc100SJani Nikula 
27580ba7ffeaSLucas De Marchi 	dig_port->set_infoframes(encoder,
2759379bc100SJani Nikula 				 crtc_state->has_infoframe,
2760379bc100SJani Nikula 				 crtc_state, conn_state);
2761379bc100SJani Nikula }
2762379bc100SJani Nikula 
2763ede9771dSVille Syrjälä static void intel_ddi_pre_enable(struct intel_atomic_state *state,
2764ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
2765379bc100SJani Nikula 				 const struct intel_crtc_state *crtc_state,
2766379bc100SJani Nikula 				 const struct drm_connector_state *conn_state)
2767379bc100SJani Nikula {
27682225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2769379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2770379bc100SJani Nikula 	enum pipe pipe = crtc->pipe;
2771379bc100SJani Nikula 
2772379bc100SJani Nikula 	/*
2773379bc100SJani Nikula 	 * When called from DP MST code:
2774379bc100SJani Nikula 	 * - conn_state will be NULL
2775379bc100SJani Nikula 	 * - encoder will be the main encoder (ie. mst->primary)
2776379bc100SJani Nikula 	 * - the main connector associated with this port
2777379bc100SJani Nikula 	 *   won't be active or linked to a crtc
2778379bc100SJani Nikula 	 * - crtc_state will be the state of the first stream to
2779379bc100SJani Nikula 	 *   be activated on this port, and it may not be the same
2780379bc100SJani Nikula 	 *   stream that will be deactivated last, but each stream
2781379bc100SJani Nikula 	 *   should have a state that is identical when it comes to
2782379bc100SJani Nikula 	 *   the DP link parameteres
2783379bc100SJani Nikula 	 */
2784379bc100SJani Nikula 
27851de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
2786379bc100SJani Nikula 
2787379bc100SJani Nikula 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
2788379bc100SJani Nikula 
2789379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
2790ede9771dSVille Syrjälä 		intel_ddi_pre_enable_hdmi(state, encoder, crtc_state,
2791ede9771dSVille Syrjälä 					  conn_state);
2792379bc100SJani Nikula 	} else {
2793f7af425dSVille Syrjälä 		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2794379bc100SJani Nikula 
2795ede9771dSVille Syrjälä 		intel_ddi_pre_enable_dp(state, encoder, crtc_state,
2796ede9771dSVille Syrjälä 					conn_state);
2797379bc100SJani Nikula 
2798f7af425dSVille Syrjälä 		/* FIXME precompute everything properly */
27990ea02bb8SJosé Roberto de Souza 		/* FIXME how do we turn infoframes off again? */
28007ffa2f27SJani Nikula 		if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
2801379bc100SJani Nikula 			dig_port->set_infoframes(encoder,
2802379bc100SJani Nikula 						 crtc_state->has_infoframe,
2803379bc100SJani Nikula 						 crtc_state, conn_state);
2804379bc100SJani Nikula 	}
2805379bc100SJani Nikula }
2806379bc100SJani Nikula 
280723ef6194SJosé Roberto de Souza static void
280823ef6194SJosé Roberto de Souza mtl_ddi_disable_d2d_link(struct intel_encoder *encoder)
280923ef6194SJosé Roberto de Souza {
281023ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
281123ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
281223ef6194SJosé Roberto de Souza 
281323ef6194SJosé Roberto de Souza 	intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port),
281423ef6194SJosé Roberto de Souza 		     XELPDP_PORT_BUF_D2D_LINK_ENABLE, 0);
281523ef6194SJosé Roberto de Souza 
281623ef6194SJosé Roberto de Souza 	if (wait_for_us(!(intel_de_read(dev_priv, XELPDP_PORT_BUF_CTL1(port)) &
281723ef6194SJosé Roberto de Souza 			  XELPDP_PORT_BUF_D2D_LINK_STATE), 100))
281823ef6194SJosé Roberto de Souza 		drm_err(&dev_priv->drm, "Timeout waiting for D2D Link disable for PORT_BUF_CTL %c\n",
281923ef6194SJosé Roberto de Souza 			port_name(port));
282023ef6194SJosé Roberto de Souza }
282123ef6194SJosé Roberto de Souza 
282223ef6194SJosé Roberto de Souza static void mtl_disable_ddi_buf(struct intel_encoder *encoder,
282323ef6194SJosé Roberto de Souza 				const struct intel_crtc_state *crtc_state)
282423ef6194SJosé Roberto de Souza {
282523ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
282623ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
282723ef6194SJosé Roberto de Souza 	u32 val;
282823ef6194SJosé Roberto de Souza 
282923ef6194SJosé Roberto de Souza 	/* 3.b Clear DDI_CTL_DE Enable to 0. */
283023ef6194SJosé Roberto de Souza 	val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
283123ef6194SJosé Roberto de Souza 	if (val & DDI_BUF_CTL_ENABLE) {
283223ef6194SJosé Roberto de Souza 		val &= ~DDI_BUF_CTL_ENABLE;
283323ef6194SJosé Roberto de Souza 		intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
283423ef6194SJosé Roberto de Souza 
283523ef6194SJosé Roberto de Souza 		/* 3.c Poll for PORT_BUF_CTL Idle Status == 1, timeout after 100us */
283623ef6194SJosé Roberto de Souza 		mtl_wait_ddi_buf_idle(dev_priv, port);
283723ef6194SJosé Roberto de Souza 	}
283823ef6194SJosé Roberto de Souza 
283923ef6194SJosé Roberto de Souza 	/* 3.d Disable D2D Link */
284023ef6194SJosé Roberto de Souza 	mtl_ddi_disable_d2d_link(encoder);
284123ef6194SJosé Roberto de Souza 
284223ef6194SJosé Roberto de Souza 	/* 3.e Disable DP_TP_CTL */
284323ef6194SJosé Roberto de Souza 	if (intel_crtc_has_dp_encoder(crtc_state)) {
284423ef6194SJosé Roberto de Souza 		intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
284523ef6194SJosé Roberto de Souza 			     DP_TP_CTL_ENABLE, 0);
284623ef6194SJosé Roberto de Souza 	}
284723ef6194SJosé Roberto de Souza }
284823ef6194SJosé Roberto de Souza 
284923ef6194SJosé Roberto de Souza static void disable_ddi_buf(struct intel_encoder *encoder,
2850379bc100SJani Nikula 			    const struct intel_crtc_state *crtc_state)
2851379bc100SJani Nikula {
2852379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2853379bc100SJani Nikula 	enum port port = encoder->port;
2854379bc100SJani Nikula 	bool wait = false;
2855379bc100SJani Nikula 	u32 val;
2856379bc100SJani Nikula 
2857f7960e7fSJani Nikula 	val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
2858379bc100SJani Nikula 	if (val & DDI_BUF_CTL_ENABLE) {
2859379bc100SJani Nikula 		val &= ~DDI_BUF_CTL_ENABLE;
2860f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
2861379bc100SJani Nikula 		wait = true;
2862379bc100SJani Nikula 	}
2863379bc100SJani Nikula 
28648910d8b7SAndrzej Hajda 	if (intel_crtc_has_dp_encoder(crtc_state))
28658910d8b7SAndrzej Hajda 		intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
28668c042949SVille Syrjälä 			     DP_TP_CTL_ENABLE, 0);
2867379bc100SJani Nikula 
2868379bc100SJani Nikula 	/* Disable FEC in DP Sink */
2869379bc100SJani Nikula 	intel_ddi_disable_fec_state(encoder, crtc_state);
2870379bc100SJani Nikula 
2871379bc100SJani Nikula 	if (wait)
2872379bc100SJani Nikula 		intel_wait_ddi_buf_idle(dev_priv, port);
2873379bc100SJani Nikula }
2874379bc100SJani Nikula 
287523ef6194SJosé Roberto de Souza static void intel_disable_ddi_buf(struct intel_encoder *encoder,
287623ef6194SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state)
287723ef6194SJosé Roberto de Souza {
287823ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
287923ef6194SJosé Roberto de Souza 
288023ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14) {
288123ef6194SJosé Roberto de Souza 		mtl_disable_ddi_buf(encoder, crtc_state);
288223ef6194SJosé Roberto de Souza 
288323ef6194SJosé Roberto de Souza 		/* 3.f Disable DP_TP_CTL FEC Enable if it is needed */
288423ef6194SJosé Roberto de Souza 		intel_ddi_disable_fec_state(encoder, crtc_state);
288523ef6194SJosé Roberto de Souza 	} else {
288623ef6194SJosé Roberto de Souza 		disable_ddi_buf(encoder, crtc_state);
288723ef6194SJosé Roberto de Souza 	}
288823ef6194SJosé Roberto de Souza }
288923ef6194SJosé Roberto de Souza 
2890ede9771dSVille Syrjälä static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
2891ede9771dSVille Syrjälä 				      struct intel_encoder *encoder,
2892379bc100SJani Nikula 				      const struct intel_crtc_state *old_crtc_state,
2893379bc100SJani Nikula 				      const struct drm_connector_state *old_conn_state)
2894379bc100SJani Nikula {
2895379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2896b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2897379bc100SJani Nikula 	struct intel_dp *intel_dp = &dig_port->dp;
289823ef6194SJosé Roberto de Souza 	intel_wakeref_t wakeref;
2899379bc100SJani Nikula 	bool is_mst = intel_crtc_has_type(old_crtc_state,
2900379bc100SJani Nikula 					  INTEL_OUTPUT_DP_MST);
2901379bc100SJani Nikula 
2902c980216dSImre Deak 	if (!is_mst)
2903c980216dSImre Deak 		intel_dp_set_infoframes(encoder, false,
2904c980216dSImre Deak 					old_crtc_state, old_conn_state);
2905fa37a213SGwan-gyeong Mun 
2906379bc100SJani Nikula 	/*
2907379bc100SJani Nikula 	 * Power down sink before disabling the port, otherwise we end
2908379bc100SJani Nikula 	 * up getting interrupts from the sink on detecting link loss.
2909379bc100SJani Nikula 	 */
29100e634efdSVille Syrjälä 	intel_dp_set_power(intel_dp, DP_SET_POWER_D3);
291178eaaba3SJosé Roberto de Souza 
2912005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2913c59053dcSJosé Roberto de Souza 		if (is_mst) {
2914c59053dcSJosé Roberto de Souza 			enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
2915c59053dcSJosé Roberto de Souza 
29168910d8b7SAndrzej Hajda 			intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
29178910d8b7SAndrzej Hajda 				     TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK,
29188910d8b7SAndrzej Hajda 				     0);
2919c59053dcSJosé Roberto de Souza 		}
2920c59053dcSJosé Roberto de Souza 	} else {
2921c59053dcSJosé Roberto de Souza 		if (!is_mst)
292255a4679eSVille Syrjälä 			intel_ddi_disable_transcoder_clock(old_crtc_state);
2923c59053dcSJosé Roberto de Souza 	}
2924379bc100SJani Nikula 
2925379bc100SJani Nikula 	intel_disable_ddi_buf(encoder, old_crtc_state);
2926379bc100SJani Nikula 
29273ca8f191SJosé Roberto de Souza 	/*
29283ca8f191SJosé Roberto de Souza 	 * From TGL spec: "If single stream or multi-stream master transcoder:
29293ca8f191SJosé Roberto de Souza 	 * Configure Transcoder Clock select to direct no clock to the
29303ca8f191SJosé Roberto de Souza 	 * transcoder"
29313ca8f191SJosé Roberto de Souza 	 */
2932005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
293355a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
29343ca8f191SJosé Roberto de Souza 
2935eb46f498SJani Nikula 	intel_pps_vdd_on(intel_dp);
2936eb46f498SJani Nikula 	intel_pps_off(intel_dp);
2937379bc100SJani Nikula 
293823ef6194SJosé Roberto de Souza 	wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
293923ef6194SJosé Roberto de Souza 
294023ef6194SJosé Roberto de Souza 	if (wakeref)
2941a4550977SImre Deak 		intel_display_power_put(dev_priv,
2942a4550977SImre Deak 					dig_port->ddi_io_power_domain,
294323ef6194SJosé Roberto de Souza 					wakeref);
2944379bc100SJani Nikula 
2945c133df69SVille Syrjälä 	intel_ddi_disable_clock(encoder);
294623ef6194SJosé Roberto de Souza 
294723ef6194SJosé Roberto de Souza 	/* De-select Thunderbolt */
294823ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(dev_priv) >= 14)
294923ef6194SJosé Roberto de Souza 		intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(encoder->port),
295023ef6194SJosé Roberto de Souza 			     XELPDP_PORT_BUF_IO_SELECT_TBT, 0);
2951379bc100SJani Nikula }
2952379bc100SJani Nikula 
2953ede9771dSVille Syrjälä static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
2954ede9771dSVille Syrjälä 					struct intel_encoder *encoder,
2955379bc100SJani Nikula 					const struct intel_crtc_state *old_crtc_state,
2956379bc100SJani Nikula 					const struct drm_connector_state *old_conn_state)
2957379bc100SJani Nikula {
2958379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2959b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2960379bc100SJani Nikula 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
296123ef6194SJosé Roberto de Souza 	intel_wakeref_t wakeref;
2962379bc100SJani Nikula 
2963379bc100SJani Nikula 	dig_port->set_infoframes(encoder, false,
2964379bc100SJani Nikula 				 old_crtc_state, old_conn_state);
2965379bc100SJani Nikula 
2966c1949189SImre Deak 	if (DISPLAY_VER(dev_priv) < 12)
296755a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
2968379bc100SJani Nikula 
2969379bc100SJani Nikula 	intel_disable_ddi_buf(encoder, old_crtc_state);
2970379bc100SJani Nikula 
2971c1949189SImre Deak 	if (DISPLAY_VER(dev_priv) >= 12)
297255a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
2973c1949189SImre Deak 
297423ef6194SJosé Roberto de Souza 	wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
297523ef6194SJosé Roberto de Souza 	if (wakeref)
2976a4550977SImre Deak 		intel_display_power_put(dev_priv,
2977a4550977SImre Deak 					dig_port->ddi_io_power_domain,
297823ef6194SJosé Roberto de Souza 					wakeref);
2979379bc100SJani Nikula 
2980c133df69SVille Syrjälä 	intel_ddi_disable_clock(encoder);
2981379bc100SJani Nikula 
2982379bc100SJani Nikula 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
2983379bc100SJani Nikula }
2984379bc100SJani Nikula 
2985ede9771dSVille Syrjälä static void intel_ddi_post_disable(struct intel_atomic_state *state,
2986ede9771dSVille Syrjälä 				   struct intel_encoder *encoder,
2987379bc100SJani Nikula 				   const struct intel_crtc_state *old_crtc_state,
2988379bc100SJani Nikula 				   const struct drm_connector_state *old_conn_state)
2989379bc100SJani Nikula {
2990379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2991a6e7a006SVille Syrjälä 	struct intel_crtc *slave_crtc;
2992379bc100SJani Nikula 
29937829c92bSVille Syrjälä 	if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) {
2994773b4b54SVille Syrjälä 		intel_crtc_vblank_off(old_crtc_state);
2995773b4b54SVille Syrjälä 
29960504d0acSVille Syrjälä 		intel_disable_transcoder(old_crtc_state);
29970504d0acSVille Syrjälä 
2998773b4b54SVille Syrjälä 		intel_ddi_disable_transcoder_func(old_crtc_state);
2999773b4b54SVille Syrjälä 
3000773b4b54SVille Syrjälä 		intel_dsc_disable(old_crtc_state);
3001773b4b54SVille Syrjälä 
3002005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 9)
3003f6df4d46SLucas De Marchi 			skl_scaler_disable(old_crtc_state);
3004773b4b54SVille Syrjälä 		else
30059eae5e27SLucas De Marchi 			ilk_pfit_disable(old_crtc_state);
30067829c92bSVille Syrjälä 	}
3007773b4b54SVille Syrjälä 
3008a6e7a006SVille Syrjälä 	for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc,
3009a6e7a006SVille Syrjälä 					 intel_crtc_bigjoiner_slave_pipes(old_crtc_state)) {
30104e3cdb45SManasi Navare 		const struct intel_crtc_state *old_slave_crtc_state =
3011f2e19b58SVille Syrjälä 			intel_atomic_get_old_crtc_state(state, slave_crtc);
30124e3cdb45SManasi Navare 
30134e3cdb45SManasi Navare 		intel_crtc_vblank_off(old_slave_crtc_state);
30144e3cdb45SManasi Navare 
30154e3cdb45SManasi Navare 		intel_dsc_disable(old_slave_crtc_state);
30164e3cdb45SManasi Navare 		skl_scaler_disable(old_slave_crtc_state);
30174e3cdb45SManasi Navare 	}
30184e3cdb45SManasi Navare 
3019379bc100SJani Nikula 	/*
3020379bc100SJani Nikula 	 * When called from DP MST code:
3021379bc100SJani Nikula 	 * - old_conn_state will be NULL
3022379bc100SJani Nikula 	 * - encoder will be the main encoder (ie. mst->primary)
3023379bc100SJani Nikula 	 * - the main connector associated with this port
3024379bc100SJani Nikula 	 *   won't be active or linked to a crtc
3025379bc100SJani Nikula 	 * - old_crtc_state will be the state of the last stream to
3026379bc100SJani Nikula 	 *   be deactivated on this port, and it may not be the same
3027379bc100SJani Nikula 	 *   stream that was activated last, but each stream
3028379bc100SJani Nikula 	 *   should have a state that is identical when it comes to
3029379bc100SJani Nikula 	 *   the DP link parameteres
3030379bc100SJani Nikula 	 */
3031379bc100SJani Nikula 
3032379bc100SJani Nikula 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3033ede9771dSVille Syrjälä 		intel_ddi_post_disable_hdmi(state, encoder, old_crtc_state,
3034ede9771dSVille Syrjälä 					    old_conn_state);
3035379bc100SJani Nikula 	else
3036ede9771dSVille Syrjälä 		intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
3037ede9771dSVille Syrjälä 					  old_conn_state);
3038b108bdd0SImre Deak }
3039b108bdd0SImre Deak 
3040b108bdd0SImre Deak static void intel_ddi_post_pll_disable(struct intel_atomic_state *state,
3041b108bdd0SImre Deak 				       struct intel_encoder *encoder,
3042b108bdd0SImre Deak 				       const struct intel_crtc_state *old_crtc_state,
3043b108bdd0SImre Deak 				       const struct drm_connector_state *old_conn_state)
3044b108bdd0SImre Deak {
3045b108bdd0SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3046b108bdd0SImre Deak 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3047b108bdd0SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
3048b108bdd0SImre Deak 	bool is_tc_port = intel_phy_is_tc(i915, phy);
3049379bc100SJani Nikula 
3050637c7aa2SImre Deak 	main_link_aux_power_domain_put(dig_port, old_crtc_state);
305117bef9baSVille Syrjälä 
305217bef9baSVille Syrjälä 	if (is_tc_port)
305317bef9baSVille Syrjälä 		intel_tc_port_put_link(dig_port);
3054379bc100SJani Nikula }
3055379bc100SJani Nikula 
3056d82a855aSVille Syrjälä static void trans_port_sync_stop_link_train(struct intel_atomic_state *state,
3057d82a855aSVille Syrjälä 					    struct intel_encoder *encoder,
3058d82a855aSVille Syrjälä 					    const struct intel_crtc_state *crtc_state)
3059d82a855aSVille Syrjälä {
3060d82a855aSVille Syrjälä 	const struct drm_connector_state *conn_state;
3061d82a855aSVille Syrjälä 	struct drm_connector *conn;
3062d82a855aSVille Syrjälä 	int i;
3063d82a855aSVille Syrjälä 
3064d82a855aSVille Syrjälä 	if (!crtc_state->sync_mode_slaves_mask)
3065d82a855aSVille Syrjälä 		return;
3066d82a855aSVille Syrjälä 
3067d82a855aSVille Syrjälä 	for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
3068d82a855aSVille Syrjälä 		struct intel_encoder *slave_encoder =
3069d82a855aSVille Syrjälä 			to_intel_encoder(conn_state->best_encoder);
3070d82a855aSVille Syrjälä 		struct intel_crtc *slave_crtc = to_intel_crtc(conn_state->crtc);
3071d82a855aSVille Syrjälä 		const struct intel_crtc_state *slave_crtc_state;
3072d82a855aSVille Syrjälä 
3073d82a855aSVille Syrjälä 		if (!slave_crtc)
3074d82a855aSVille Syrjälä 			continue;
3075d82a855aSVille Syrjälä 
3076d82a855aSVille Syrjälä 		slave_crtc_state =
3077d82a855aSVille Syrjälä 			intel_atomic_get_new_crtc_state(state, slave_crtc);
3078d82a855aSVille Syrjälä 
3079d82a855aSVille Syrjälä 		if (slave_crtc_state->master_transcoder !=
3080d82a855aSVille Syrjälä 		    crtc_state->cpu_transcoder)
3081d82a855aSVille Syrjälä 			continue;
3082d82a855aSVille Syrjälä 
3083a621860aSVille Syrjälä 		intel_dp_stop_link_train(enc_to_intel_dp(slave_encoder),
3084a621860aSVille Syrjälä 					 slave_crtc_state);
3085d82a855aSVille Syrjälä 	}
3086d82a855aSVille Syrjälä 
3087d82a855aSVille Syrjälä 	usleep_range(200, 400);
3088d82a855aSVille Syrjälä 
3089a621860aSVille Syrjälä 	intel_dp_stop_link_train(enc_to_intel_dp(encoder),
3090a621860aSVille Syrjälä 				 crtc_state);
3091d82a855aSVille Syrjälä }
3092d82a855aSVille Syrjälä 
3093ede9771dSVille Syrjälä static void intel_enable_ddi_dp(struct intel_atomic_state *state,
3094ede9771dSVille Syrjälä 				struct intel_encoder *encoder,
3095379bc100SJani Nikula 				const struct intel_crtc_state *crtc_state,
3096379bc100SJani Nikula 				const struct drm_connector_state *conn_state)
3097379bc100SJani Nikula {
3098379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3099b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3100998cc864SUma Shankar 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3101379bc100SJani Nikula 	enum port port = encoder->port;
3102379bc100SJani Nikula 
3103005e9537SMatt Roper 	if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
3104a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
3105379bc100SJani Nikula 
31066306d8dbSHans de Goede 	drm_connector_update_privacy_screen(conn_state);
3107379bc100SJani Nikula 	intel_edp_backlight_on(crtc_state, conn_state);
3108998cc864SUma Shankar 
31097ffa2f27SJani Nikula 	if (!dig_port->lspcon.active || intel_dp_has_hdmi_sink(&dig_port->dp))
31101bf3657cSGwan-gyeong Mun 		intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3111998cc864SUma Shankar 
3112379bc100SJani Nikula 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
3113d82a855aSVille Syrjälä 
3114d82a855aSVille Syrjälä 	trans_port_sync_stop_link_train(state, encoder, crtc_state);
3115379bc100SJani Nikula }
3116379bc100SJani Nikula 
3117379bc100SJani Nikula static i915_reg_t
3118379bc100SJani Nikula gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
3119379bc100SJani Nikula 			       enum port port)
3120379bc100SJani Nikula {
312112c4d4c1SVille Syrjälä 	static const enum transcoder trans[] = {
312212c4d4c1SVille Syrjälä 		[PORT_A] = TRANSCODER_EDP,
312312c4d4c1SVille Syrjälä 		[PORT_B] = TRANSCODER_A,
312412c4d4c1SVille Syrjälä 		[PORT_C] = TRANSCODER_B,
312512c4d4c1SVille Syrjälä 		[PORT_D] = TRANSCODER_C,
312612c4d4c1SVille Syrjälä 		[PORT_E] = TRANSCODER_A,
3127379bc100SJani Nikula 	};
3128379bc100SJani Nikula 
3129005e9537SMatt Roper 	drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9);
3130379bc100SJani Nikula 
31311de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E))
3132379bc100SJani Nikula 		port = PORT_A;
3133379bc100SJani Nikula 
313412c4d4c1SVille Syrjälä 	return CHICKEN_TRANS(trans[port]);
3135379bc100SJani Nikula }
3136379bc100SJani Nikula 
3137ede9771dSVille Syrjälä static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
3138ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
3139379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state,
3140379bc100SJani Nikula 				  const struct drm_connector_state *conn_state)
3141379bc100SJani Nikula {
3142379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3143b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3144379bc100SJani Nikula 	struct drm_connector *connector = conn_state->connector;
3145379bc100SJani Nikula 	enum port port = encoder->port;
3146e99ba962SImre Deak 	enum phy phy = intel_port_to_phy(dev_priv, port);
3147e99ba962SImre Deak 	u32 buf_ctl;
3148379bc100SJani Nikula 
3149379bc100SJani Nikula 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3150379bc100SJani Nikula 					       crtc_state->hdmi_high_tmds_clock_ratio,
3151379bc100SJani Nikula 					       crtc_state->hdmi_scrambling))
315247bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
315347bdb1caSJani Nikula 			    "[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
3154379bc100SJani Nikula 			    connector->base.id, connector->name);
3155379bc100SJani Nikula 
31565bafd85dSVille Syrjälä 	if (has_buf_trans_select(dev_priv))
3157e722ab8bSVille Syrjälä 		hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state);
3158c9b69041SVille Syrjälä 
3159b66a8abaSAnkit Nautiyal 	/* e. Enable D2D Link for C10/C20 Phy */
3160b66a8abaSAnkit Nautiyal 	if (DISPLAY_VER(dev_priv) >= 14)
3161b66a8abaSAnkit Nautiyal 		mtl_ddi_enable_d2d(encoder);
3162b66a8abaSAnkit Nautiyal 
3163e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
3164c9b69041SVille Syrjälä 
3165379bc100SJani Nikula 	/* Display WA #1143: skl,kbl,cfl */
316693e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
3167379bc100SJani Nikula 		/*
3168379bc100SJani Nikula 		 * For some reason these chicken bits have been
3169379bc100SJani Nikula 		 * stuffed into a transcoder register, event though
3170379bc100SJani Nikula 		 * the bits affect a specific DDI port rather than
3171379bc100SJani Nikula 		 * a specific transcoder.
3172379bc100SJani Nikula 		 */
3173379bc100SJani Nikula 		i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port);
3174379bc100SJani Nikula 		u32 val;
3175379bc100SJani Nikula 
3176f7960e7fSJani Nikula 		val = intel_de_read(dev_priv, reg);
3177379bc100SJani Nikula 
3178379bc100SJani Nikula 		if (port == PORT_E)
3179379bc100SJani Nikula 			val |= DDIE_TRAINING_OVERRIDE_ENABLE |
3180379bc100SJani Nikula 				DDIE_TRAINING_OVERRIDE_VALUE;
3181379bc100SJani Nikula 		else
3182379bc100SJani Nikula 			val |= DDI_TRAINING_OVERRIDE_ENABLE |
3183379bc100SJani Nikula 				DDI_TRAINING_OVERRIDE_VALUE;
3184379bc100SJani Nikula 
3185f7960e7fSJani Nikula 		intel_de_write(dev_priv, reg, val);
3186f7960e7fSJani Nikula 		intel_de_posting_read(dev_priv, reg);
3187379bc100SJani Nikula 
3188379bc100SJani Nikula 		udelay(1);
3189379bc100SJani Nikula 
3190379bc100SJani Nikula 		if (port == PORT_E)
3191379bc100SJani Nikula 			val &= ~(DDIE_TRAINING_OVERRIDE_ENABLE |
3192379bc100SJani Nikula 				 DDIE_TRAINING_OVERRIDE_VALUE);
3193379bc100SJani Nikula 		else
3194379bc100SJani Nikula 			val &= ~(DDI_TRAINING_OVERRIDE_ENABLE |
3195379bc100SJani Nikula 				 DDI_TRAINING_OVERRIDE_VALUE);
3196379bc100SJani Nikula 
3197f7960e7fSJani Nikula 		intel_de_write(dev_priv, reg, val);
3198379bc100SJani Nikula 	}
3199379bc100SJani Nikula 
32001e0cb7beSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
32011e0cb7beSVille Syrjälä 
3202379bc100SJani Nikula 	/* In HDMI/DVI mode, the port width, and swing/emphasis values
3203379bc100SJani Nikula 	 * are ignored so nothing special needs to be done besides
3204379bc100SJani Nikula 	 * enabling the port.
3205414002f1SImre Deak 	 *
3206414002f1SImre Deak 	 * On ADL_P the PHY link rate and lane count must be programmed but
3207414002f1SImre Deak 	 * these are both 0 for HDMI.
3208b66a8abaSAnkit Nautiyal 	 *
3209b66a8abaSAnkit Nautiyal 	 * But MTL onwards HDMI2.1 is supported and in TMDS mode this
3210b66a8abaSAnkit Nautiyal 	 * is filled with lane count, already set in the crtc_state.
3211b66a8abaSAnkit Nautiyal 	 * The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
3212379bc100SJani Nikula 	 */
3213e99ba962SImre Deak 	buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
3214b66a8abaSAnkit Nautiyal 	if (DISPLAY_VER(dev_priv) >= 14) {
3215b66a8abaSAnkit Nautiyal 		u8  lane_count = mtl_get_port_width(crtc_state->lane_count);
3216b66a8abaSAnkit Nautiyal 		u32 port_buf = 0;
3217b66a8abaSAnkit Nautiyal 
3218b66a8abaSAnkit Nautiyal 		port_buf |= XELPDP_PORT_WIDTH(lane_count);
3219b66a8abaSAnkit Nautiyal 
3220b66a8abaSAnkit Nautiyal 		if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
3221b66a8abaSAnkit Nautiyal 			port_buf |= XELPDP_PORT_REVERSAL;
3222b66a8abaSAnkit Nautiyal 
3223b66a8abaSAnkit Nautiyal 		intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(port),
3224b66a8abaSAnkit Nautiyal 			     XELPDP_PORT_WIDTH_MASK | XELPDP_PORT_REVERSAL, port_buf);
3225b66a8abaSAnkit Nautiyal 
3226b66a8abaSAnkit Nautiyal 		buf_ctl |= DDI_PORT_WIDTH(lane_count);
3227b66a8abaSAnkit Nautiyal 	} else if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
3228e99ba962SImre Deak 		drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port));
3229e99ba962SImre Deak 		buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
3230e99ba962SImre Deak 	}
3231b66a8abaSAnkit Nautiyal 
3232e99ba962SImre Deak 	intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
3233379bc100SJani Nikula 
323465e75edaSAnkit Nautiyal 	intel_wait_ddi_buf_active(dev_priv, port);
323565e75edaSAnkit Nautiyal 
3236379bc100SJani Nikula 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
3237379bc100SJani Nikula }
3238379bc100SJani Nikula 
3239ede9771dSVille Syrjälä static void intel_enable_ddi(struct intel_atomic_state *state,
3240ede9771dSVille Syrjälä 			     struct intel_encoder *encoder,
3241379bc100SJani Nikula 			     const struct intel_crtc_state *crtc_state,
3242379bc100SJani Nikula 			     const struct drm_connector_state *conn_state)
3243379bc100SJani Nikula {
32448b4f2137SPankaj Bharadiya 	drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
324521fd23acSJani Nikula 
3246df529053SVille Syrjälä 	if (!intel_crtc_is_bigjoiner_slave(crtc_state))
3247eed22a46SVille Syrjälä 		intel_ddi_enable_transcoder_func(encoder, crtc_state);
32487c2fedd7SVille Syrjälä 
32498853750dSVinod Govindapillai 	/* Enable/Disable DP2.0 SDP split config before transcoder */
32508853750dSVinod Govindapillai 	intel_audio_sdp_split_update(encoder, crtc_state);
32518853750dSVinod Govindapillai 
32528c66081bSVille Syrjälä 	intel_enable_transcoder(crtc_state);
325321fd23acSJani Nikula 
325421fd23acSJani Nikula 	intel_crtc_vblank_on(crtc_state);
325521fd23acSJani Nikula 
3256379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
3257ede9771dSVille Syrjälä 		intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state);
3258379bc100SJani Nikula 	else
3259ede9771dSVille Syrjälä 		intel_enable_ddi_dp(state, encoder, crtc_state, conn_state);
3260379bc100SJani Nikula 
3261379bc100SJani Nikula 	/* Enable hdcp if it's desired */
3262379bc100SJani Nikula 	if (conn_state->content_protection ==
3263379bc100SJani Nikula 	    DRM_MODE_CONTENT_PROTECTION_DESIRED)
32644c4279a8SSuraj Kandpal 		intel_hdcp_enable(state, encoder, crtc_state, conn_state);
3265379bc100SJani Nikula }
3266379bc100SJani Nikula 
3267ede9771dSVille Syrjälä static void intel_disable_ddi_dp(struct intel_atomic_state *state,
3268ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
3269379bc100SJani Nikula 				 const struct intel_crtc_state *old_crtc_state,
3270379bc100SJani Nikula 				 const struct drm_connector_state *old_conn_state)
3271379bc100SJani Nikula {
3272b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3273379bc100SJani Nikula 
3274379bc100SJani Nikula 	intel_dp->link_trained = false;
3275379bc100SJani Nikula 
3276179db7c1SJani Nikula 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
3277f28c5950SVille Syrjälä 
3278f28c5950SVille Syrjälä 	intel_psr_disable(intel_dp, old_crtc_state);
3279379bc100SJani Nikula 	intel_edp_backlight_off(old_conn_state);
3280379bc100SJani Nikula 	/* Disable the decompression in DP Sink */
3281379bc100SJani Nikula 	intel_dp_sink_set_decompression_state(intel_dp, old_crtc_state,
3282379bc100SJani Nikula 					      false);
32831639406aSManasi Navare 	/* Disable Ignore_MSA bit in DP Sink */
32841639406aSManasi Navare 	intel_dp_sink_set_msa_timing_par_ignore_state(intel_dp, old_crtc_state,
32851639406aSManasi Navare 						      false);
3286379bc100SJani Nikula }
3287379bc100SJani Nikula 
3288ede9771dSVille Syrjälä static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
3289ede9771dSVille Syrjälä 				   struct intel_encoder *encoder,
3290379bc100SJani Nikula 				   const struct intel_crtc_state *old_crtc_state,
3291379bc100SJani Nikula 				   const struct drm_connector_state *old_conn_state)
3292379bc100SJani Nikula {
329347bdb1caSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3294379bc100SJani Nikula 	struct drm_connector *connector = old_conn_state->connector;
3295379bc100SJani Nikula 
3296179db7c1SJani Nikula 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
3297f28c5950SVille Syrjälä 
3298379bc100SJani Nikula 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3299379bc100SJani Nikula 					       false, false))
330047bdb1caSJani Nikula 		drm_dbg_kms(&i915->drm,
330147bdb1caSJani Nikula 			    "[CONNECTOR:%d:%s] Failed to reset sink scrambling/TMDS bit clock ratio\n",
3302379bc100SJani Nikula 			    connector->base.id, connector->name);
3303379bc100SJani Nikula }
3304379bc100SJani Nikula 
3305ede9771dSVille Syrjälä static void intel_disable_ddi(struct intel_atomic_state *state,
3306ede9771dSVille Syrjälä 			      struct intel_encoder *encoder,
3307379bc100SJani Nikula 			      const struct intel_crtc_state *old_crtc_state,
3308379bc100SJani Nikula 			      const struct drm_connector_state *old_conn_state)
3309379bc100SJani Nikula {
3310c598c335SImre Deak 	intel_tc_port_link_cancel_reset_work(enc_to_dig_port(encoder));
3311c598c335SImre Deak 
3312379bc100SJani Nikula 	intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
3313379bc100SJani Nikula 
3314379bc100SJani Nikula 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3315ede9771dSVille Syrjälä 		intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
3316ede9771dSVille Syrjälä 				       old_conn_state);
3317379bc100SJani Nikula 	else
3318ede9771dSVille Syrjälä 		intel_disable_ddi_dp(state, encoder, old_crtc_state,
3319ede9771dSVille Syrjälä 				     old_conn_state);
3320379bc100SJani Nikula }
3321379bc100SJani Nikula 
3322ede9771dSVille Syrjälä static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
3323ede9771dSVille Syrjälä 				     struct intel_encoder *encoder,
3324379bc100SJani Nikula 				     const struct intel_crtc_state *crtc_state,
3325379bc100SJani Nikula 				     const struct drm_connector_state *conn_state)
3326379bc100SJani Nikula {
33270c06fa15SGwan-gyeong Mun 	intel_ddi_set_dp_msa(crtc_state, conn_state);
3328379bc100SJani Nikula 
332976d45d06SGwan-gyeong Mun 	intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3330379bc100SJani Nikula 
3331c0a52f8bSJani Nikula 	intel_backlight_update(state, encoder, crtc_state, conn_state);
33326306d8dbSHans de Goede 	drm_connector_update_privacy_screen(conn_state);
3333379bc100SJani Nikula }
3334379bc100SJani Nikula 
3335f1c7a36bSSean Paul void intel_ddi_update_pipe(struct intel_atomic_state *state,
3336ede9771dSVille Syrjälä 			   struct intel_encoder *encoder,
3337379bc100SJani Nikula 			   const struct intel_crtc_state *crtc_state,
3338379bc100SJani Nikula 			   const struct drm_connector_state *conn_state)
3339379bc100SJani Nikula {
3340d456512cSRamalingam C 
3341f1c7a36bSSean Paul 	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
3342f1c7a36bSSean Paul 	    !intel_encoder_is_mst(encoder))
3343ede9771dSVille Syrjälä 		intel_ddi_update_pipe_dp(state, encoder, crtc_state,
3344ede9771dSVille Syrjälä 					 conn_state);
3345379bc100SJani Nikula 
3346ede9771dSVille Syrjälä 	intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state);
3347379bc100SJani Nikula }
3348379bc100SJani Nikula 
334927ac123bSImre Deak void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
335027ac123bSImre Deak 				  struct intel_encoder *encoder,
335127ac123bSImre Deak 				  struct intel_crtc *crtc)
335227ac123bSImre Deak {
335327ac123bSImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
335427ac123bSImre Deak 	struct intel_crtc_state *crtc_state =
335527ac123bSImre Deak 		intel_atomic_get_new_crtc_state(state, crtc);
335627ac123bSImre Deak 	struct intel_crtc *slave_crtc;
335727ac123bSImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
335827ac123bSImre Deak 
335962618c7fSMika Kahola 	/* FIXME: Add MTL pll_mgr */
336062618c7fSMika Kahola 	if (DISPLAY_VER(i915) >= 14 || !intel_phy_is_tc(i915, phy))
336127ac123bSImre Deak 		return;
336227ac123bSImre Deak 
336327ac123bSImre Deak 	intel_update_active_dpll(state, crtc, encoder);
336427ac123bSImre Deak 	for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
336527ac123bSImre Deak 					 intel_crtc_bigjoiner_slave_pipes(crtc_state))
336627ac123bSImre Deak 		intel_update_active_dpll(state, slave_crtc, encoder);
336727ac123bSImre Deak }
336827ac123bSImre Deak 
3369379bc100SJani Nikula static void
3370ede9771dSVille Syrjälä intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
3371ede9771dSVille Syrjälä 			 struct intel_encoder *encoder,
3372379bc100SJani Nikula 			 const struct intel_crtc_state *crtc_state,
3373379bc100SJani Nikula 			 const struct drm_connector_state *conn_state)
3374379bc100SJani Nikula {
3375379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3376b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3377d8fe2ab6SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
3378d8fe2ab6SMatt Roper 	bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
3379379bc100SJani Nikula 
33800f752b21SImre Deak 	if (is_tc_port) {
33810f752b21SImre Deak 		struct intel_crtc *master_crtc =
33820f752b21SImre Deak 			to_intel_crtc(crtc_state->uapi.crtc);
33830f752b21SImre Deak 
338424a7bfe0SImre Deak 		intel_tc_port_get_link(dig_port, crtc_state->lane_count);
338527ac123bSImre Deak 		intel_ddi_update_active_dpll(state, encoder, master_crtc);
33860f752b21SImre Deak 	}
33870f752b21SImre Deak 
3388637c7aa2SImre Deak 	main_link_aux_power_domain_get(dig_port, crtc_state);
3389379bc100SJani Nikula 
339011a89708SImre Deak 	if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port))
33919d44dcb9SLucas De Marchi 		/*
33929d44dcb9SLucas De Marchi 		 * Program the lane count for static/dynamic connections on
33939d44dcb9SLucas De Marchi 		 * Type-C ports.  Skip this step for TBT.
33949d44dcb9SLucas De Marchi 		 */
33959d44dcb9SLucas De Marchi 		intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count);
33962446e1d6SMatt Roper 	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3397379bc100SJani Nikula 		bxt_ddi_phy_set_lane_optim_mask(encoder,
3398379bc100SJani Nikula 						crtc_state->lane_lat_optim_mask);
3399379bc100SJani Nikula }
3400379bc100SJani Nikula 
340155223c3bSImre Deak static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
340255223c3bSImre Deak {
340355223c3bSImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
340455223c3bSImre Deak 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
340555223c3bSImre Deak 	int ln;
340655223c3bSImre Deak 
340789cb0ba4SImre Deak 	for (ln = 0; ln < 2; ln++)
3408b8ed5533SImre Deak 		intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0);
340955223c3bSImre Deak }
341055223c3bSImre Deak 
341123ef6194SJosé Roberto de Souza static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
341223ef6194SJosé Roberto de Souza 					 const struct intel_crtc_state *crtc_state)
341323ef6194SJosé Roberto de Souza {
341423ef6194SJosé Roberto de Souza 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
341523ef6194SJosé Roberto de Souza 	struct intel_encoder *encoder = &dig_port->base;
341623ef6194SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
341723ef6194SJosé Roberto de Souza 	enum port port = encoder->port;
341823ef6194SJosé Roberto de Souza 	u32 dp_tp_ctl;
341923ef6194SJosé Roberto de Souza 
342023ef6194SJosé Roberto de Souza 	/*
342123ef6194SJosé Roberto de Souza 	 * TODO: To train with only a different voltage swing entry is not
342223ef6194SJosé Roberto de Souza 	 * necessary disable and enable port
342323ef6194SJosé Roberto de Souza 	 */
342423ef6194SJosé Roberto de Souza 	dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
342523ef6194SJosé Roberto de Souza 	if (dp_tp_ctl & DP_TP_CTL_ENABLE)
342623ef6194SJosé Roberto de Souza 		mtl_disable_ddi_buf(encoder, crtc_state);
342723ef6194SJosé Roberto de Souza 
342823ef6194SJosé Roberto de Souza 	/* 6.d Configure and enable DP_TP_CTL with link training pattern 1 selected */
342923ef6194SJosé Roberto de Souza 	dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
343023ef6194SJosé Roberto de Souza 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
343123ef6194SJosé Roberto de Souza 		dp_tp_ctl |= DP_TP_CTL_MODE_MST;
343223ef6194SJosé Roberto de Souza 	} else {
343323ef6194SJosé Roberto de Souza 		dp_tp_ctl |= DP_TP_CTL_MODE_SST;
343423ef6194SJosé Roberto de Souza 		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
343523ef6194SJosé Roberto de Souza 			dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
343623ef6194SJosé Roberto de Souza 	}
343723ef6194SJosé Roberto de Souza 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
343823ef6194SJosé Roberto de Souza 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
343923ef6194SJosé Roberto de Souza 
344023ef6194SJosé Roberto de Souza 	/* 6.f Enable D2D Link */
344123ef6194SJosé Roberto de Souza 	mtl_ddi_enable_d2d(encoder);
344223ef6194SJosé Roberto de Souza 
344323ef6194SJosé Roberto de Souza 	/* 6.g Configure voltage swing and related IO settings */
344423ef6194SJosé Roberto de Souza 	encoder->set_signal_levels(encoder, crtc_state);
344523ef6194SJosé Roberto de Souza 
344623ef6194SJosé Roberto de Souza 	/* 6.h Configure PORT_BUF_CTL1 */
344723ef6194SJosé Roberto de Souza 	mtl_port_buf_ctl_program(encoder, crtc_state);
344823ef6194SJosé Roberto de Souza 
344923ef6194SJosé Roberto de Souza 	/* 6.i Configure and enable DDI_CTL_DE to start sending valid data to port slice */
345023ef6194SJosé Roberto de Souza 	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
345123ef6194SJosé Roberto de Souza 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
345223ef6194SJosé Roberto de Souza 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
345323ef6194SJosé Roberto de Souza 
345423ef6194SJosé Roberto de Souza 	/* 6.j Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 us */
345523ef6194SJosé Roberto de Souza 	intel_wait_ddi_buf_active(dev_priv, port);
345623ef6194SJosé Roberto de Souza }
345723ef6194SJosé Roberto de Souza 
3458a621860aSVille Syrjälä static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
3459a621860aSVille Syrjälä 					   const struct intel_crtc_state *crtc_state)
3460379bc100SJani Nikula {
346155223c3bSImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
346255223c3bSImre Deak 	struct intel_encoder *encoder = &dig_port->base;
3463ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3464ef79fafeSVille Syrjälä 	enum port port = encoder->port;
346535ac28a8SLucas De Marchi 	u32 dp_tp_ctl, ddi_buf_ctl;
3466379bc100SJani Nikula 	bool wait = false;
3467379bc100SJani Nikula 
3468ef79fafeSVille Syrjälä 	dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
346935ac28a8SLucas De Marchi 
347035ac28a8SLucas De Marchi 	if (dp_tp_ctl & DP_TP_CTL_ENABLE) {
3471f7960e7fSJani Nikula 		ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port));
347235ac28a8SLucas De Marchi 		if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) {
3473f7960e7fSJani Nikula 			intel_de_write(dev_priv, DDI_BUF_CTL(port),
347435ac28a8SLucas De Marchi 				       ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE);
3475379bc100SJani Nikula 			wait = true;
3476379bc100SJani Nikula 		}
3477379bc100SJani Nikula 
34788c042949SVille Syrjälä 		dp_tp_ctl &= ~DP_TP_CTL_ENABLE;
3479ef79fafeSVille Syrjälä 		intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3480ef79fafeSVille Syrjälä 		intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3481379bc100SJani Nikula 
3482379bc100SJani Nikula 		if (wait)
3483379bc100SJani Nikula 			intel_wait_ddi_buf_idle(dev_priv, port);
3484379bc100SJani Nikula 	}
3485379bc100SJani Nikula 
3486963501bdSImre Deak 	dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
3487a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
348835ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_MODE_MST;
3489a621860aSVille Syrjälä 	} else {
349035ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_MODE_SST;
3491379bc100SJani Nikula 		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
349235ac28a8SLucas De Marchi 			dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
3493379bc100SJani Nikula 	}
3494ef79fafeSVille Syrjälä 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3495ef79fafeSVille Syrjälä 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3496379bc100SJani Nikula 
349755223c3bSImre Deak 	if (IS_ALDERLAKE_P(dev_priv) &&
349855223c3bSImre Deak 	    (intel_tc_port_in_dp_alt_mode(dig_port) || intel_tc_port_in_legacy_mode(dig_port)))
349955223c3bSImre Deak 		adlp_tbt_to_dp_alt_switch_wa(encoder);
350055223c3bSImre Deak 
3501379bc100SJani Nikula 	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
3502f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
3503f7960e7fSJani Nikula 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
3504379bc100SJani Nikula 
3505e828da30SManasi Navare 	intel_wait_ddi_buf_active(dev_priv, port);
3506379bc100SJani Nikula }
3507379bc100SJani Nikula 
3508eee3f911SVille Syrjälä static void intel_ddi_set_link_train(struct intel_dp *intel_dp,
3509a621860aSVille Syrjälä 				     const struct intel_crtc_state *crtc_state,
3510eee3f911SVille Syrjälä 				     u8 dp_train_pat)
3511eee3f911SVille Syrjälä {
3512ef79fafeSVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
3513ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3514eee3f911SVille Syrjälä 	u32 temp;
3515eee3f911SVille Syrjälä 
3516ef79fafeSVille Syrjälä 	temp = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3517eee3f911SVille Syrjälä 
3518eee3f911SVille Syrjälä 	temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
35196777a855SImre Deak 	switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
3520eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_DISABLE:
3521eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
3522eee3f911SVille Syrjälä 		break;
3523eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_1:
3524eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
3525eee3f911SVille Syrjälä 		break;
3526eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_2:
3527eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
3528eee3f911SVille Syrjälä 		break;
3529eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_3:
3530eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
3531eee3f911SVille Syrjälä 		break;
3532eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_4:
3533eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT4;
3534eee3f911SVille Syrjälä 		break;
3535eee3f911SVille Syrjälä 	}
3536eee3f911SVille Syrjälä 
3537ef79fafeSVille Syrjälä 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), temp);
3538eee3f911SVille Syrjälä }
3539eee3f911SVille Syrjälä 
3540a621860aSVille Syrjälä static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp,
3541a621860aSVille Syrjälä 					  const struct intel_crtc_state *crtc_state)
35428fdda385SVille Syrjälä {
35438fdda385SVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
35448fdda385SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
35458fdda385SVille Syrjälä 	enum port port = encoder->port;
35468fdda385SVille Syrjälä 
35478910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
35488910d8b7SAndrzej Hajda 		     DP_TP_CTL_LINK_TRAIN_MASK, DP_TP_CTL_LINK_TRAIN_IDLE);
35498fdda385SVille Syrjälä 
35508fdda385SVille Syrjälä 	/*
35518fdda385SVille Syrjälä 	 * Until TGL on PORT_A we can have only eDP in SST mode. There the only
35528fdda385SVille Syrjälä 	 * reason we need to set idle transmission mode is to work around a HW
35538fdda385SVille Syrjälä 	 * issue where we enable the pipe while not in idle link-training mode.
35548fdda385SVille Syrjälä 	 * In this case there is requirement to wait for a minimum number of
35558fdda385SVille Syrjälä 	 * idle patterns to be sent.
35568fdda385SVille Syrjälä 	 */
3557005e9537SMatt Roper 	if (port == PORT_A && DISPLAY_VER(dev_priv) < 12)
35588fdda385SVille Syrjälä 		return;
35598fdda385SVille Syrjälä 
3560ef79fafeSVille Syrjälä 	if (intel_de_wait_for_set(dev_priv,
3561ef79fafeSVille Syrjälä 				  dp_tp_status_reg(encoder, crtc_state),
35628fdda385SVille Syrjälä 				  DP_TP_STATUS_IDLE_DONE, 1))
35638fdda385SVille Syrjälä 		drm_err(&dev_priv->drm,
35648fdda385SVille Syrjälä 			"Timed out waiting for DP idle patterns\n");
35658fdda385SVille Syrjälä }
35668fdda385SVille Syrjälä 
3567379bc100SJani Nikula static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
3568379bc100SJani Nikula 				       enum transcoder cpu_transcoder)
3569379bc100SJani Nikula {
3570379bc100SJani Nikula 	if (cpu_transcoder == TRANSCODER_EDP)
3571379bc100SJani Nikula 		return false;
3572379bc100SJani Nikula 
3573615a7724SAnshuman Gupta 	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO_MMIO))
3574379bc100SJani Nikula 		return false;
3575379bc100SJani Nikula 
3576f7960e7fSJani Nikula 	return intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD) &
3577379bc100SJani Nikula 		AUDIO_OUTPUT_ENABLE(cpu_transcoder);
3578379bc100SJani Nikula }
3579379bc100SJani Nikula 
3580379bc100SJani Nikula void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
3581379bc100SJani Nikula 					 struct intel_crtc_state *crtc_state)
3582379bc100SJani Nikula {
3583005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12 && crtc_state->port_clock > 594000)
35840fde0b1dSMatt Roper 		crtc_state->min_voltage_level = 2;
358524ea098bSTejas Upadhyay 	else if (IS_JSL_EHL(dev_priv) && crtc_state->port_clock > 594000)
35869d5fd37eSMatt Roper 		crtc_state->min_voltage_level = 3;
3587005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11 && crtc_state->port_clock > 594000)
3588379bc100SJani Nikula 		crtc_state->min_voltage_level = 1;
3589379bc100SJani Nikula }
3590379bc100SJani Nikula 
3591dc5b8ed5SVille Syrjälä static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *dev_priv,
359202d8ea47SVille Syrjälä 						     enum transcoder cpu_transcoder)
359302d8ea47SVille Syrjälä {
3594dc5b8ed5SVille Syrjälä 	u32 master_select;
359502d8ea47SVille Syrjälä 
3596005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
3597dc5b8ed5SVille Syrjälä 		u32 ctl2 = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL2(cpu_transcoder));
359802d8ea47SVille Syrjälä 
359902d8ea47SVille Syrjälä 		if ((ctl2 & PORT_SYNC_MODE_ENABLE) == 0)
360002d8ea47SVille Syrjälä 			return INVALID_TRANSCODER;
360102d8ea47SVille Syrjälä 
3602d4d7d9caSVille Syrjälä 		master_select = REG_FIELD_GET(PORT_SYNC_MODE_MASTER_SELECT_MASK, ctl2);
3603dc5b8ed5SVille Syrjälä 	} else {
3604dc5b8ed5SVille Syrjälä 		u32 ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
3605dc5b8ed5SVille Syrjälä 
3606dc5b8ed5SVille Syrjälä 		if ((ctl & TRANS_DDI_PORT_SYNC_ENABLE) == 0)
3607dc5b8ed5SVille Syrjälä 			return INVALID_TRANSCODER;
3608dc5b8ed5SVille Syrjälä 
3609dc5b8ed5SVille Syrjälä 		master_select = REG_FIELD_GET(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, ctl);
3610dc5b8ed5SVille Syrjälä 	}
361102d8ea47SVille Syrjälä 
361202d8ea47SVille Syrjälä 	if (master_select == 0)
361302d8ea47SVille Syrjälä 		return TRANSCODER_EDP;
361402d8ea47SVille Syrjälä 	else
361502d8ea47SVille Syrjälä 		return master_select - 1;
361602d8ea47SVille Syrjälä }
361702d8ea47SVille Syrjälä 
3618dc5b8ed5SVille Syrjälä static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
361902d8ea47SVille Syrjälä {
362002d8ea47SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
362102d8ea47SVille Syrjälä 	u32 transcoders = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
362202d8ea47SVille Syrjälä 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
362302d8ea47SVille Syrjälä 	enum transcoder cpu_transcoder;
362402d8ea47SVille Syrjälä 
362502d8ea47SVille Syrjälä 	crtc_state->master_transcoder =
3626dc5b8ed5SVille Syrjälä 		bdw_transcoder_master_readout(dev_priv, crtc_state->cpu_transcoder);
362702d8ea47SVille Syrjälä 
362802d8ea47SVille Syrjälä 	for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
362902d8ea47SVille Syrjälä 		enum intel_display_power_domain power_domain;
363002d8ea47SVille Syrjälä 		intel_wakeref_t trans_wakeref;
363102d8ea47SVille Syrjälä 
363202d8ea47SVille Syrjälä 		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
363302d8ea47SVille Syrjälä 		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
363402d8ea47SVille Syrjälä 								   power_domain);
363502d8ea47SVille Syrjälä 
363602d8ea47SVille Syrjälä 		if (!trans_wakeref)
363702d8ea47SVille Syrjälä 			continue;
363802d8ea47SVille Syrjälä 
3639dc5b8ed5SVille Syrjälä 		if (bdw_transcoder_master_readout(dev_priv, cpu_transcoder) ==
364002d8ea47SVille Syrjälä 		    crtc_state->cpu_transcoder)
364102d8ea47SVille Syrjälä 			crtc_state->sync_mode_slaves_mask |= BIT(cpu_transcoder);
364202d8ea47SVille Syrjälä 
364302d8ea47SVille Syrjälä 		intel_display_power_put(dev_priv, power_domain, trans_wakeref);
364402d8ea47SVille Syrjälä 	}
364502d8ea47SVille Syrjälä 
364602d8ea47SVille Syrjälä 	drm_WARN_ON(&dev_priv->drm,
364702d8ea47SVille Syrjälä 		    crtc_state->master_transcoder != INVALID_TRANSCODER &&
364802d8ea47SVille Syrjälä 		    crtc_state->sync_mode_slaves_mask);
364902d8ea47SVille Syrjälä }
365002d8ea47SVille Syrjälä 
36510385eceaSManasi Navare static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
3652379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config)
3653379bc100SJani Nikula {
3654379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3655f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
3656379bc100SJani Nikula 	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
3657a44289b9SUma Shankar 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3658379bc100SJani Nikula 	u32 temp, flags = 0;
3659379bc100SJani Nikula 
3660f7960e7fSJani Nikula 	temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
3661379bc100SJani Nikula 	if (temp & TRANS_DDI_PHSYNC)
3662379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_PHSYNC;
3663379bc100SJani Nikula 	else
3664379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_NHSYNC;
3665379bc100SJani Nikula 	if (temp & TRANS_DDI_PVSYNC)
3666379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_PVSYNC;
3667379bc100SJani Nikula 	else
3668379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_NVSYNC;
3669379bc100SJani Nikula 
36701326a92cSMaarten Lankhorst 	pipe_config->hw.adjusted_mode.flags |= flags;
3671379bc100SJani Nikula 
3672379bc100SJani Nikula 	switch (temp & TRANS_DDI_BPC_MASK) {
3673379bc100SJani Nikula 	case TRANS_DDI_BPC_6:
3674379bc100SJani Nikula 		pipe_config->pipe_bpp = 18;
3675379bc100SJani Nikula 		break;
3676379bc100SJani Nikula 	case TRANS_DDI_BPC_8:
3677379bc100SJani Nikula 		pipe_config->pipe_bpp = 24;
3678379bc100SJani Nikula 		break;
3679379bc100SJani Nikula 	case TRANS_DDI_BPC_10:
3680379bc100SJani Nikula 		pipe_config->pipe_bpp = 30;
3681379bc100SJani Nikula 		break;
3682379bc100SJani Nikula 	case TRANS_DDI_BPC_12:
3683379bc100SJani Nikula 		pipe_config->pipe_bpp = 36;
3684379bc100SJani Nikula 		break;
3685379bc100SJani Nikula 	default:
3686379bc100SJani Nikula 		break;
3687379bc100SJani Nikula 	}
3688379bc100SJani Nikula 
3689379bc100SJani Nikula 	switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
3690379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_HDMI:
3691379bc100SJani Nikula 		pipe_config->has_hdmi_sink = true;
3692379bc100SJani Nikula 
3693379bc100SJani Nikula 		pipe_config->infoframes.enable |=
3694379bc100SJani Nikula 			intel_hdmi_infoframes_enabled(encoder, pipe_config);
3695379bc100SJani Nikula 
3696379bc100SJani Nikula 		if (pipe_config->infoframes.enable)
3697379bc100SJani Nikula 			pipe_config->has_infoframe = true;
3698379bc100SJani Nikula 
3699379bc100SJani Nikula 		if (temp & TRANS_DDI_HDMI_SCRAMBLING)
3700379bc100SJani Nikula 			pipe_config->hdmi_scrambling = true;
3701379bc100SJani Nikula 		if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
3702379bc100SJani Nikula 			pipe_config->hdmi_high_tmds_clock_ratio = true;
3703df561f66SGustavo A. R. Silva 		fallthrough;
3704379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DVI:
3705379bc100SJani Nikula 		pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
3706b66a8abaSAnkit Nautiyal 		if (DISPLAY_VER(dev_priv) >= 14)
3707b66a8abaSAnkit Nautiyal 			pipe_config->lane_count =
3708b66a8abaSAnkit Nautiyal 				((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
3709b66a8abaSAnkit Nautiyal 		else
3710379bc100SJani Nikula 			pipe_config->lane_count = 4;
3711379bc100SJani Nikula 		break;
3712379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_SST:
3713379bc100SJani Nikula 		if (encoder->type == INTEL_OUTPUT_EDP)
3714379bc100SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP);
3715379bc100SJani Nikula 		else
3716379bc100SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
3717379bc100SJani Nikula 		pipe_config->lane_count =
3718379bc100SJani Nikula 			((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
37196149cb68SVille Syrjälä 
37205cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
37215cd06644SVille Syrjälä 					       &pipe_config->dp_m_n);
37225cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
37236149cb68SVille Syrjälä 					       &pipe_config->dp_m2_n2);
37248aa940c8SMaarten Lankhorst 
3725005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 11) {
3726ef79fafeSVille Syrjälä 			i915_reg_t dp_tp_ctl = dp_tp_ctl_reg(encoder, pipe_config);
37278aa940c8SMaarten Lankhorst 
37288aa940c8SMaarten Lankhorst 			pipe_config->fec_enable =
3729f7960e7fSJani Nikula 				intel_de_read(dev_priv, dp_tp_ctl) & DP_TP_CTL_FEC_ENABLE;
37308aa940c8SMaarten Lankhorst 
373147bdb1caSJani Nikula 			drm_dbg_kms(&dev_priv->drm,
373247bdb1caSJani Nikula 				    "[ENCODER:%d:%s] Fec status: %u\n",
37338aa940c8SMaarten Lankhorst 				    encoder->base.base.id, encoder->base.name,
37348aa940c8SMaarten Lankhorst 				    pipe_config->fec_enable);
37358aa940c8SMaarten Lankhorst 		}
37368aa940c8SMaarten Lankhorst 
37377ffa2f27SJani Nikula 		if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
3738a44289b9SUma Shankar 			pipe_config->infoframes.enable |=
3739a44289b9SUma Shankar 				intel_lspcon_infoframes_enabled(encoder, pipe_config);
3740a44289b9SUma Shankar 		else
3741dee66f3eSGwan-gyeong Mun 			pipe_config->infoframes.enable |=
3742dee66f3eSGwan-gyeong Mun 				intel_hdmi_infoframes_enabled(encoder, pipe_config);
3743379bc100SJani Nikula 		break;
374465213594SJani Nikula 	case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
374565213594SJani Nikula 		if (!HAS_DP20(dev_priv)) {
374665213594SJani Nikula 			/* FDI */
374765213594SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
374865213594SJani Nikula 			break;
374965213594SJani Nikula 		}
375065213594SJani Nikula 		fallthrough; /* 128b/132b */
3751379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_MST:
3752379bc100SJani Nikula 		pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
3753379bc100SJani Nikula 		pipe_config->lane_count =
3754379bc100SJani Nikula 			((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
37556671c367SJosé Roberto de Souza 
3756005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12)
37576671c367SJosé Roberto de Souza 			pipe_config->mst_master_transcoder =
37586671c367SJosé Roberto de Souza 					REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
37596671c367SJosé Roberto de Souza 
37605cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
37615cd06644SVille Syrjälä 					       &pipe_config->dp_m_n);
3762dee66f3eSGwan-gyeong Mun 
3763dee66f3eSGwan-gyeong Mun 		pipe_config->infoframes.enable |=
3764dee66f3eSGwan-gyeong Mun 			intel_hdmi_infoframes_enabled(encoder, pipe_config);
3765379bc100SJani Nikula 		break;
3766379bc100SJani Nikula 	default:
3767379bc100SJani Nikula 		break;
3768379bc100SJani Nikula 	}
37690385eceaSManasi Navare }
37700385eceaSManasi Navare 
3771351221ffSVille Syrjälä static void intel_ddi_get_config(struct intel_encoder *encoder,
37720385eceaSManasi Navare 				 struct intel_crtc_state *pipe_config)
37730385eceaSManasi Navare {
37740385eceaSManasi Navare 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
37750385eceaSManasi Navare 	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
37760385eceaSManasi Navare 
37770385eceaSManasi Navare 	/* XXX: DSI transcoder paranoia */
37780385eceaSManasi Navare 	if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)))
37790385eceaSManasi Navare 		return;
37800385eceaSManasi Navare 
37810385eceaSManasi Navare 	intel_ddi_read_func_ctl(encoder, pipe_config);
3782379bc100SJani Nikula 
37835b616a29SJani Nikula 	intel_ddi_mso_get_config(encoder, pipe_config);
37845b616a29SJani Nikula 
3785379bc100SJani Nikula 	pipe_config->has_audio =
3786379bc100SJani Nikula 		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
3787379bc100SJani Nikula 
3788822e5ae7SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_EDP)
3789822e5ae7SVille Syrjälä 		intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp);
3790379bc100SJani Nikula 
3791351221ffSVille Syrjälä 	ddi_dotclock_get(pipe_config);
3792379bc100SJani Nikula 
37932446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3794379bc100SJani Nikula 		pipe_config->lane_lat_optim_mask =
3795379bc100SJani Nikula 			bxt_ddi_phy_get_lane_lat_optim_mask(encoder);
3796379bc100SJani Nikula 
3797379bc100SJani Nikula 	intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
3798379bc100SJani Nikula 
3799379bc100SJani Nikula 	intel_hdmi_read_gcp_infoframe(encoder, pipe_config);
3800379bc100SJani Nikula 
3801379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3802379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_AVI,
3803379bc100SJani Nikula 			     &pipe_config->infoframes.avi);
3804379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3805379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_SPD,
3806379bc100SJani Nikula 			     &pipe_config->infoframes.spd);
3807379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3808379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_VENDOR,
3809379bc100SJani Nikula 			     &pipe_config->infoframes.hdmi);
3810379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3811379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_DRM,
3812379bc100SJani Nikula 			     &pipe_config->infoframes.drm);
381302d8ea47SVille Syrjälä 
3814005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
3815dc5b8ed5SVille Syrjälä 		bdw_get_trans_port_sync_config(pipe_config);
3816dee66f3eSGwan-gyeong Mun 
3817dee66f3eSGwan-gyeong Mun 	intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
38182c3928e4SGwan-gyeong Mun 	intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
381978b772e1SJosé Roberto de Souza 
382078b772e1SJosé Roberto de Souza 	intel_psr_get_config(encoder, pipe_config);
382161a60df6SVille Syrjälä 
382261a60df6SVille Syrjälä 	intel_audio_codec_get_config(encoder, pipe_config);
3823379bc100SJani Nikula }
3824379bc100SJani Nikula 
3825351221ffSVille Syrjälä void intel_ddi_get_clock(struct intel_encoder *encoder,
3826351221ffSVille Syrjälä 			 struct intel_crtc_state *crtc_state,
3827351221ffSVille Syrjälä 			 struct intel_shared_dpll *pll)
3828351221ffSVille Syrjälä {
3829351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3830351221ffSVille Syrjälä 	enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
3831351221ffSVille Syrjälä 	struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
3832351221ffSVille Syrjälä 	bool pll_active;
3833351221ffSVille Syrjälä 
3834086877a1SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
3835086877a1SVille Syrjälä 		return;
3836086877a1SVille Syrjälä 
3837351221ffSVille Syrjälä 	port_dpll->pll = pll;
3838351221ffSVille Syrjälä 	pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
3839351221ffSVille Syrjälä 	drm_WARN_ON(&i915->drm, !pll_active);
3840351221ffSVille Syrjälä 
3841351221ffSVille Syrjälä 	icl_set_active_port_dpll(crtc_state, port_dpll_id);
3842351221ffSVille Syrjälä 
3843351221ffSVille Syrjälä 	crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
3844351221ffSVille Syrjälä 						     &crtc_state->dpll_hw_state);
3845351221ffSVille Syrjälä }
3846351221ffSVille Syrjälä 
384751390cc0SRadhakrishna Sripada static void mtl_ddi_get_config(struct intel_encoder *encoder,
384851390cc0SRadhakrishna Sripada 			       struct intel_crtc_state *crtc_state)
384951390cc0SRadhakrishna Sripada {
385051390cc0SRadhakrishna Sripada 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
385151390cc0SRadhakrishna Sripada 	enum phy phy = intel_port_to_phy(i915, encoder->port);
38527dee06bcSMika Kahola 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
385351390cc0SRadhakrishna Sripada 
38547dee06bcSMika Kahola 	if (intel_tc_port_in_tbt_alt_mode(dig_port)) {
38557dee06bcSMika Kahola 		crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
38567dee06bcSMika Kahola 	} else if (intel_is_c10phy(i915, phy)) {
385751390cc0SRadhakrishna Sripada 		intel_c10pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c10);
385851390cc0SRadhakrishna Sripada 		intel_c10pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c10);
3859f1f9e627SMika Kahola 		crtc_state->port_clock = intel_c10pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c10);
3860929f527aSMika Kahola 	} else {
3861929f527aSMika Kahola 		intel_c20pll_readout_hw_state(encoder, &crtc_state->cx0pll_state.c20);
3862f968a253SMika Kahola 		intel_c20pll_dump_hw_state(i915, &crtc_state->cx0pll_state.c20);
3863f1f9e627SMika Kahola 		crtc_state->port_clock = intel_c20pll_calc_port_clock(encoder, &crtc_state->cx0pll_state.c20);
3864929f527aSMika Kahola 	}
3865929f527aSMika Kahola 
386651390cc0SRadhakrishna Sripada 	intel_ddi_get_config(encoder, crtc_state);
386751390cc0SRadhakrishna Sripada }
386851390cc0SRadhakrishna Sripada 
3869865b73eaSMatt Roper static void dg2_ddi_get_config(struct intel_encoder *encoder,
3870865b73eaSMatt Roper 				struct intel_crtc_state *crtc_state)
3871865b73eaSMatt Roper {
3872865b73eaSMatt Roper 	intel_mpllb_readout_hw_state(encoder, &crtc_state->mpllb_state);
3873865b73eaSMatt Roper 	crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->mpllb_state);
3874865b73eaSMatt Roper 
3875865b73eaSMatt Roper 	intel_ddi_get_config(encoder, crtc_state);
3876865b73eaSMatt Roper }
3877865b73eaSMatt Roper 
3878351221ffSVille Syrjälä static void adls_ddi_get_config(struct intel_encoder *encoder,
3879351221ffSVille Syrjälä 				struct intel_crtc_state *crtc_state)
3880351221ffSVille Syrjälä {
3881351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, adls_ddi_get_pll(encoder));
3882351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3883351221ffSVille Syrjälä }
3884351221ffSVille Syrjälä 
3885351221ffSVille Syrjälä static void rkl_ddi_get_config(struct intel_encoder *encoder,
3886351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3887351221ffSVille Syrjälä {
3888351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, rkl_ddi_get_pll(encoder));
3889351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3890351221ffSVille Syrjälä }
3891351221ffSVille Syrjälä 
3892351221ffSVille Syrjälä static void dg1_ddi_get_config(struct intel_encoder *encoder,
3893351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3894351221ffSVille Syrjälä {
3895351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, dg1_ddi_get_pll(encoder));
3896351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3897351221ffSVille Syrjälä }
3898351221ffSVille Syrjälä 
3899351221ffSVille Syrjälä static void icl_ddi_combo_get_config(struct intel_encoder *encoder,
3900351221ffSVille Syrjälä 				     struct intel_crtc_state *crtc_state)
3901351221ffSVille Syrjälä {
3902351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, icl_ddi_combo_get_pll(encoder));
3903351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3904351221ffSVille Syrjälä }
3905351221ffSVille Syrjälä 
39067c1da068SImre Deak static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll)
39077c1da068SImre Deak {
39087c1da068SImre Deak 	return pll->info->id == DPLL_ID_ICL_TBTPLL;
39097c1da068SImre Deak }
39107c1da068SImre Deak 
39117c1da068SImre Deak static enum icl_port_dpll_id
39127c1da068SImre Deak icl_ddi_tc_port_pll_type(struct intel_encoder *encoder,
39137c1da068SImre Deak 			 const struct intel_crtc_state *crtc_state)
39147c1da068SImre Deak {
39157c1da068SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
39167c1da068SImre Deak 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
39177c1da068SImre Deak 
39187c1da068SImre Deak 	if (drm_WARN_ON(&i915->drm, !pll))
39197c1da068SImre Deak 		return ICL_PORT_DPLL_DEFAULT;
39207c1da068SImre Deak 
39217c1da068SImre Deak 	if (icl_ddi_tc_pll_is_tbt(pll))
39227c1da068SImre Deak 		return ICL_PORT_DPLL_DEFAULT;
39237c1da068SImre Deak 	else
39247c1da068SImre Deak 		return ICL_PORT_DPLL_MG_PHY;
39257c1da068SImre Deak }
39267c1da068SImre Deak 
39277c1da068SImre Deak enum icl_port_dpll_id
39287c1da068SImre Deak intel_ddi_port_pll_type(struct intel_encoder *encoder,
39297c1da068SImre Deak 			const struct intel_crtc_state *crtc_state)
39307c1da068SImre Deak {
39317c1da068SImre Deak 	if (!encoder->port_pll_type)
39327c1da068SImre Deak 		return ICL_PORT_DPLL_DEFAULT;
39337c1da068SImre Deak 
39347c1da068SImre Deak 	return encoder->port_pll_type(encoder, crtc_state);
39357c1da068SImre Deak }
39367c1da068SImre Deak 
3937086877a1SVille Syrjälä static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
3938086877a1SVille Syrjälä 				 struct intel_crtc_state *crtc_state,
3939086877a1SVille Syrjälä 				 struct intel_shared_dpll *pll)
3940351221ffSVille Syrjälä {
3941351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3942351221ffSVille Syrjälä 	enum icl_port_dpll_id port_dpll_id;
3943351221ffSVille Syrjälä 	struct icl_port_dpll *port_dpll;
3944351221ffSVille Syrjälä 	bool pll_active;
3945351221ffSVille Syrjälä 
3946086877a1SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
3947086877a1SVille Syrjälä 		return;
3948351221ffSVille Syrjälä 
39497c1da068SImre Deak 	if (icl_ddi_tc_pll_is_tbt(pll))
3950351221ffSVille Syrjälä 		port_dpll_id = ICL_PORT_DPLL_DEFAULT;
3951351221ffSVille Syrjälä 	else
3952351221ffSVille Syrjälä 		port_dpll_id = ICL_PORT_DPLL_MG_PHY;
3953351221ffSVille Syrjälä 
3954351221ffSVille Syrjälä 	port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
3955351221ffSVille Syrjälä 
3956351221ffSVille Syrjälä 	port_dpll->pll = pll;
3957351221ffSVille Syrjälä 	pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
3958351221ffSVille Syrjälä 	drm_WARN_ON(&i915->drm, !pll_active);
3959351221ffSVille Syrjälä 
3960351221ffSVille Syrjälä 	icl_set_active_port_dpll(crtc_state, port_dpll_id);
3961351221ffSVille Syrjälä 
39627c1da068SImre Deak 	if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll))
3963351221ffSVille Syrjälä 		crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port);
3964351221ffSVille Syrjälä 	else
3965351221ffSVille Syrjälä 		crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
3966351221ffSVille Syrjälä 							     &crtc_state->dpll_hw_state);
3967086877a1SVille Syrjälä }
3968351221ffSVille Syrjälä 
3969086877a1SVille Syrjälä static void icl_ddi_tc_get_config(struct intel_encoder *encoder,
3970086877a1SVille Syrjälä 				  struct intel_crtc_state *crtc_state)
3971086877a1SVille Syrjälä {
3972086877a1SVille Syrjälä 	icl_ddi_tc_get_clock(encoder, crtc_state, icl_ddi_tc_get_pll(encoder));
3973351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3974351221ffSVille Syrjälä }
3975351221ffSVille Syrjälä 
3976351221ffSVille Syrjälä static void bxt_ddi_get_config(struct intel_encoder *encoder,
3977351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3978351221ffSVille Syrjälä {
3979351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, bxt_ddi_get_pll(encoder));
3980351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3981351221ffSVille Syrjälä }
3982351221ffSVille Syrjälä 
3983351221ffSVille Syrjälä static void skl_ddi_get_config(struct intel_encoder *encoder,
3984351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3985351221ffSVille Syrjälä {
3986351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, skl_ddi_get_pll(encoder));
3987351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3988351221ffSVille Syrjälä }
3989351221ffSVille Syrjälä 
3990351221ffSVille Syrjälä void hsw_ddi_get_config(struct intel_encoder *encoder,
3991351221ffSVille Syrjälä 			struct intel_crtc_state *crtc_state)
3992351221ffSVille Syrjälä {
3993351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, hsw_ddi_get_pll(encoder));
3994351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3995351221ffSVille Syrjälä }
3996351221ffSVille Syrjälä 
3997f9e76a6eSImre Deak static void intel_ddi_sync_state(struct intel_encoder *encoder,
3998f9e76a6eSImre Deak 				 const struct intel_crtc_state *crtc_state)
3999f9e76a6eSImre Deak {
40007194dc99SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
40017194dc99SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
40027194dc99SImre Deak 
40037194dc99SImre Deak 	if (intel_phy_is_tc(i915, phy))
40042a4d292fSImre Deak 		intel_tc_port_sanitize_mode(enc_to_dig_port(encoder),
40052a4d292fSImre Deak 					    crtc_state);
40067194dc99SImre Deak 
40077194dc99SImre Deak 	if (crtc_state && intel_crtc_has_dp_encoder(crtc_state))
4008f9e76a6eSImre Deak 		intel_dp_sync_state(encoder, crtc_state);
4009f9e76a6eSImre Deak }
4010f9e76a6eSImre Deak 
4011b671d6efSImre Deak static bool intel_ddi_initial_fastset_check(struct intel_encoder *encoder,
4012b671d6efSImre Deak 					    struct intel_crtc_state *crtc_state)
4013b671d6efSImre Deak {
4014eddb4afcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4015eddb4afcSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4016eddb4afcSVille Syrjälä 	bool fastset = true;
4017b671d6efSImre Deak 
4018eddb4afcSVille Syrjälä 	if (intel_phy_is_tc(i915, phy)) {
4019eddb4afcSVille Syrjälä 		drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute TC port DPLLs\n",
4020eddb4afcSVille Syrjälä 			    encoder->base.base.id, encoder->base.name);
4021eddb4afcSVille Syrjälä 		crtc_state->uapi.mode_changed = true;
4022eddb4afcSVille Syrjälä 		fastset = false;
4023eddb4afcSVille Syrjälä 	}
4024eddb4afcSVille Syrjälä 
4025eddb4afcSVille Syrjälä 	if (intel_crtc_has_dp_encoder(crtc_state) &&
4026eddb4afcSVille Syrjälä 	    !intel_dp_initial_fastset_check(encoder, crtc_state))
4027eddb4afcSVille Syrjälä 		fastset = false;
4028eddb4afcSVille Syrjälä 
4029eddb4afcSVille Syrjälä 	return fastset;
4030b671d6efSImre Deak }
4031b671d6efSImre Deak 
4032379bc100SJani Nikula static enum intel_output_type
4033379bc100SJani Nikula intel_ddi_compute_output_type(struct intel_encoder *encoder,
4034379bc100SJani Nikula 			      struct intel_crtc_state *crtc_state,
4035379bc100SJani Nikula 			      struct drm_connector_state *conn_state)
4036379bc100SJani Nikula {
4037379bc100SJani Nikula 	switch (conn_state->connector->connector_type) {
4038379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_HDMIA:
4039379bc100SJani Nikula 		return INTEL_OUTPUT_HDMI;
4040379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_eDP:
4041379bc100SJani Nikula 		return INTEL_OUTPUT_EDP;
4042379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_DisplayPort:
4043379bc100SJani Nikula 		return INTEL_OUTPUT_DP;
4044379bc100SJani Nikula 	default:
4045379bc100SJani Nikula 		MISSING_CASE(conn_state->connector->connector_type);
4046379bc100SJani Nikula 		return INTEL_OUTPUT_UNUSED;
4047379bc100SJani Nikula 	}
4048379bc100SJani Nikula }
4049379bc100SJani Nikula 
4050379bc100SJani Nikula static int intel_ddi_compute_config(struct intel_encoder *encoder,
4051379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config,
4052379bc100SJani Nikula 				    struct drm_connector_state *conn_state)
4053379bc100SJani Nikula {
40542225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
4055379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4056379bc100SJani Nikula 	enum port port = encoder->port;
4057379bc100SJani Nikula 	int ret;
4058379bc100SJani Nikula 
405910cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
4060379bc100SJani Nikula 		pipe_config->cpu_transcoder = TRANSCODER_EDP;
4061379bc100SJani Nikula 
4062bdacf087SAnshuman Gupta 	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
406334682d60SVille Syrjälä 		pipe_config->has_hdmi_sink =
406434682d60SVille Syrjälä 			intel_hdmi_compute_has_hdmi_sink(encoder, pipe_config, conn_state);
406534682d60SVille Syrjälä 
4066379bc100SJani Nikula 		ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
4067bdacf087SAnshuman Gupta 	} else {
4068379bc100SJani Nikula 		ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
4069bdacf087SAnshuman Gupta 	}
4070bdacf087SAnshuman Gupta 
4071379bc100SJani Nikula 	if (ret)
4072379bc100SJani Nikula 		return ret;
4073379bc100SJani Nikula 
4074379bc100SJani Nikula 	if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A &&
4075379bc100SJani Nikula 	    pipe_config->cpu_transcoder == TRANSCODER_EDP)
4076379bc100SJani Nikula 		pipe_config->pch_pfit.force_thru =
4077379bc100SJani Nikula 			pipe_config->pch_pfit.enabled ||
4078379bc100SJani Nikula 			pipe_config->crc_enabled;
4079379bc100SJani Nikula 
40802446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4081379bc100SJani Nikula 		pipe_config->lane_lat_optim_mask =
4082379bc100SJani Nikula 			bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
4083379bc100SJani Nikula 
4084379bc100SJani Nikula 	intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
4085379bc100SJani Nikula 
4086379bc100SJani Nikula 	return 0;
4087379bc100SJani Nikula }
4088379bc100SJani Nikula 
4089b50a1aa6SManasi Navare static bool mode_equal(const struct drm_display_mode *mode1,
4090b50a1aa6SManasi Navare 		       const struct drm_display_mode *mode2)
4091b50a1aa6SManasi Navare {
4092b50a1aa6SManasi Navare 	return drm_mode_match(mode1, mode2,
4093b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_TIMINGS |
4094b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_FLAGS |
4095b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_3D_FLAGS) &&
4096b50a1aa6SManasi Navare 		mode1->clock == mode2->clock; /* we want an exact match */
4097b50a1aa6SManasi Navare }
4098b50a1aa6SManasi Navare 
4099b50a1aa6SManasi Navare static bool m_n_equal(const struct intel_link_m_n *m_n_1,
4100b50a1aa6SManasi Navare 		      const struct intel_link_m_n *m_n_2)
4101b50a1aa6SManasi Navare {
4102b50a1aa6SManasi Navare 	return m_n_1->tu == m_n_2->tu &&
41035f721a5dSVille Syrjälä 		m_n_1->data_m == m_n_2->data_m &&
41045f721a5dSVille Syrjälä 		m_n_1->data_n == m_n_2->data_n &&
4105b50a1aa6SManasi Navare 		m_n_1->link_m == m_n_2->link_m &&
4106b50a1aa6SManasi Navare 		m_n_1->link_n == m_n_2->link_n;
4107b50a1aa6SManasi Navare }
4108b50a1aa6SManasi Navare 
4109b50a1aa6SManasi Navare static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
4110b50a1aa6SManasi Navare 				       const struct intel_crtc_state *crtc_state2)
4111b50a1aa6SManasi Navare {
4112b50a1aa6SManasi Navare 	return crtc_state1->hw.active && crtc_state2->hw.active &&
4113b50a1aa6SManasi Navare 		crtc_state1->output_types == crtc_state2->output_types &&
4114b50a1aa6SManasi Navare 		crtc_state1->output_format == crtc_state2->output_format &&
4115b50a1aa6SManasi Navare 		crtc_state1->lane_count == crtc_state2->lane_count &&
4116b50a1aa6SManasi Navare 		crtc_state1->port_clock == crtc_state2->port_clock &&
4117b50a1aa6SManasi Navare 		mode_equal(&crtc_state1->hw.adjusted_mode,
4118b50a1aa6SManasi Navare 			   &crtc_state2->hw.adjusted_mode) &&
4119b50a1aa6SManasi Navare 		m_n_equal(&crtc_state1->dp_m_n, &crtc_state2->dp_m_n);
4120b50a1aa6SManasi Navare }
4121b50a1aa6SManasi Navare 
4122b50a1aa6SManasi Navare static u8
4123b50a1aa6SManasi Navare intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state,
4124b50a1aa6SManasi Navare 				int tile_group_id)
4125b50a1aa6SManasi Navare {
4126b50a1aa6SManasi Navare 	struct drm_connector *connector;
4127b50a1aa6SManasi Navare 	const struct drm_connector_state *conn_state;
4128b50a1aa6SManasi Navare 	struct drm_i915_private *dev_priv = to_i915(ref_crtc_state->uapi.crtc->dev);
4129b50a1aa6SManasi Navare 	struct intel_atomic_state *state =
4130b50a1aa6SManasi Navare 		to_intel_atomic_state(ref_crtc_state->uapi.state);
4131b50a1aa6SManasi Navare 	u8 transcoders = 0;
4132b50a1aa6SManasi Navare 	int i;
4133b50a1aa6SManasi Navare 
4134dc5b8ed5SVille Syrjälä 	/*
4135dc5b8ed5SVille Syrjälä 	 * We don't enable port sync on BDW due to missing w/as and
4136dc5b8ed5SVille Syrjälä 	 * due to not having adjusted the modeset sequence appropriately.
4137dc5b8ed5SVille Syrjälä 	 */
4138005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) < 9)
4139b50a1aa6SManasi Navare 		return 0;
4140b50a1aa6SManasi Navare 
4141b50a1aa6SManasi Navare 	if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP))
4142b50a1aa6SManasi Navare 		return 0;
4143b50a1aa6SManasi Navare 
4144b50a1aa6SManasi Navare 	for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
4145b50a1aa6SManasi Navare 		struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
4146b50a1aa6SManasi Navare 		const struct intel_crtc_state *crtc_state;
4147b50a1aa6SManasi Navare 
4148b50a1aa6SManasi Navare 		if (!crtc)
4149b50a1aa6SManasi Navare 			continue;
4150b50a1aa6SManasi Navare 
4151b50a1aa6SManasi Navare 		if (!connector->has_tile ||
4152b50a1aa6SManasi Navare 		    connector->tile_group->id !=
4153b50a1aa6SManasi Navare 		    tile_group_id)
4154b50a1aa6SManasi Navare 			continue;
4155b50a1aa6SManasi Navare 		crtc_state = intel_atomic_get_new_crtc_state(state,
4156b50a1aa6SManasi Navare 							     crtc);
4157b50a1aa6SManasi Navare 		if (!crtcs_port_sync_compatible(ref_crtc_state,
4158b50a1aa6SManasi Navare 						crtc_state))
4159b50a1aa6SManasi Navare 			continue;
4160b50a1aa6SManasi Navare 		transcoders |= BIT(crtc_state->cpu_transcoder);
4161b50a1aa6SManasi Navare 	}
4162b50a1aa6SManasi Navare 
4163b50a1aa6SManasi Navare 	return transcoders;
4164b50a1aa6SManasi Navare }
4165b50a1aa6SManasi Navare 
4166b50a1aa6SManasi Navare static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
4167b50a1aa6SManasi Navare 					 struct intel_crtc_state *crtc_state,
4168b50a1aa6SManasi Navare 					 struct drm_connector_state *conn_state)
4169b50a1aa6SManasi Navare {
417047bdb1caSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4171b50a1aa6SManasi Navare 	struct drm_connector *connector = conn_state->connector;
4172b50a1aa6SManasi Navare 	u8 port_sync_transcoders = 0;
4173b50a1aa6SManasi Navare 
417447bdb1caSJani Nikula 	drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]",
4175b50a1aa6SManasi Navare 		    encoder->base.base.id, encoder->base.name,
4176b50a1aa6SManasi Navare 		    crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
4177b50a1aa6SManasi Navare 
4178b50a1aa6SManasi Navare 	if (connector->has_tile)
4179b50a1aa6SManasi Navare 		port_sync_transcoders = intel_ddi_port_sync_transcoders(crtc_state,
4180b50a1aa6SManasi Navare 									connector->tile_group->id);
4181b50a1aa6SManasi Navare 
4182b50a1aa6SManasi Navare 	/*
4183b50a1aa6SManasi Navare 	 * EDP Transcoders cannot be ensalved
4184b50a1aa6SManasi Navare 	 * make them a master always when present
4185b50a1aa6SManasi Navare 	 */
4186b50a1aa6SManasi Navare 	if (port_sync_transcoders & BIT(TRANSCODER_EDP))
4187b50a1aa6SManasi Navare 		crtc_state->master_transcoder = TRANSCODER_EDP;
4188b50a1aa6SManasi Navare 	else
4189b50a1aa6SManasi Navare 		crtc_state->master_transcoder = ffs(port_sync_transcoders) - 1;
4190b50a1aa6SManasi Navare 
4191b50a1aa6SManasi Navare 	if (crtc_state->master_transcoder == crtc_state->cpu_transcoder) {
4192b50a1aa6SManasi Navare 		crtc_state->master_transcoder = INVALID_TRANSCODER;
4193b50a1aa6SManasi Navare 		crtc_state->sync_mode_slaves_mask =
4194b50a1aa6SManasi Navare 			port_sync_transcoders & ~BIT(crtc_state->cpu_transcoder);
4195b50a1aa6SManasi Navare 	}
4196b50a1aa6SManasi Navare 
4197b50a1aa6SManasi Navare 	return 0;
4198b50a1aa6SManasi Navare }
4199b50a1aa6SManasi Navare 
4200379bc100SJani Nikula static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
4201379bc100SJani Nikula {
42024a300e65SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->dev);
4203b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
42043e0abc76SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
4205379bc100SJani Nikula 
4206379bc100SJani Nikula 	intel_dp_encoder_flush_work(encoder);
42073e0abc76SImre Deak 	if (intel_phy_is_tc(i915, phy))
4208c5879999SImre Deak 		intel_tc_port_cleanup(dig_port);
42094a300e65SImre Deak 	intel_display_power_flush_work(i915);
4210379bc100SJani Nikula 
4211379bc100SJani Nikula 	drm_encoder_cleanup(encoder);
4212a6c6eac9SAnshuman Gupta 	kfree(dig_port->hdcp_port_data.streams);
4213379bc100SJani Nikula 	kfree(dig_port);
4214379bc100SJani Nikula }
4215379bc100SJani Nikula 
4216764f6729SVille Syrjälä static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
4217764f6729SVille Syrjälä {
4218a82796a2SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->dev);
4219764f6729SVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
4220a82796a2SImre Deak 	struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
4221a82796a2SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
4222764f6729SVille Syrjälä 
4223764f6729SVille Syrjälä 	intel_dp->reset_link_params = true;
4224764f6729SVille Syrjälä 
4225764f6729SVille Syrjälä 	intel_pps_encoder_reset(intel_dp);
4226a82796a2SImre Deak 
4227a82796a2SImre Deak 	if (intel_phy_is_tc(i915, phy))
4228a82796a2SImre Deak 		intel_tc_port_init_mode(dig_port);
4229764f6729SVille Syrjälä }
4230764f6729SVille Syrjälä 
4231c598c335SImre Deak static int intel_ddi_encoder_late_register(struct drm_encoder *_encoder)
4232c598c335SImre Deak {
4233c598c335SImre Deak 	struct intel_encoder *encoder = to_intel_encoder(_encoder);
4234c598c335SImre Deak 
4235c598c335SImre Deak 	intel_tc_port_link_reset(enc_to_dig_port(encoder));
4236c598c335SImre Deak 
4237c598c335SImre Deak 	return 0;
4238c598c335SImre Deak }
4239c598c335SImre Deak 
4240379bc100SJani Nikula static const struct drm_encoder_funcs intel_ddi_funcs = {
4241764f6729SVille Syrjälä 	.reset = intel_ddi_encoder_reset,
4242379bc100SJani Nikula 	.destroy = intel_ddi_encoder_destroy,
4243c598c335SImre Deak 	.late_register = intel_ddi_encoder_late_register,
4244379bc100SJani Nikula };
4245379bc100SJani Nikula 
4246379bc100SJani Nikula static struct intel_connector *
42477801f3b7SLucas De Marchi intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
4248379bc100SJani Nikula {
424923ef6194SJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
4250379bc100SJani Nikula 	struct intel_connector *connector;
42517801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4252379bc100SJani Nikula 
4253379bc100SJani Nikula 	connector = intel_connector_alloc();
4254379bc100SJani Nikula 	if (!connector)
4255379bc100SJani Nikula 		return NULL;
4256379bc100SJani Nikula 
42577801f3b7SLucas De Marchi 	dig_port->dp.output_reg = DDI_BUF_CTL(port);
425823ef6194SJosé Roberto de Souza 	if (DISPLAY_VER(i915) >= 14)
425923ef6194SJosé Roberto de Souza 		dig_port->dp.prepare_link_retrain = mtl_ddi_prepare_link_retrain;
426023ef6194SJosé Roberto de Souza 	else
42617801f3b7SLucas De Marchi 		dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain;
42627801f3b7SLucas De Marchi 	dig_port->dp.set_link_train = intel_ddi_set_link_train;
42637801f3b7SLucas De Marchi 	dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train;
4264eee3f911SVille Syrjälä 
42657801f3b7SLucas De Marchi 	dig_port->dp.voltage_max = intel_ddi_dp_voltage_max;
42667801f3b7SLucas De Marchi 	dig_port->dp.preemph_max = intel_ddi_dp_preemph_max;
426753de0a20SVille Syrjälä 
42687801f3b7SLucas De Marchi 	if (!intel_dp_init_connector(dig_port, connector)) {
4269379bc100SJani Nikula 		kfree(connector);
4270379bc100SJani Nikula 		return NULL;
4271379bc100SJani Nikula 	}
4272379bc100SJani Nikula 
42736306d8dbSHans de Goede 	if (dig_port->base.type == INTEL_OUTPUT_EDP) {
42746306d8dbSHans de Goede 		struct drm_device *dev = dig_port->base.base.dev;
42756306d8dbSHans de Goede 		struct drm_privacy_screen *privacy_screen;
42766306d8dbSHans de Goede 
42776306d8dbSHans de Goede 		privacy_screen = drm_privacy_screen_get(dev->dev, NULL);
42786306d8dbSHans de Goede 		if (!IS_ERR(privacy_screen)) {
42796306d8dbSHans de Goede 			drm_connector_attach_privacy_screen_provider(&connector->base,
42806306d8dbSHans de Goede 								     privacy_screen);
42816306d8dbSHans de Goede 		} else if (PTR_ERR(privacy_screen) != -ENODEV) {
42826306d8dbSHans de Goede 			drm_warn(dev, "Error getting privacy-screen\n");
42836306d8dbSHans de Goede 		}
42846306d8dbSHans de Goede 	}
42856306d8dbSHans de Goede 
4286379bc100SJani Nikula 	return connector;
4287379bc100SJani Nikula }
4288379bc100SJani Nikula 
4289379bc100SJani Nikula static int modeset_pipe(struct drm_crtc *crtc,
4290379bc100SJani Nikula 			struct drm_modeset_acquire_ctx *ctx)
4291379bc100SJani Nikula {
4292379bc100SJani Nikula 	struct drm_atomic_state *state;
4293379bc100SJani Nikula 	struct drm_crtc_state *crtc_state;
4294379bc100SJani Nikula 	int ret;
4295379bc100SJani Nikula 
4296379bc100SJani Nikula 	state = drm_atomic_state_alloc(crtc->dev);
4297379bc100SJani Nikula 	if (!state)
4298379bc100SJani Nikula 		return -ENOMEM;
4299379bc100SJani Nikula 
4300379bc100SJani Nikula 	state->acquire_ctx = ctx;
430176ec6927SVille Syrjälä 	to_intel_atomic_state(state)->internal = true;
4302379bc100SJani Nikula 
4303379bc100SJani Nikula 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
4304379bc100SJani Nikula 	if (IS_ERR(crtc_state)) {
4305379bc100SJani Nikula 		ret = PTR_ERR(crtc_state);
4306379bc100SJani Nikula 		goto out;
4307379bc100SJani Nikula 	}
4308379bc100SJani Nikula 
4309379bc100SJani Nikula 	crtc_state->connectors_changed = true;
4310379bc100SJani Nikula 
4311379bc100SJani Nikula 	ret = drm_atomic_commit(state);
4312379bc100SJani Nikula out:
4313379bc100SJani Nikula 	drm_atomic_state_put(state);
4314379bc100SJani Nikula 
4315379bc100SJani Nikula 	return ret;
4316379bc100SJani Nikula }
4317379bc100SJani Nikula 
4318379bc100SJani Nikula static int intel_hdmi_reset_link(struct intel_encoder *encoder,
4319379bc100SJani Nikula 				 struct drm_modeset_acquire_ctx *ctx)
4320379bc100SJani Nikula {
4321379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4322b7d02c3aSVille Syrjälä 	struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
4323379bc100SJani Nikula 	struct intel_connector *connector = hdmi->attached_connector;
4324379bc100SJani Nikula 	struct i2c_adapter *adapter =
4325379bc100SJani Nikula 		intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
4326379bc100SJani Nikula 	struct drm_connector_state *conn_state;
4327379bc100SJani Nikula 	struct intel_crtc_state *crtc_state;
4328379bc100SJani Nikula 	struct intel_crtc *crtc;
4329379bc100SJani Nikula 	u8 config;
4330379bc100SJani Nikula 	int ret;
4331379bc100SJani Nikula 
4332379bc100SJani Nikula 	if (!connector || connector->base.status != connector_status_connected)
4333379bc100SJani Nikula 		return 0;
4334379bc100SJani Nikula 
4335379bc100SJani Nikula 	ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex,
4336379bc100SJani Nikula 			       ctx);
4337379bc100SJani Nikula 	if (ret)
4338379bc100SJani Nikula 		return ret;
4339379bc100SJani Nikula 
4340379bc100SJani Nikula 	conn_state = connector->base.state;
4341379bc100SJani Nikula 
4342379bc100SJani Nikula 	crtc = to_intel_crtc(conn_state->crtc);
4343379bc100SJani Nikula 	if (!crtc)
4344379bc100SJani Nikula 		return 0;
4345379bc100SJani Nikula 
4346379bc100SJani Nikula 	ret = drm_modeset_lock(&crtc->base.mutex, ctx);
4347379bc100SJani Nikula 	if (ret)
4348379bc100SJani Nikula 		return ret;
4349379bc100SJani Nikula 
4350379bc100SJani Nikula 	crtc_state = to_intel_crtc_state(crtc->base.state);
4351379bc100SJani Nikula 
43521de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm,
43531de143ccSPankaj Bharadiya 		    !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI));
4354379bc100SJani Nikula 
43551326a92cSMaarten Lankhorst 	if (!crtc_state->hw.active)
4356379bc100SJani Nikula 		return 0;
4357379bc100SJani Nikula 
4358379bc100SJani Nikula 	if (!crtc_state->hdmi_high_tmds_clock_ratio &&
4359379bc100SJani Nikula 	    !crtc_state->hdmi_scrambling)
4360379bc100SJani Nikula 		return 0;
4361379bc100SJani Nikula 
4362379bc100SJani Nikula 	if (conn_state->commit &&
4363379bc100SJani Nikula 	    !try_wait_for_completion(&conn_state->commit->hw_done))
4364379bc100SJani Nikula 		return 0;
4365379bc100SJani Nikula 
4366379bc100SJani Nikula 	ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
4367379bc100SJani Nikula 	if (ret < 0) {
43685d844091SVille Syrjälä 		drm_err(&dev_priv->drm, "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n",
43695d844091SVille Syrjälä 			connector->base.base.id, connector->base.name, ret);
4370379bc100SJani Nikula 		return 0;
4371379bc100SJani Nikula 	}
4372379bc100SJani Nikula 
4373379bc100SJani Nikula 	if (!!(config & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) ==
4374379bc100SJani Nikula 	    crtc_state->hdmi_high_tmds_clock_ratio &&
4375379bc100SJani Nikula 	    !!(config & SCDC_SCRAMBLING_ENABLE) ==
4376379bc100SJani Nikula 	    crtc_state->hdmi_scrambling)
4377379bc100SJani Nikula 		return 0;
4378379bc100SJani Nikula 
4379379bc100SJani Nikula 	/*
4380379bc100SJani Nikula 	 * HDMI 2.0 says that one should not send scrambled data
4381379bc100SJani Nikula 	 * prior to configuring the sink scrambling, and that
4382379bc100SJani Nikula 	 * TMDS clock/data transmission should be suspended when
4383379bc100SJani Nikula 	 * changing the TMDS clock rate in the sink. So let's
4384379bc100SJani Nikula 	 * just do a full modeset here, even though some sinks
4385379bc100SJani Nikula 	 * would be perfectly happy if were to just reconfigure
4386379bc100SJani Nikula 	 * the SCDC settings on the fly.
4387379bc100SJani Nikula 	 */
4388379bc100SJani Nikula 	return modeset_pipe(&crtc->base, ctx);
4389379bc100SJani Nikula }
4390379bc100SJani Nikula 
43913944709dSImre Deak static enum intel_hotplug_state
43923944709dSImre Deak intel_ddi_hotplug(struct intel_encoder *encoder,
43938c8919c7SImre Deak 		  struct intel_connector *connector)
4394379bc100SJani Nikula {
4395b4df5405SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4396b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
4397699390f7SVille Syrjälä 	struct intel_dp *intel_dp = &dig_port->dp;
4398b4df5405SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4399b4df5405SImre Deak 	bool is_tc = intel_phy_is_tc(i915, phy);
4400379bc100SJani Nikula 	struct drm_modeset_acquire_ctx ctx;
44013944709dSImre Deak 	enum intel_hotplug_state state;
4402379bc100SJani Nikula 	int ret;
4403379bc100SJani Nikula 
4404699390f7SVille Syrjälä 	if (intel_dp->compliance.test_active &&
4405699390f7SVille Syrjälä 	    intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
4406699390f7SVille Syrjälä 		intel_dp_phy_test(encoder);
4407699390f7SVille Syrjälä 		/* just do the PHY test and nothing else */
4408699390f7SVille Syrjälä 		return INTEL_HOTPLUG_UNCHANGED;
4409699390f7SVille Syrjälä 	}
4410699390f7SVille Syrjälä 
44118c8919c7SImre Deak 	state = intel_encoder_hotplug(encoder, connector);
4412379bc100SJani Nikula 
4413c598c335SImre Deak 	if (!intel_tc_port_link_reset(dig_port)) {
441460ded7ccSImre Deak 		intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) {
4415379bc100SJani Nikula 			if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA)
4416379bc100SJani Nikula 				ret = intel_hdmi_reset_link(encoder, &ctx);
4417379bc100SJani Nikula 			else
4418379bc100SJani Nikula 				ret = intel_dp_retrain_link(encoder, &ctx);
4419379bc100SJani Nikula 		}
4420379bc100SJani Nikula 
442160ded7ccSImre Deak 		drm_WARN_ON(encoder->base.dev, ret);
4422c598c335SImre Deak 	}
4423379bc100SJani Nikula 
4424bb80c925SJosé Roberto de Souza 	/*
4425bb80c925SJosé Roberto de Souza 	 * Unpowered type-c dongles can take some time to boot and be
4426bb80c925SJosé Roberto de Souza 	 * responsible, so here giving some time to those dongles to power up
4427bb80c925SJosé Roberto de Souza 	 * and then retrying the probe.
4428bb80c925SJosé Roberto de Souza 	 *
4429bb80c925SJosé Roberto de Souza 	 * On many platforms the HDMI live state signal is known to be
4430bb80c925SJosé Roberto de Souza 	 * unreliable, so we can't use it to detect if a sink is connected or
4431bb80c925SJosé Roberto de Souza 	 * not. Instead we detect if it's connected based on whether we can
4432bb80c925SJosé Roberto de Souza 	 * read the EDID or not. That in turn has a problem during disconnect,
4433bb80c925SJosé Roberto de Souza 	 * since the HPD interrupt may be raised before the DDC lines get
4434bb80c925SJosé Roberto de Souza 	 * disconnected (due to how the required length of DDC vs. HPD
4435bb80c925SJosé Roberto de Souza 	 * connector pins are specified) and so we'll still be able to get a
4436bb80c925SJosé Roberto de Souza 	 * valid EDID. To solve this schedule another detection cycle if this
4437bb80c925SJosé Roberto de Souza 	 * time around we didn't detect any change in the sink's connection
4438bb80c925SJosé Roberto de Souza 	 * status.
4439b4df5405SImre Deak 	 *
4440b4df5405SImre Deak 	 * Type-c connectors which get their HPD signal deasserted then
4441b4df5405SImre Deak 	 * reasserted, without unplugging/replugging the sink from the
4442b4df5405SImre Deak 	 * connector, introduce a delay until the AUX channel communication
4443b4df5405SImre Deak 	 * becomes functional. Retry the detection for 5 seconds on type-c
4444b4df5405SImre Deak 	 * connectors to account for this delay.
4445bb80c925SJosé Roberto de Souza 	 */
4446b4df5405SImre Deak 	if (state == INTEL_HOTPLUG_UNCHANGED &&
4447b4df5405SImre Deak 	    connector->hotplug_retries < (is_tc ? 5 : 1) &&
4448bb80c925SJosé Roberto de Souza 	    !dig_port->dp.is_mst)
4449bb80c925SJosé Roberto de Souza 		state = INTEL_HOTPLUG_RETRY;
4450bb80c925SJosé Roberto de Souza 
44513944709dSImre Deak 	return state;
4452379bc100SJani Nikula }
4453379bc100SJani Nikula 
4454edc0e09cSVille Syrjälä static bool lpt_digital_port_connected(struct intel_encoder *encoder)
4455edc0e09cSVille Syrjälä {
4456edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
44575a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin];
4458edc0e09cSVille Syrjälä 
4459edc0e09cSVille Syrjälä 	return intel_de_read(dev_priv, SDEISR) & bit;
4460edc0e09cSVille Syrjälä }
4461edc0e09cSVille Syrjälä 
4462edc0e09cSVille Syrjälä static bool hsw_digital_port_connected(struct intel_encoder *encoder)
4463edc0e09cSVille Syrjälä {
4464edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
44655a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4466edc0e09cSVille Syrjälä 
4467c7e8a3d6SVille Syrjälä 	return intel_de_read(dev_priv, DEISR) & bit;
4468edc0e09cSVille Syrjälä }
4469edc0e09cSVille Syrjälä 
4470edc0e09cSVille Syrjälä static bool bdw_digital_port_connected(struct intel_encoder *encoder)
4471edc0e09cSVille Syrjälä {
4472edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
44735a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4474edc0e09cSVille Syrjälä 
4475edc0e09cSVille Syrjälä 	return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit;
4476edc0e09cSVille Syrjälä }
4477edc0e09cSVille Syrjälä 
4478379bc100SJani Nikula static struct intel_connector *
44797801f3b7SLucas De Marchi intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port)
4480379bc100SJani Nikula {
4481379bc100SJani Nikula 	struct intel_connector *connector;
44827801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4483379bc100SJani Nikula 
4484379bc100SJani Nikula 	connector = intel_connector_alloc();
4485379bc100SJani Nikula 	if (!connector)
4486379bc100SJani Nikula 		return NULL;
4487379bc100SJani Nikula 
44887801f3b7SLucas De Marchi 	dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
44897801f3b7SLucas De Marchi 	intel_hdmi_init_connector(dig_port, connector);
4490379bc100SJani Nikula 
4491379bc100SJani Nikula 	return connector;
4492379bc100SJani Nikula }
4493379bc100SJani Nikula 
44947801f3b7SLucas De Marchi static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
4495379bc100SJani Nikula {
44967801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
4497379bc100SJani Nikula 
44987801f3b7SLucas De Marchi 	if (dig_port->base.port != PORT_A)
4499379bc100SJani Nikula 		return false;
4500379bc100SJani Nikula 
45017801f3b7SLucas De Marchi 	if (dig_port->saved_port_bits & DDI_A_4_LANES)
4502379bc100SJani Nikula 		return false;
4503379bc100SJani Nikula 
4504379bc100SJani Nikula 	/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
4505379bc100SJani Nikula 	 *                     supported configuration
4506379bc100SJani Nikula 	 */
45072446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4508379bc100SJani Nikula 		return true;
4509379bc100SJani Nikula 
4510379bc100SJani Nikula 	return false;
4511379bc100SJani Nikula }
4512379bc100SJani Nikula 
4513379bc100SJani Nikula static int
45147801f3b7SLucas De Marchi intel_ddi_max_lanes(struct intel_digital_port *dig_port)
4515379bc100SJani Nikula {
45167801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
45177801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4518379bc100SJani Nikula 	int max_lanes = 4;
4519379bc100SJani Nikula 
4520005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
4521379bc100SJani Nikula 		return max_lanes;
4522379bc100SJani Nikula 
4523379bc100SJani Nikula 	if (port == PORT_A || port == PORT_E) {
4524f7960e7fSJani Nikula 		if (intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
4525379bc100SJani Nikula 			max_lanes = port == PORT_A ? 4 : 0;
4526379bc100SJani Nikula 		else
4527379bc100SJani Nikula 			/* Both A and E share 2 lanes */
4528379bc100SJani Nikula 			max_lanes = 2;
4529379bc100SJani Nikula 	}
4530379bc100SJani Nikula 
4531379bc100SJani Nikula 	/*
4532379bc100SJani Nikula 	 * Some BIOS might fail to set this bit on port A if eDP
4533379bc100SJani Nikula 	 * wasn't lit up at boot.  Force this bit set when needed
4534379bc100SJani Nikula 	 * so we use the proper lane count for our calculations.
4535379bc100SJani Nikula 	 */
45367801f3b7SLucas De Marchi 	if (intel_ddi_a_force_4_lanes(dig_port)) {
453747bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
453847bdb1caSJani Nikula 			    "Forcing DDI_A_4_LANES for port A\n");
45397801f3b7SLucas De Marchi 		dig_port->saved_port_bits |= DDI_A_4_LANES;
4540379bc100SJani Nikula 		max_lanes = 4;
4541379bc100SJani Nikula 	}
4542379bc100SJani Nikula 
4543379bc100SJani Nikula 	return max_lanes;
4544379bc100SJani Nikula }
4545379bc100SJani Nikula 
4546ed2615a8SMatt Roper static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv,
4547ed2615a8SMatt Roper 				  enum port port)
4548ed2615a8SMatt Roper {
4549ed2615a8SMatt Roper 	if (port >= PORT_D_XELPD)
4550ed2615a8SMatt Roper 		return HPD_PORT_D + port - PORT_D_XELPD;
4551ed2615a8SMatt Roper 	else if (port >= PORT_TC1)
4552ed2615a8SMatt Roper 		return HPD_PORT_TC1 + port - PORT_TC1;
4553ed2615a8SMatt Roper 	else
4554ed2615a8SMatt Roper 		return HPD_PORT_A + port - PORT_A;
4555ed2615a8SMatt Roper }
4556ed2615a8SMatt Roper 
4557229f31e2SLucas De Marchi static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv,
4558229f31e2SLucas De Marchi 				enum port port)
4559229f31e2SLucas De Marchi {
45601d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
45611d8ca002SVille Syrjälä 		return HPD_PORT_C + port - PORT_TC1;
4562229f31e2SLucas De Marchi 	else
4563229f31e2SLucas De Marchi 		return HPD_PORT_A + port - PORT_A;
4564229f31e2SLucas De Marchi }
4565229f31e2SLucas De Marchi 
4566da51e4baSVille Syrjälä static enum hpd_pin tgl_hpd_pin(struct drm_i915_private *dev_priv,
4567da51e4baSVille Syrjälä 				enum port port)
4568da51e4baSVille Syrjälä {
45691d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
45701d8ca002SVille Syrjälä 		return HPD_PORT_TC1 + port - PORT_TC1;
4571da51e4baSVille Syrjälä 	else
4572da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4573da51e4baSVille Syrjälä }
4574da51e4baSVille Syrjälä 
4575da51e4baSVille Syrjälä static enum hpd_pin rkl_hpd_pin(struct drm_i915_private *dev_priv,
4576da51e4baSVille Syrjälä 				enum port port)
4577da51e4baSVille Syrjälä {
4578da51e4baSVille Syrjälä 	if (HAS_PCH_TGP(dev_priv))
4579da51e4baSVille Syrjälä 		return tgl_hpd_pin(dev_priv, port);
4580da51e4baSVille Syrjälä 
45811d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
45821d8ca002SVille Syrjälä 		return HPD_PORT_C + port - PORT_TC1;
4583da51e4baSVille Syrjälä 	else
4584da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4585da51e4baSVille Syrjälä }
4586da51e4baSVille Syrjälä 
4587da51e4baSVille Syrjälä static enum hpd_pin icl_hpd_pin(struct drm_i915_private *dev_priv,
4588da51e4baSVille Syrjälä 				enum port port)
4589da51e4baSVille Syrjälä {
4590da51e4baSVille Syrjälä 	if (port >= PORT_C)
4591da51e4baSVille Syrjälä 		return HPD_PORT_TC1 + port - PORT_C;
4592da51e4baSVille Syrjälä 	else
4593da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4594da51e4baSVille Syrjälä }
4595da51e4baSVille Syrjälä 
4596da51e4baSVille Syrjälä static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv,
4597da51e4baSVille Syrjälä 				enum port port)
4598da51e4baSVille Syrjälä {
4599da51e4baSVille Syrjälä 	if (port == PORT_D)
4600da51e4baSVille Syrjälä 		return HPD_PORT_A;
4601da51e4baSVille Syrjälä 
4602f24d1d45SVille Syrjälä 	if (HAS_PCH_TGP(dev_priv))
4603da51e4baSVille Syrjälä 		return icl_hpd_pin(dev_priv, port);
4604da51e4baSVille Syrjälä 
4605da51e4baSVille Syrjälä 	return HPD_PORT_A + port - PORT_A;
4606da51e4baSVille Syrjälä }
4607da51e4baSVille Syrjälä 
4608c8455098SLyude Paul static enum hpd_pin skl_hpd_pin(struct drm_i915_private *dev_priv, enum port port)
4609c8455098SLyude Paul {
4610c8455098SLyude Paul 	if (HAS_PCH_TGP(dev_priv))
4611c8455098SLyude Paul 		return icl_hpd_pin(dev_priv, port);
4612c8455098SLyude Paul 
4613c8455098SLyude Paul 	return HPD_PORT_A + port - PORT_A;
4614c8455098SLyude Paul }
4615c8455098SLyude Paul 
461636ecb0ecSVille Syrjälä static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port)
461736ecb0ecSVille Syrjälä {
4618005e9537SMatt Roper 	if (DISPLAY_VER(i915) >= 12)
461936ecb0ecSVille Syrjälä 		return port >= PORT_TC1;
4620005e9537SMatt Roper 	else if (DISPLAY_VER(i915) >= 11)
462136ecb0ecSVille Syrjälä 		return port >= PORT_C;
462236ecb0ecSVille Syrjälä 	else
462336ecb0ecSVille Syrjälä 		return false;
462436ecb0ecSVille Syrjälä }
462536ecb0ecSVille Syrjälä 
4626151ec347SImre Deak static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
4627151ec347SImre Deak {
4628151ec347SImre Deak 	intel_dp_encoder_suspend(encoder);
4629b61fad5fSImre Deak }
4630151ec347SImre Deak 
4631b61fad5fSImre Deak static void intel_ddi_tc_encoder_suspend_complete(struct intel_encoder *encoder)
4632b61fad5fSImre Deak {
4633b61fad5fSImre Deak 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4634b61fad5fSImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4635151ec347SImre Deak 
4636c598c335SImre Deak 	intel_tc_port_suspend(dig_port);
4637151ec347SImre Deak }
4638151ec347SImre Deak 
4639151ec347SImre Deak static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
4640151ec347SImre Deak {
4641151ec347SImre Deak 	intel_dp_encoder_shutdown(encoder);
464249c55f7bSVille Syrjälä 	intel_hdmi_encoder_shutdown(encoder);
4643b61fad5fSImre Deak }
4644151ec347SImre Deak 
4645b61fad5fSImre Deak static void intel_ddi_tc_encoder_shutdown_complete(struct intel_encoder *encoder)
4646b61fad5fSImre Deak {
4647b61fad5fSImre Deak 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4648b61fad5fSImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4649151ec347SImre Deak 
4650c5879999SImre Deak 	intel_tc_port_cleanup(dig_port);
4651151ec347SImre Deak }
4652151ec347SImre Deak 
465383566d13SVille Syrjälä #define port_tc_name(port) ((port) - PORT_TC1 + '1')
465483566d13SVille Syrjälä #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1')
465583566d13SVille Syrjälä 
4656379bc100SJani Nikula void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
4657379bc100SJani Nikula {
46587801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port;
465970dfbc29SLucas De Marchi 	struct intel_encoder *encoder;
466045c0673aSJani Nikula 	const struct intel_bios_encoder_data *devdata;
4661f542d671SKai-Heng Feng 	bool init_hdmi, init_dp;
4662d8fe2ab6SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, port);
4663379bc100SJani Nikula 
4664*679df6f1SVille Syrjälä 	if (!assert_port_valid(dev_priv, port))
4665*679df6f1SVille Syrjälä 		return;
4666*679df6f1SVille Syrjälä 
4667ddff9a60SMatt Roper 	/*
4668ddff9a60SMatt Roper 	 * On platforms with HTI (aka HDPORT), if it's enabled at boot it may
4669ddff9a60SMatt Roper 	 * have taken over some of the PHYs and made them unavailable to the
4670ddff9a60SMatt Roper 	 * driver.  In that case we should skip initializing the corresponding
4671ddff9a60SMatt Roper 	 * outputs.
4672ddff9a60SMatt Roper 	 */
467303120fefSJani Nikula 	if (intel_hti_uses_phy(dev_priv, phy)) {
4674ddff9a60SMatt Roper 		drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n",
4675ddff9a60SMatt Roper 			    port_name(port), phy_name(phy));
4676ddff9a60SMatt Roper 		return;
4677ddff9a60SMatt Roper 	}
4678ddff9a60SMatt Roper 
467945c0673aSJani Nikula 	devdata = intel_bios_encoder_data_lookup(dev_priv, port);
468045c0673aSJani Nikula 	if (!devdata) {
468145c0673aSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
468245c0673aSJani Nikula 			    "VBT says port %c is not present\n",
468345c0673aSJani Nikula 			    port_name(port));
468445c0673aSJani Nikula 		return;
468545c0673aSJani Nikula 	}
468645c0673aSJani Nikula 
468745c0673aSJani Nikula 	init_hdmi = intel_bios_encoder_supports_dvi(devdata) ||
468845c0673aSJani Nikula 		intel_bios_encoder_supports_hdmi(devdata);
468945c0673aSJani Nikula 	init_dp = intel_bios_encoder_supports_dp(devdata);
4690379bc100SJani Nikula 
4691db5d650fSVille Syrjälä 	if (intel_bios_encoder_is_lspcon(devdata)) {
4692379bc100SJani Nikula 		/*
4693379bc100SJani Nikula 		 * Lspcon device needs to be driven with DP connector
4694379bc100SJani Nikula 		 * with special detection sequence. So make sure DP
4695379bc100SJani Nikula 		 * is initialized before lspcon.
4696379bc100SJani Nikula 		 */
4697379bc100SJani Nikula 		init_dp = true;
4698379bc100SJani Nikula 		init_hdmi = false;
469947bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm, "VBT says port %c has lspcon\n",
470047bdb1caSJani Nikula 			    port_name(port));
4701379bc100SJani Nikula 	}
4702379bc100SJani Nikula 
4703379bc100SJani Nikula 	if (!init_dp && !init_hdmi) {
470447bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
470547bdb1caSJani Nikula 			    "VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
4706379bc100SJani Nikula 			    port_name(port));
4707379bc100SJani Nikula 		return;
4708379bc100SJani Nikula 	}
4709379bc100SJani Nikula 
4710b4eb76d8SMatt Roper 	if (intel_phy_is_snps(dev_priv, phy) &&
47113a7e2d58SJani Nikula 	    dev_priv->display.snps.phy_failed_calibration & BIT(phy)) {
4712b4eb76d8SMatt Roper 		drm_dbg_kms(&dev_priv->drm,
471382c362f2SLucas De Marchi 			    "SNPS PHY %c failed to calibrate, proceeding anyway\n",
4714b4eb76d8SMatt Roper 			    phy_name(phy));
4715b4eb76d8SMatt Roper 	}
4716b4eb76d8SMatt Roper 
47177801f3b7SLucas De Marchi 	dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
47187801f3b7SLucas De Marchi 	if (!dig_port)
4719379bc100SJani Nikula 		return;
4720379bc100SJani Nikula 
47217801f3b7SLucas De Marchi 	encoder = &dig_port->base;
4722c0a950d1SJani Nikula 	encoder->devdata = devdata;
4723379bc100SJani Nikula 
4724ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) {
4725ed2615a8SMatt Roper 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
4726ed2615a8SMatt Roper 				 DRM_MODE_ENCODER_TMDS,
4727ed2615a8SMatt Roper 				 "DDI %c/PHY %c",
4728ed2615a8SMatt Roper 				 port_name(port - PORT_D_XELPD + PORT_D),
4729ed2615a8SMatt Roper 				 phy_name(phy));
4730ed2615a8SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 12) {
47312d709a5aSVille Syrjälä 		enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
47322d709a5aSVille Syrjälä 
473370dfbc29SLucas De Marchi 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
47342d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
47352d709a5aSVille Syrjälä 				 "DDI %s%c/PHY %s%c",
47362d709a5aSVille Syrjälä 				 port >= PORT_TC1 ? "TC" : "",
473783566d13SVille Syrjälä 				 port >= PORT_TC1 ? port_tc_name(port) : port_name(port),
47382d709a5aSVille Syrjälä 				 tc_port != TC_PORT_NONE ? "TC" : "",
473983566d13SVille Syrjälä 				 tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
4740005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
47412d709a5aSVille Syrjälä 		enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
47422d709a5aSVille Syrjälä 
47432d709a5aSVille Syrjälä 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
47442d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
47452d709a5aSVille Syrjälä 				 "DDI %c%s/PHY %s%c",
47462d709a5aSVille Syrjälä 				 port_name(port),
47472d709a5aSVille Syrjälä 				 port >= PORT_C ? " (TC)" : "",
47482d709a5aSVille Syrjälä 				 tc_port != TC_PORT_NONE ? "TC" : "",
474983566d13SVille Syrjälä 				 tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
47502d709a5aSVille Syrjälä 	} else {
47512d709a5aSVille Syrjälä 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
47522d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
47532d709a5aSVille Syrjälä 				 "DDI %c/PHY %c", port_name(port),  phy_name(phy));
47542d709a5aSVille Syrjälä 	}
4755379bc100SJani Nikula 
475636e5e704SSean Paul 	mutex_init(&dig_port->hdcp_mutex);
475736e5e704SSean Paul 	dig_port->num_hdcp_streams = 0;
475836e5e704SSean Paul 
475970dfbc29SLucas De Marchi 	encoder->hotplug = intel_ddi_hotplug;
476070dfbc29SLucas De Marchi 	encoder->compute_output_type = intel_ddi_compute_output_type;
476170dfbc29SLucas De Marchi 	encoder->compute_config = intel_ddi_compute_config;
4762b50a1aa6SManasi Navare 	encoder->compute_config_late = intel_ddi_compute_config_late;
476370dfbc29SLucas De Marchi 	encoder->enable = intel_enable_ddi;
476470dfbc29SLucas De Marchi 	encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
476570dfbc29SLucas De Marchi 	encoder->pre_enable = intel_ddi_pre_enable;
476670dfbc29SLucas De Marchi 	encoder->disable = intel_disable_ddi;
4767b108bdd0SImre Deak 	encoder->post_pll_disable = intel_ddi_post_pll_disable;
476870dfbc29SLucas De Marchi 	encoder->post_disable = intel_ddi_post_disable;
476970dfbc29SLucas De Marchi 	encoder->update_pipe = intel_ddi_update_pipe;
477070dfbc29SLucas De Marchi 	encoder->get_hw_state = intel_ddi_get_hw_state;
4771f9e76a6eSImre Deak 	encoder->sync_state = intel_ddi_sync_state;
4772b671d6efSImre Deak 	encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
4773151ec347SImre Deak 	encoder->suspend = intel_ddi_encoder_suspend;
4774151ec347SImre Deak 	encoder->shutdown = intel_ddi_encoder_shutdown;
477570dfbc29SLucas De Marchi 	encoder->get_power_domains = intel_ddi_get_power_domains;
477670dfbc29SLucas De Marchi 
477770dfbc29SLucas De Marchi 	encoder->type = INTEL_OUTPUT_DDI;
4778979e1b32SImre Deak 	encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
477970dfbc29SLucas De Marchi 	encoder->port = port;
478070dfbc29SLucas De Marchi 	encoder->cloneable = 0;
478170dfbc29SLucas De Marchi 	encoder->pipe_mask = ~0;
4782da51e4baSVille Syrjälä 
478351390cc0SRadhakrishna Sripada 	if (DISPLAY_VER(dev_priv) >= 14) {
478473fc3abcSMika Kahola 		encoder->enable_clock = intel_mtl_pll_enable;
478573fc3abcSMika Kahola 		encoder->disable_clock = intel_mtl_pll_disable;
47866f0423b0SMika Kahola 		encoder->port_pll_type = intel_mtl_port_pll_type;
478751390cc0SRadhakrishna Sripada 		encoder->get_config = mtl_ddi_get_config;
478851390cc0SRadhakrishna Sripada 	} else if (IS_DG2(dev_priv)) {
4789f82f2563SMatt Roper 		encoder->enable_clock = intel_mpllb_enable;
4790f82f2563SMatt Roper 		encoder->disable_clock = intel_mpllb_disable;
4791865b73eaSMatt Roper 		encoder->get_config = dg2_ddi_get_config;
4792865b73eaSMatt Roper 	} else if (IS_ALDERLAKE_S(dev_priv)) {
479340b316d4SVille Syrjälä 		encoder->enable_clock = adls_ddi_enable_clock;
479440b316d4SVille Syrjälä 		encoder->disable_clock = adls_ddi_disable_clock;
47950fbd8694SVille Syrjälä 		encoder->is_clock_enabled = adls_ddi_is_clock_enabled;
4796351221ffSVille Syrjälä 		encoder->get_config = adls_ddi_get_config;
479740b316d4SVille Syrjälä 	} else if (IS_ROCKETLAKE(dev_priv)) {
479840b316d4SVille Syrjälä 		encoder->enable_clock = rkl_ddi_enable_clock;
479940b316d4SVille Syrjälä 		encoder->disable_clock = rkl_ddi_disable_clock;
48000fbd8694SVille Syrjälä 		encoder->is_clock_enabled = rkl_ddi_is_clock_enabled;
4801351221ffSVille Syrjälä 		encoder->get_config = rkl_ddi_get_config;
480236ecb0ecSVille Syrjälä 	} else if (IS_DG1(dev_priv)) {
480335bb6b1aSVille Syrjälä 		encoder->enable_clock = dg1_ddi_enable_clock;
480435bb6b1aSVille Syrjälä 		encoder->disable_clock = dg1_ddi_disable_clock;
48050fbd8694SVille Syrjälä 		encoder->is_clock_enabled = dg1_ddi_is_clock_enabled;
4806351221ffSVille Syrjälä 		encoder->get_config = dg1_ddi_get_config;
480736ecb0ecSVille Syrjälä 	} else if (IS_JSL_EHL(dev_priv)) {
480836ecb0ecSVille Syrjälä 		if (intel_ddi_is_tc(dev_priv, port)) {
480936ecb0ecSVille Syrjälä 			encoder->enable_clock = jsl_ddi_tc_enable_clock;
481036ecb0ecSVille Syrjälä 			encoder->disable_clock = jsl_ddi_tc_disable_clock;
48110fbd8694SVille Syrjälä 			encoder->is_clock_enabled = jsl_ddi_tc_is_clock_enabled;
48127c1da068SImre Deak 			encoder->port_pll_type = icl_ddi_tc_port_pll_type;
4813351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
481436ecb0ecSVille Syrjälä 		} else {
481536ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_combo_enable_clock;
481636ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_combo_disable_clock;
48170fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
4818351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
481936ecb0ecSVille Syrjälä 		}
4820005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
482136ecb0ecSVille Syrjälä 		if (intel_ddi_is_tc(dev_priv, port)) {
482236ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_tc_enable_clock;
482336ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_tc_disable_clock;
48240fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_tc_is_clock_enabled;
48257c1da068SImre Deak 			encoder->port_pll_type = icl_ddi_tc_port_pll_type;
4826351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_tc_get_config;
482736ecb0ecSVille Syrjälä 		} else {
482836ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_combo_enable_clock;
482936ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_combo_disable_clock;
48300fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
4831351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
483236ecb0ecSVille Syrjälä 		}
48332446e1d6SMatt Roper 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
4834351221ffSVille Syrjälä 		/* BXT/GLK have fixed PLL->port mapping */
4835351221ffSVille Syrjälä 		encoder->get_config = bxt_ddi_get_config;
483693e7e61eSLucas De Marchi 	} else if (DISPLAY_VER(dev_priv) == 9) {
483738e31f1aSVille Syrjälä 		encoder->enable_clock = skl_ddi_enable_clock;
483838e31f1aSVille Syrjälä 		encoder->disable_clock = skl_ddi_disable_clock;
48390fbd8694SVille Syrjälä 		encoder->is_clock_enabled = skl_ddi_is_clock_enabled;
4840351221ffSVille Syrjälä 		encoder->get_config = skl_ddi_get_config;
484138e31f1aSVille Syrjälä 	} else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
4842d135368dSVille Syrjälä 		encoder->enable_clock = hsw_ddi_enable_clock;
4843d135368dSVille Syrjälä 		encoder->disable_clock = hsw_ddi_disable_clock;
48440fbd8694SVille Syrjälä 		encoder->is_clock_enabled = hsw_ddi_is_clock_enabled;
4845351221ffSVille Syrjälä 		encoder->get_config = hsw_ddi_get_config;
4846d135368dSVille Syrjälä 	}
4847d135368dSVille Syrjälä 
4848ea8af87aSMika Kahola 	if (DISPLAY_VER(dev_priv) >= 14) {
4849ea8af87aSMika Kahola 		encoder->set_signal_levels = intel_cx0_phy_set_signal_levels;
4850ea8af87aSMika Kahola 	} else if (IS_DG2(dev_priv)) {
4851193299adSVille Syrjälä 		encoder->set_signal_levels = intel_snps_phy_set_signal_levels;
4852193299adSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) >= 12) {
4853193299adSVille Syrjälä 		if (intel_phy_is_combo(dev_priv, phy))
4854193299adSVille Syrjälä 			encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
4855e722ab8bSVille Syrjälä 		else
4856193299adSVille Syrjälä 			encoder->set_signal_levels = tgl_dkl_phy_set_signal_levels;
4857193299adSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) >= 11) {
4858193299adSVille Syrjälä 		if (intel_phy_is_combo(dev_priv, phy))
4859193299adSVille Syrjälä 			encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
4860193299adSVille Syrjälä 		else
4861193299adSVille Syrjälä 			encoder->set_signal_levels = icl_mg_phy_set_signal_levels;
4862193299adSVille Syrjälä 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
48635f5ada0bSVille Syrjälä 		encoder->set_signal_levels = bxt_ddi_phy_set_signal_levels;
4864193299adSVille Syrjälä 	} else {
4865e722ab8bSVille Syrjälä 		encoder->set_signal_levels = hsw_set_signal_levels;
4866193299adSVille Syrjälä 	}
4867e722ab8bSVille Syrjälä 
4868c40a253bSVille Syrjälä 	intel_ddi_buf_trans_init(encoder);
4869c40a253bSVille Syrjälä 
4870ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
4871ed2615a8SMatt Roper 		encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port);
4872ed2615a8SMatt Roper 	else if (IS_DG1(dev_priv))
4873229f31e2SLucas De Marchi 		encoder->hpd_pin = dg1_hpd_pin(dev_priv, port);
4874229f31e2SLucas De Marchi 	else if (IS_ROCKETLAKE(dev_priv))
4875da51e4baSVille Syrjälä 		encoder->hpd_pin = rkl_hpd_pin(dev_priv, port);
4876005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
4877da51e4baSVille Syrjälä 		encoder->hpd_pin = tgl_hpd_pin(dev_priv, port);
487824ea098bSTejas Upadhyay 	else if (IS_JSL_EHL(dev_priv))
4879da51e4baSVille Syrjälä 		encoder->hpd_pin = ehl_hpd_pin(dev_priv, port);
488093e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 11)
4881da51e4baSVille Syrjälä 		encoder->hpd_pin = icl_hpd_pin(dev_priv, port);
488293e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
4883c8455098SLyude Paul 		encoder->hpd_pin = skl_hpd_pin(dev_priv, port);
4884da51e4baSVille Syrjälä 	else
488503c7e4f1SVille Syrjälä 		encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
4886379bc100SJani Nikula 
4887005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
48887801f3b7SLucas De Marchi 		dig_port->saved_port_bits =
48897801f3b7SLucas De Marchi 			intel_de_read(dev_priv, DDI_BUF_CTL(port))
48907801f3b7SLucas De Marchi 			& DDI_BUF_PORT_REVERSAL;
4891379bc100SJani Nikula 	else
48927801f3b7SLucas De Marchi 		dig_port->saved_port_bits =
48937801f3b7SLucas De Marchi 			intel_de_read(dev_priv, DDI_BUF_CTL(port))
48947801f3b7SLucas De Marchi 			& (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
489570dfbc29SLucas De Marchi 
48965f42196dSVille Syrjälä 	if (intel_bios_encoder_lane_reversal(devdata))
4897aaab24bbSUma Shankar 		dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
4898aaab24bbSUma Shankar 
48997801f3b7SLucas De Marchi 	dig_port->dp.output_reg = INVALID_MMIO_REG;
49007801f3b7SLucas De Marchi 	dig_port->max_lanes = intel_ddi_max_lanes(dig_port);
4901bb45217fSVille Syrjälä 	dig_port->aux_ch = intel_dp_aux_ch(encoder);
4902379bc100SJani Nikula 
4903d8fe2ab6SMatt Roper 	if (intel_phy_is_tc(dev_priv, phy)) {
4904c5faae5aSJani Nikula 		bool is_legacy =
4905f08fbe6aSJani Nikula 			!intel_bios_encoder_supports_typec_usb(devdata) &&
4906f08fbe6aSJani Nikula 			!intel_bios_encoder_supports_tbt(devdata);
4907379bc100SJani Nikula 
490840a55b84SImre Deak 		if (!is_legacy && init_hdmi) {
490940a55b84SImre Deak 			is_legacy = !init_dp;
491040a55b84SImre Deak 
491140a55b84SImre Deak 			drm_dbg_kms(&dev_priv->drm,
491240a55b84SImre Deak 				    "VBT says port %c is non-legacy TC and has HDMI (with DP: %s), assume it's %s\n",
491340a55b84SImre Deak 				    port_name(port),
491440a55b84SImre Deak 				    str_yes_no(init_dp),
491540a55b84SImre Deak 				    is_legacy ? "legacy" : "non-legacy");
491640a55b84SImre Deak 		}
491740a55b84SImre Deak 
4918b61fad5fSImre Deak 		encoder->suspend_complete = intel_ddi_tc_encoder_suspend_complete;
4919b61fad5fSImre Deak 		encoder->shutdown_complete = intel_ddi_tc_encoder_shutdown_complete;
4920b61fad5fSImre Deak 
4921c5879999SImre Deak 		if (intel_tc_port_init(dig_port, is_legacy) < 0)
4922c5879999SImre Deak 			goto err;
4923ab7bc4e1SImre Deak 	}
4924ab7bc4e1SImre Deak 
49251de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, port > PORT_I);
4926979e1b32SImre Deak 	dig_port->ddi_io_power_domain = intel_display_power_ddi_io_domain(dev_priv, port);
4927379bc100SJani Nikula 
4928005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
4929edc0e09cSVille Syrjälä 		if (intel_phy_is_tc(dev_priv, phy))
49307801f3b7SLucas De Marchi 			dig_port->connected = intel_tc_port_connected;
4931edc0e09cSVille Syrjälä 		else
49327801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4933dded35acSVille Syrjälä 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
4934dded35acSVille Syrjälä 		dig_port->connected = bdw_digital_port_connected;
4935dded35acSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) == 9) {
4936dded35acSVille Syrjälä 		dig_port->connected = lpt_digital_port_connected;
4937dded35acSVille Syrjälä 	} else if (IS_BROADWELL(dev_priv)) {
4938dded35acSVille Syrjälä 		if (port == PORT_A)
49397801f3b7SLucas De Marchi 			dig_port->connected = bdw_digital_port_connected;
4940edc0e09cSVille Syrjälä 		else
49417801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4942dded35acSVille Syrjälä 	} else if (IS_HASWELL(dev_priv)) {
4943c7e8a3d6SVille Syrjälä 		if (port == PORT_A)
49447801f3b7SLucas De Marchi 			dig_port->connected = hsw_digital_port_connected;
4945edc0e09cSVille Syrjälä 		else
49467801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4947edc0e09cSVille Syrjälä 	}
4948edc0e09cSVille Syrjälä 
49497801f3b7SLucas De Marchi 	intel_infoframe_init(dig_port);
4950379bc100SJani Nikula 
4951a98ffd6eSVille Syrjälä 	if (init_dp) {
4952a98ffd6eSVille Syrjälä 		if (!intel_ddi_init_dp_connector(dig_port))
4953a98ffd6eSVille Syrjälä 			goto err;
4954a98ffd6eSVille Syrjälä 
4955a98ffd6eSVille Syrjälä 		dig_port->hpd_pulse = intel_dp_hpd_pulse;
4956a98ffd6eSVille Syrjälä 
4957a98ffd6eSVille Syrjälä 		if (dig_port->dp.mso_link_count)
4958a98ffd6eSVille Syrjälä 			encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv);
4959a98ffd6eSVille Syrjälä 	}
4960a98ffd6eSVille Syrjälä 
4961a98ffd6eSVille Syrjälä 	/*
4962a98ffd6eSVille Syrjälä 	 * In theory we don't need the encoder->type check,
4963a98ffd6eSVille Syrjälä 	 * but leave it just in case we have some really bad VBTs...
4964a98ffd6eSVille Syrjälä 	 */
4965a98ffd6eSVille Syrjälä 	if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
4966a98ffd6eSVille Syrjälä 		if (!intel_ddi_init_hdmi_connector(dig_port))
4967a98ffd6eSVille Syrjälä 			goto err;
4968a98ffd6eSVille Syrjälä 	}
4969a98ffd6eSVille Syrjälä 
4970379bc100SJani Nikula 	return;
4971379bc100SJani Nikula 
4972379bc100SJani Nikula err:
497370dfbc29SLucas De Marchi 	drm_encoder_cleanup(&encoder->base);
49747801f3b7SLucas De Marchi 	kfree(dig_port);
4975379bc100SJani Nikula }
4976