xref: /linux/drivers/gpu/drm/i915/display/intel_ddi.c (revision dded35acecffe9b6ec881ddd42c6275a38fbfbfc)
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"
42379bc100SJani Nikula #include "intel_ddi.h"
4399092a97SDave Airlie #include "intel_ddi_buf_trans.h"
447785ae0bSVille Syrjälä #include "intel_de.h"
45979e1b32SImre Deak #include "intel_display_power.h"
461d455f8dSJani Nikula #include "intel_display_types.h"
4789cb0ba4SImre Deak #include "intel_dkl_phy.h"
48d69813c7SImre Deak #include "intel_dkl_phy_regs.h"
49379bc100SJani Nikula #include "intel_dp.h"
50bb45217fSVille Syrjälä #include "intel_dp_aux.h"
51379bc100SJani Nikula #include "intel_dp_link_training.h"
52dcb38f79SDave Airlie #include "intel_dp_mst.h"
53379bc100SJani Nikula #include "intel_dpio_phy.h"
54379bc100SJani Nikula #include "intel_dsi.h"
55dcb38f79SDave Airlie #include "intel_fdi.h"
56379bc100SJani Nikula #include "intel_fifo_underrun.h"
57379bc100SJani Nikula #include "intel_gmbus.h"
58379bc100SJani Nikula #include "intel_hdcp.h"
59379bc100SJani Nikula #include "intel_hdmi.h"
60379bc100SJani Nikula #include "intel_hotplug.h"
6103120fefSJani Nikula #include "intel_hti.h"
62379bc100SJani Nikula #include "intel_lspcon.h"
63589ebefdSImre Deak #include "intel_mg_phy_regs.h"
64abad6805SJani Nikula #include "intel_pps.h"
65379bc100SJani Nikula #include "intel_psr.h"
660c82118bSJani Nikula #include "intel_quirks.h"
67865b73eaSMatt Roper #include "intel_snps_phy.h"
68bdacf087SAnshuman Gupta #include "intel_sprite.h"
69bc85328fSImre Deak #include "intel_tc.h"
70379bc100SJani Nikula #include "intel_vdsc.h"
71c3f05948SJani Nikula #include "intel_vdsc_regs.h"
72aa52b39dSManasi Navare #include "intel_vrr.h"
73714b1cdbSDave Airlie #include "skl_scaler.h"
7446d12f91SDave Airlie #include "skl_universal_plane.h"
75379bc100SJani Nikula 
76379bc100SJani Nikula static const u8 index_to_dp_signal_levels[] = {
77379bc100SJani Nikula 	[0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
78379bc100SJani Nikula 	[1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1,
79379bc100SJani Nikula 	[2] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2,
80379bc100SJani Nikula 	[3] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3,
81379bc100SJani Nikula 	[4] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0,
82379bc100SJani Nikula 	[5] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1,
83379bc100SJani Nikula 	[6] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2,
84379bc100SJani Nikula 	[7] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0,
85379bc100SJani Nikula 	[8] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1,
86379bc100SJani Nikula 	[9] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0,
87379bc100SJani Nikula };
88379bc100SJani Nikula 
89a621860aSVille Syrjälä static int intel_ddi_hdmi_level(struct intel_encoder *encoder,
903e022c1fSVille Syrjälä 				const struct intel_ddi_buf_trans *trans)
91379bc100SJani Nikula {
923e022c1fSVille Syrjälä 	int level;
93379bc100SJani Nikula 
9402107ef1SVille Syrjälä 	level = intel_bios_hdmi_level_shift(encoder->devdata);
950aed3bdeSJani Nikula 	if (level < 0)
963e022c1fSVille Syrjälä 		level = trans->hdmi_default_entry;
97379bc100SJani Nikula 
98379bc100SJani Nikula 	return level;
99379bc100SJani Nikula }
100379bc100SJani Nikula 
1015bafd85dSVille Syrjälä static bool has_buf_trans_select(struct drm_i915_private *i915)
1025bafd85dSVille Syrjälä {
1035bafd85dSVille Syrjälä 	return DISPLAY_VER(i915) < 10 && !IS_BROXTON(i915);
1045bafd85dSVille Syrjälä }
1055bafd85dSVille Syrjälä 
106f820693bSVille Syrjälä static bool has_iboost(struct drm_i915_private *i915)
107f820693bSVille Syrjälä {
108f820693bSVille Syrjälä 	return DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915);
109f820693bSVille Syrjälä }
110f820693bSVille Syrjälä 
111379bc100SJani Nikula /*
112379bc100SJani Nikula  * Starting with Haswell, DDI port buffers must be programmed with correct
113379bc100SJani Nikula  * values in advance. This function programs the correct values for
114379bc100SJani Nikula  * DP/eDP/FDI use cases.
115379bc100SJani Nikula  */
116266152aeSVille Syrjälä void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
117379bc100SJani Nikula 				const struct intel_crtc_state *crtc_state)
118379bc100SJani Nikula {
119379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
120379bc100SJani Nikula 	u32 iboost_bit = 0;
121379bc100SJani Nikula 	int i, n_entries;
122379bc100SJani Nikula 	enum port port = encoder->port;
123e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
124379bc100SJani Nikula 
125e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
126e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
127d6b10b1aSVille Syrjälä 		return;
128379bc100SJani Nikula 
129379bc100SJani Nikula 	/* If we're boosting the current, set bit 31 of trans1 */
130f820693bSVille Syrjälä 	if (has_iboost(dev_priv) &&
13102107ef1SVille Syrjälä 	    intel_bios_dp_boost_level(encoder->devdata))
132379bc100SJani Nikula 		iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
133379bc100SJani Nikula 
134379bc100SJani Nikula 	for (i = 0; i < n_entries; i++) {
135f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, i),
136e505d764SVille Syrjälä 			       trans->entries[i].hsw.trans1 | iboost_bit);
137f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, i),
138e505d764SVille Syrjälä 			       trans->entries[i].hsw.trans2);
139379bc100SJani Nikula 	}
140379bc100SJani Nikula }
141379bc100SJani Nikula 
142379bc100SJani Nikula /*
143379bc100SJani Nikula  * Starting with Haswell, DDI port buffers must be programmed with correct
144379bc100SJani Nikula  * values in advance. This function programs the correct values for
145379bc100SJani Nikula  * HDMI/DVI use cases.
146379bc100SJani Nikula  */
147266152aeSVille Syrjälä static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
148e722ab8bSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
149379bc100SJani Nikula {
150379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
151d0920a45SVille Syrjälä 	int level = intel_ddi_level(encoder, crtc_state, 0);
152379bc100SJani Nikula 	u32 iboost_bit = 0;
153379bc100SJani Nikula 	int n_entries;
154379bc100SJani Nikula 	enum port port = encoder->port;
155e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
156379bc100SJani Nikula 
157e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
158e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
159379bc100SJani Nikula 		return;
160379bc100SJani Nikula 
161379bc100SJani Nikula 	/* If we're boosting the current, set bit 31 of trans1 */
162f820693bSVille Syrjälä 	if (has_iboost(dev_priv) &&
16302107ef1SVille Syrjälä 	    intel_bios_hdmi_boost_level(encoder->devdata))
164379bc100SJani Nikula 		iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
165379bc100SJani Nikula 
166379bc100SJani Nikula 	/* Entry 9 is for HDMI: */
167f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, 9),
168e505d764SVille Syrjälä 		       trans->entries[level].hsw.trans1 | iboost_bit);
169f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, 9),
170e505d764SVille Syrjälä 		       trans->entries[level].hsw.trans2);
171379bc100SJani Nikula }
172379bc100SJani Nikula 
173dcb38f79SDave Airlie void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
174379bc100SJani Nikula 			     enum port port)
175379bc100SJani Nikula {
1765a2ad99bSManasi Navare 	if (IS_BROXTON(dev_priv)) {
1775a2ad99bSManasi Navare 		udelay(16);
178379bc100SJani Nikula 		return;
179379bc100SJani Nikula 	}
1805a2ad99bSManasi Navare 
1815a2ad99bSManasi Navare 	if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
1825a2ad99bSManasi Navare 			 DDI_BUF_IS_IDLE), 8))
1835a2ad99bSManasi Navare 		drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get idle\n",
18447bdb1caSJani Nikula 			port_name(port));
185379bc100SJani Nikula }
186379bc100SJani Nikula 
187e828da30SManasi Navare static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv,
188e828da30SManasi Navare 				      enum port port)
189e828da30SManasi Navare {
1905add4575SAnkit Nautiyal 	enum phy phy = intel_port_to_phy(dev_priv, port);
1915add4575SAnkit Nautiyal 	int timeout_us;
192f82f2563SMatt Roper 	int ret;
193f82f2563SMatt Roper 
194e828da30SManasi Navare 	/* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
195ad314fecSVille Syrjälä 	if (DISPLAY_VER(dev_priv) < 10) {
196e828da30SManasi Navare 		usleep_range(518, 1000);
197e828da30SManasi Navare 		return;
198e828da30SManasi Navare 	}
199e828da30SManasi Navare 
2005add4575SAnkit Nautiyal 	if (IS_DG2(dev_priv)) {
2015add4575SAnkit Nautiyal 		timeout_us = 1200;
2025add4575SAnkit Nautiyal 	} else if (DISPLAY_VER(dev_priv) >= 12) {
2035add4575SAnkit Nautiyal 		if (intel_phy_is_tc(dev_priv, phy))
2045add4575SAnkit Nautiyal 			timeout_us = 3000;
2055add4575SAnkit Nautiyal 		else
2065add4575SAnkit Nautiyal 			timeout_us = 1000;
2075add4575SAnkit Nautiyal 	} else {
2085add4575SAnkit Nautiyal 		timeout_us = 500;
2095add4575SAnkit Nautiyal 	}
2105add4575SAnkit Nautiyal 
211f82f2563SMatt Roper 	ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
2125add4575SAnkit Nautiyal 			  DDI_BUF_IS_IDLE), timeout_us, 10, 10);
213f82f2563SMatt Roper 
214f82f2563SMatt Roper 	if (ret)
215e828da30SManasi Navare 		drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
216e828da30SManasi Navare 			port_name(port));
217e828da30SManasi Navare }
218e828da30SManasi Navare 
219ad952982SVille Syrjälä static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
220379bc100SJani Nikula {
221379bc100SJani Nikula 	switch (pll->info->id) {
222379bc100SJani Nikula 	case DPLL_ID_WRPLL1:
223379bc100SJani Nikula 		return PORT_CLK_SEL_WRPLL1;
224379bc100SJani Nikula 	case DPLL_ID_WRPLL2:
225379bc100SJani Nikula 		return PORT_CLK_SEL_WRPLL2;
226379bc100SJani Nikula 	case DPLL_ID_SPLL:
227379bc100SJani Nikula 		return PORT_CLK_SEL_SPLL;
228379bc100SJani Nikula 	case DPLL_ID_LCPLL_810:
229379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_810;
230379bc100SJani Nikula 	case DPLL_ID_LCPLL_1350:
231379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_1350;
232379bc100SJani Nikula 	case DPLL_ID_LCPLL_2700:
233379bc100SJani Nikula 		return PORT_CLK_SEL_LCPLL_2700;
234379bc100SJani Nikula 	default:
235379bc100SJani Nikula 		MISSING_CASE(pll->info->id);
236379bc100SJani Nikula 		return PORT_CLK_SEL_NONE;
237379bc100SJani Nikula 	}
238379bc100SJani Nikula }
239379bc100SJani Nikula 
240379bc100SJani Nikula static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
241379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state)
242379bc100SJani Nikula {
243379bc100SJani Nikula 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
244379bc100SJani Nikula 	int clock = crtc_state->port_clock;
245379bc100SJani Nikula 	const enum intel_dpll_id id = pll->info->id;
246379bc100SJani Nikula 
247379bc100SJani Nikula 	switch (id) {
248379bc100SJani Nikula 	default:
249379bc100SJani Nikula 		/*
250379bc100SJani Nikula 		 * DPLL_ID_ICL_DPLL0 and DPLL_ID_ICL_DPLL1 should not be used
251379bc100SJani Nikula 		 * here, so do warn if this get passed in
252379bc100SJani Nikula 		 */
253379bc100SJani Nikula 		MISSING_CASE(id);
254379bc100SJani Nikula 		return DDI_CLK_SEL_NONE;
255379bc100SJani Nikula 	case DPLL_ID_ICL_TBTPLL:
256379bc100SJani Nikula 		switch (clock) {
257379bc100SJani Nikula 		case 162000:
258379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_162;
259379bc100SJani Nikula 		case 270000:
260379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_270;
261379bc100SJani Nikula 		case 540000:
262379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_540;
263379bc100SJani Nikula 		case 810000:
264379bc100SJani Nikula 			return DDI_CLK_SEL_TBT_810;
265379bc100SJani Nikula 		default:
266379bc100SJani Nikula 			MISSING_CASE(clock);
267379bc100SJani Nikula 			return DDI_CLK_SEL_NONE;
268379bc100SJani Nikula 		}
269379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL1:
270379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL2:
271379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL3:
272379bc100SJani Nikula 	case DPLL_ID_ICL_MGPLL4:
2736677c3b1SJosé Roberto de Souza 	case DPLL_ID_TGL_MGPLL5:
2746677c3b1SJosé Roberto de Souza 	case DPLL_ID_TGL_MGPLL6:
275379bc100SJani Nikula 		return DDI_CLK_SEL_MG;
276379bc100SJani Nikula 	}
277379bc100SJani Nikula }
278379bc100SJani Nikula 
279414002f1SImre Deak static u32 ddi_buf_phy_link_rate(int port_clock)
280414002f1SImre Deak {
281414002f1SImre Deak 	switch (port_clock) {
282414002f1SImre Deak 	case 162000:
283414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(0);
284414002f1SImre Deak 	case 216000:
285414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(4);
286414002f1SImre Deak 	case 243000:
287414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(5);
288414002f1SImre Deak 	case 270000:
289414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(1);
290414002f1SImre Deak 	case 324000:
291414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(6);
292414002f1SImre Deak 	case 432000:
293414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(7);
294414002f1SImre Deak 	case 540000:
295414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(2);
296414002f1SImre Deak 	case 810000:
297414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(3);
298414002f1SImre Deak 	default:
299414002f1SImre Deak 		MISSING_CASE(port_clock);
300414002f1SImre Deak 		return DDI_BUF_PHY_LINK_RATE(0);
301414002f1SImre Deak 	}
302414002f1SImre Deak }
303414002f1SImre Deak 
304a621860aSVille Syrjälä static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
305a621860aSVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
306379bc100SJani Nikula {
30755ce306cSJosé Roberto de Souza 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
308b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3097801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
31055ce306cSJosé Roberto de Souza 	enum phy phy = intel_port_to_phy(i915, encoder->port);
311379bc100SJani Nikula 
3129f620f1dSVille Syrjälä 	/* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */
3137801f3b7SLucas De Marchi 	intel_dp->DP = dig_port->saved_port_bits |
3149f620f1dSVille Syrjälä 		DDI_PORT_WIDTH(crtc_state->lane_count) |
3159f620f1dSVille Syrjälä 		DDI_BUF_TRANS_SELECT(0);
31655ce306cSJosé Roberto de Souza 
317414002f1SImre Deak 	if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) {
318414002f1SImre Deak 		intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock);
31911a89708SImre Deak 		if (!intel_tc_port_in_tbt_alt_mode(dig_port))
32055ce306cSJosé Roberto de Souza 			intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
321379bc100SJani Nikula 	}
322414002f1SImre Deak }
323379bc100SJani Nikula 
324379bc100SJani Nikula static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
325379bc100SJani Nikula 				 enum port port)
326379bc100SJani Nikula {
327f7960e7fSJani Nikula 	u32 val = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK;
328379bc100SJani Nikula 
329379bc100SJani Nikula 	switch (val) {
330379bc100SJani Nikula 	case DDI_CLK_SEL_NONE:
331379bc100SJani Nikula 		return 0;
332379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_162:
333379bc100SJani Nikula 		return 162000;
334379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_270:
335379bc100SJani Nikula 		return 270000;
336379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_540:
337379bc100SJani Nikula 		return 540000;
338379bc100SJani Nikula 	case DDI_CLK_SEL_TBT_810:
339379bc100SJani Nikula 		return 810000;
340379bc100SJani Nikula 	default:
341379bc100SJani Nikula 		MISSING_CASE(val);
342379bc100SJani Nikula 		return 0;
343379bc100SJani Nikula 	}
344379bc100SJani Nikula }
345379bc100SJani Nikula 
346623411c2SVille Syrjälä static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
347623411c2SVille Syrjälä {
348623411c2SVille Syrjälä 	/* CRT dotclock is determined via other means */
349623411c2SVille Syrjälä 	if (pipe_config->has_pch_encoder)
350623411c2SVille Syrjälä 		return;
351623411c2SVille Syrjälä 
352623411c2SVille Syrjälä 	pipe_config->hw.adjusted_mode.crtc_clock =
353623411c2SVille Syrjälä 		intel_crtc_dotclock(pipe_config);
354379bc100SJani Nikula }
355379bc100SJani Nikula 
3560c06fa15SGwan-gyeong Mun void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
3570c06fa15SGwan-gyeong Mun 			  const struct drm_connector_state *conn_state)
358379bc100SJani Nikula {
3592225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
360379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
361379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
362379bc100SJani Nikula 	u32 temp;
363379bc100SJani Nikula 
364379bc100SJani Nikula 	if (!intel_crtc_has_dp_encoder(crtc_state))
365379bc100SJani Nikula 		return;
366379bc100SJani Nikula 
3671de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder));
368379bc100SJani Nikula 
3693e706dffSVille Syrjälä 	temp = DP_MSA_MISC_SYNC_CLOCK;
370379bc100SJani Nikula 
371379bc100SJani Nikula 	switch (crtc_state->pipe_bpp) {
372379bc100SJani Nikula 	case 18:
3733e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_6_BPC;
374379bc100SJani Nikula 		break;
375379bc100SJani Nikula 	case 24:
3763e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_8_BPC;
377379bc100SJani Nikula 		break;
378379bc100SJani Nikula 	case 30:
3793e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_10_BPC;
380379bc100SJani Nikula 		break;
381379bc100SJani Nikula 	case 36:
3823e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_12_BPC;
383379bc100SJani Nikula 		break;
384379bc100SJani Nikula 	default:
385379bc100SJani Nikula 		MISSING_CASE(crtc_state->pipe_bpp);
386379bc100SJani Nikula 		break;
387379bc100SJani Nikula 	}
388379bc100SJani Nikula 
389cae154fcSVille Syrjälä 	/* nonsense combination */
3901de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, crtc_state->limited_color_range &&
391cae154fcSVille Syrjälä 		    crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
392cae154fcSVille Syrjälä 
393cae154fcSVille Syrjälä 	if (crtc_state->limited_color_range)
3943e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_CEA_RGB;
395cae154fcSVille Syrjälä 
396379bc100SJani Nikula 	/*
397379bc100SJani Nikula 	 * As per DP 1.2 spec section 2.3.4.3 while sending
398379bc100SJani Nikula 	 * YCBCR 444 signals we should program MSA MISC1/0 fields with
399646d3dc8SVille Syrjälä 	 * colorspace information.
400379bc100SJani Nikula 	 */
401379bc100SJani Nikula 	if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
4023e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
403646d3dc8SVille Syrjälä 
404379bc100SJani Nikula 	/*
405379bc100SJani Nikula 	 * As per DP 1.4a spec section 2.2.4.3 [MSA Field for Indication
406379bc100SJani Nikula 	 * of Color Encoding Format and Content Color Gamut] while sending
4070c06fa15SGwan-gyeong Mun 	 * YCBCR 420, HDR BT.2020 signals we should program MSA MISC1 fields
4080c06fa15SGwan-gyeong Mun 	 * which indicate VSC SDP for the Pixel Encoding/Colorimetry Format.
409379bc100SJani Nikula 	 */
410bd8c9ccaSGwan-gyeong Mun 	if (intel_dp_needs_vsc_sdp(crtc_state, conn_state))
4113e706dffSVille Syrjälä 		temp |= DP_MSA_MISC_COLOR_VSC_SDP;
4120c06fa15SGwan-gyeong Mun 
413f7960e7fSJani Nikula 	intel_de_write(dev_priv, TRANS_MSA_MISC(cpu_transcoder), temp);
414379bc100SJani Nikula }
415379bc100SJani Nikula 
416dc5b8ed5SVille Syrjälä static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder)
417dc5b8ed5SVille Syrjälä {
418dc5b8ed5SVille Syrjälä 	if (master_transcoder == TRANSCODER_EDP)
419dc5b8ed5SVille Syrjälä 		return 0;
420dc5b8ed5SVille Syrjälä 	else
421dc5b8ed5SVille Syrjälä 		return master_transcoder + 1;
422dc5b8ed5SVille Syrjälä }
423dc5b8ed5SVille Syrjälä 
42479ac2b1bSJani Nikula static void
42579ac2b1bSJani Nikula intel_ddi_config_transcoder_dp2(struct intel_encoder *encoder,
42679ac2b1bSJani Nikula 				const struct intel_crtc_state *crtc_state)
42779ac2b1bSJani Nikula {
42879ac2b1bSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
42979ac2b1bSJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
43079ac2b1bSJani Nikula 	u32 val = 0;
43179ac2b1bSJani Nikula 
43279ac2b1bSJani Nikula 	if (intel_dp_is_uhbr(crtc_state))
43379ac2b1bSJani Nikula 		val = TRANS_DP2_128B132B_CHANNEL_CODING;
43479ac2b1bSJani Nikula 
43579ac2b1bSJani Nikula 	intel_de_write(i915, TRANS_DP2_CTL(cpu_transcoder), val);
43679ac2b1bSJani Nikula }
43779ac2b1bSJani Nikula 
43899389390SJosé Roberto de Souza /*
43999389390SJosé Roberto de Souza  * Returns the TRANS_DDI_FUNC_CTL value based on CRTC state.
44099389390SJosé Roberto de Souza  *
44199389390SJosé Roberto de Souza  * Only intended to be used by intel_ddi_enable_transcoder_func() and
44299389390SJosé Roberto de Souza  * intel_ddi_config_transcoder_func().
44399389390SJosé Roberto de Souza  */
44499389390SJosé Roberto de Souza static u32
445eed22a46SVille Syrjälä intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
446eed22a46SVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
447379bc100SJani Nikula {
4482225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
449379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
450379bc100SJani Nikula 	enum pipe pipe = crtc->pipe;
451379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
452379bc100SJani Nikula 	enum port port = encoder->port;
453379bc100SJani Nikula 	u32 temp;
454379bc100SJani Nikula 
455379bc100SJani Nikula 	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
456379bc100SJani Nikula 	temp = TRANS_DDI_FUNC_ENABLE;
457005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
458df16b636SMahesh Kumar 		temp |= TGL_TRANS_DDI_SELECT_PORT(port);
459df16b636SMahesh Kumar 	else
460379bc100SJani Nikula 		temp |= TRANS_DDI_SELECT_PORT(port);
461379bc100SJani Nikula 
462379bc100SJani Nikula 	switch (crtc_state->pipe_bpp) {
46304514c14SJani Nikula 	default:
46404514c14SJani Nikula 		MISSING_CASE(crtc_state->pipe_bpp);
46504514c14SJani Nikula 		fallthrough;
466379bc100SJani Nikula 	case 18:
467379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_6;
468379bc100SJani Nikula 		break;
469379bc100SJani Nikula 	case 24:
470379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_8;
471379bc100SJani Nikula 		break;
472379bc100SJani Nikula 	case 30:
473379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_10;
474379bc100SJani Nikula 		break;
475379bc100SJani Nikula 	case 36:
476379bc100SJani Nikula 		temp |= TRANS_DDI_BPC_12;
477379bc100SJani Nikula 		break;
478379bc100SJani Nikula 	}
479379bc100SJani Nikula 
4801326a92cSMaarten Lankhorst 	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
481379bc100SJani Nikula 		temp |= TRANS_DDI_PVSYNC;
4821326a92cSMaarten Lankhorst 	if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
483379bc100SJani Nikula 		temp |= TRANS_DDI_PHSYNC;
484379bc100SJani Nikula 
485379bc100SJani Nikula 	if (cpu_transcoder == TRANSCODER_EDP) {
486379bc100SJani Nikula 		switch (pipe) {
48704514c14SJani Nikula 		default:
48804514c14SJani Nikula 			MISSING_CASE(pipe);
48904514c14SJani Nikula 			fallthrough;
490379bc100SJani Nikula 		case PIPE_A:
491379bc100SJani Nikula 			/* On Haswell, can only use the always-on power well for
492379bc100SJani Nikula 			 * eDP when not using the panel fitter, and when not
493379bc100SJani Nikula 			 * using motion blur mitigation (which we don't
494379bc100SJani Nikula 			 * support). */
495379bc100SJani Nikula 			if (crtc_state->pch_pfit.force_thru)
496379bc100SJani Nikula 				temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
497379bc100SJani Nikula 			else
498379bc100SJani Nikula 				temp |= TRANS_DDI_EDP_INPUT_A_ON;
499379bc100SJani Nikula 			break;
500379bc100SJani Nikula 		case PIPE_B:
501379bc100SJani Nikula 			temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
502379bc100SJani Nikula 			break;
503379bc100SJani Nikula 		case PIPE_C:
504379bc100SJani Nikula 			temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
505379bc100SJani Nikula 			break;
506379bc100SJani Nikula 		}
507379bc100SJani Nikula 	}
508379bc100SJani Nikula 
509379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
510379bc100SJani Nikula 		if (crtc_state->has_hdmi_sink)
511379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_HDMI;
512379bc100SJani Nikula 		else
513379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_DVI;
514379bc100SJani Nikula 
515379bc100SJani Nikula 		if (crtc_state->hdmi_scrambling)
516379bc100SJani Nikula 			temp |= TRANS_DDI_HDMI_SCRAMBLING;
517379bc100SJani Nikula 		if (crtc_state->hdmi_high_tmds_clock_ratio)
518379bc100SJani Nikula 			temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
519379bc100SJani Nikula 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
5207bb97db8SJani Nikula 		temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
521379bc100SJani Nikula 		temp |= (crtc_state->fdi_lanes - 1) << 1;
522379bc100SJani Nikula 	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
52365213594SJani Nikula 		if (intel_dp_is_uhbr(crtc_state))
52465213594SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
52565213594SJani Nikula 		else
526379bc100SJani Nikula 			temp |= TRANS_DDI_MODE_SELECT_DP_MST;
527379bc100SJani Nikula 		temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
528b3545e08SLucas De Marchi 
529005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
5306671c367SJosé Roberto de Souza 			enum transcoder master;
5316671c367SJosé Roberto de Souza 
5326671c367SJosé Roberto de Souza 			master = crtc_state->mst_master_transcoder;
5331de143ccSPankaj Bharadiya 			drm_WARN_ON(&dev_priv->drm,
5341de143ccSPankaj Bharadiya 				    master == INVALID_TRANSCODER);
5356671c367SJosé Roberto de Souza 			temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master);
5366671c367SJosé Roberto de Souza 		}
537379bc100SJani Nikula 	} else {
538379bc100SJani Nikula 		temp |= TRANS_DDI_MODE_SELECT_DP_SST;
539379bc100SJani Nikula 		temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
540379bc100SJani Nikula 	}
541379bc100SJani Nikula 
54293e7e61eSLucas De Marchi 	if (IS_DISPLAY_VER(dev_priv, 8, 10) &&
543dc5b8ed5SVille Syrjälä 	    crtc_state->master_transcoder != INVALID_TRANSCODER) {
544dc5b8ed5SVille Syrjälä 		u8 master_select =
545dc5b8ed5SVille Syrjälä 			bdw_trans_port_sync_master_select(crtc_state->master_transcoder);
546dc5b8ed5SVille Syrjälä 
547dc5b8ed5SVille Syrjälä 		temp |= TRANS_DDI_PORT_SYNC_ENABLE |
548dc5b8ed5SVille Syrjälä 			TRANS_DDI_PORT_SYNC_MASTER_SELECT(master_select);
549dc5b8ed5SVille Syrjälä 	}
550dc5b8ed5SVille Syrjälä 
55199389390SJosé Roberto de Souza 	return temp;
55299389390SJosé Roberto de Souza }
55399389390SJosé Roberto de Souza 
554eed22a46SVille Syrjälä void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
555eed22a46SVille Syrjälä 				      const struct intel_crtc_state *crtc_state)
55699389390SJosé Roberto de Souza {
5572225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
55899389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
55999389390SJosé Roberto de Souza 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
56099389390SJosé Roberto de Souza 
561005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
562589a4cd6SVille Syrjälä 		enum transcoder master_transcoder = crtc_state->master_transcoder;
563589a4cd6SVille Syrjälä 		u32 ctl2 = 0;
564589a4cd6SVille Syrjälä 
565589a4cd6SVille Syrjälä 		if (master_transcoder != INVALID_TRANSCODER) {
566dc5b8ed5SVille Syrjälä 			u8 master_select =
567dc5b8ed5SVille Syrjälä 				bdw_trans_port_sync_master_select(master_transcoder);
568589a4cd6SVille Syrjälä 
569589a4cd6SVille Syrjälä 			ctl2 |= PORT_SYNC_MODE_ENABLE |
570d4d7d9caSVille Syrjälä 				PORT_SYNC_MODE_MASTER_SELECT(master_select);
571589a4cd6SVille Syrjälä 		}
572589a4cd6SVille Syrjälä 
573589a4cd6SVille Syrjälä 		intel_de_write(dev_priv,
574589a4cd6SVille Syrjälä 			       TRANS_DDI_FUNC_CTL2(cpu_transcoder), ctl2);
575589a4cd6SVille Syrjälä 	}
576589a4cd6SVille Syrjälä 
577580fbdc5SImre Deak 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
578580fbdc5SImre Deak 		       intel_ddi_transcoder_func_reg_val_get(encoder,
579580fbdc5SImre Deak 							     crtc_state));
58099389390SJosé Roberto de Souza }
58199389390SJosé Roberto de Souza 
58299389390SJosé Roberto de Souza /*
58399389390SJosé Roberto de Souza  * Same as intel_ddi_enable_transcoder_func(), but it does not set the enable
58499389390SJosé Roberto de Souza  * bit.
58599389390SJosé Roberto de Souza  */
58699389390SJosé Roberto de Souza static void
587eed22a46SVille Syrjälä intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
588eed22a46SVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
58999389390SJosé Roberto de Souza {
5902225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
59199389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
59299389390SJosé Roberto de Souza 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
593589a4cd6SVille Syrjälä 	u32 ctl;
59499389390SJosé Roberto de Souza 
595eed22a46SVille Syrjälä 	ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state);
596589a4cd6SVille Syrjälä 	ctl &= ~TRANS_DDI_FUNC_ENABLE;
597589a4cd6SVille Syrjälä 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl);
598379bc100SJani Nikula }
599379bc100SJani Nikula 
600379bc100SJani Nikula void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
601379bc100SJani Nikula {
6022225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
603379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
604379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
605589a4cd6SVille Syrjälä 	u32 ctl;
606c59053dcSJosé Roberto de Souza 
607005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
608589a4cd6SVille Syrjälä 		intel_de_write(dev_priv,
609589a4cd6SVille Syrjälä 			       TRANS_DDI_FUNC_CTL2(cpu_transcoder), 0);
610589a4cd6SVille Syrjälä 
611589a4cd6SVille Syrjälä 	ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
612dc5b8ed5SVille Syrjälä 
6131cfcdbf3SSean Paul 	drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING);
6141cfcdbf3SSean Paul 
615589a4cd6SVille Syrjälä 	ctl &= ~TRANS_DDI_FUNC_ENABLE;
616379bc100SJani Nikula 
61793e7e61eSLucas De Marchi 	if (IS_DISPLAY_VER(dev_priv, 8, 10))
618dc5b8ed5SVille Syrjälä 		ctl &= ~(TRANS_DDI_PORT_SYNC_ENABLE |
619dc5b8ed5SVille Syrjälä 			 TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK);
620dc5b8ed5SVille Syrjälä 
621005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
622919e4f07SJosé Roberto de Souza 		if (!intel_dp_mst_is_master_trans(crtc_state)) {
623589a4cd6SVille Syrjälä 			ctl &= ~(TGL_TRANS_DDI_PORT_MASK |
624919e4f07SJosé Roberto de Souza 				 TRANS_DDI_MODE_SELECT_MASK);
625919e4f07SJosé Roberto de Souza 		}
626df16b636SMahesh Kumar 	} else {
627589a4cd6SVille Syrjälä 		ctl &= ~(TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK);
628df16b636SMahesh Kumar 	}
629dc5b8ed5SVille Syrjälä 
630589a4cd6SVille Syrjälä 	intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder), ctl);
631379bc100SJani Nikula 
6320c82118bSJani Nikula 	if (intel_has_quirk(dev_priv, QUIRK_INCREASE_DDI_DISABLED_TIME) &&
633379bc100SJani Nikula 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
63447bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
63547bdb1caSJani Nikula 			    "Quirk Increase DDI disabled time\n");
636379bc100SJani Nikula 		/* Quirk time at 100ms for reliable operation */
637379bc100SJani Nikula 		msleep(100);
638379bc100SJani Nikula 	}
639379bc100SJani Nikula }
640379bc100SJani Nikula 
6411a67a168SAnshuman Gupta int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
6420b9c9290SSean Paul 			       enum transcoder cpu_transcoder,
6431a67a168SAnshuman Gupta 			       bool enable, u32 hdcp_mask)
644379bc100SJani Nikula {
645379bc100SJani Nikula 	struct drm_device *dev = intel_encoder->base.dev;
646379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
647379bc100SJani Nikula 	intel_wakeref_t wakeref;
648379bc100SJani Nikula 	int ret = 0;
649379bc100SJani Nikula 
650379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
651379bc100SJani Nikula 						     intel_encoder->power_domain);
6521de143ccSPankaj Bharadiya 	if (drm_WARN_ON(dev, !wakeref))
653379bc100SJani Nikula 		return -ENXIO;
654379bc100SJani Nikula 
6558910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
6568910d8b7SAndrzej Hajda 		     hdcp_mask, enable ? hdcp_mask : 0);
657379bc100SJani Nikula 	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
658379bc100SJani Nikula 	return ret;
659379bc100SJani Nikula }
660379bc100SJani Nikula 
661379bc100SJani Nikula bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
662379bc100SJani Nikula {
663379bc100SJani Nikula 	struct drm_device *dev = intel_connector->base.dev;
664379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
665fa7edcd2SVille Syrjälä 	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
666379bc100SJani Nikula 	int type = intel_connector->base.connector_type;
667379bc100SJani Nikula 	enum port port = encoder->port;
668379bc100SJani Nikula 	enum transcoder cpu_transcoder;
669379bc100SJani Nikula 	intel_wakeref_t wakeref;
670379bc100SJani Nikula 	enum pipe pipe = 0;
671379bc100SJani Nikula 	u32 tmp;
672379bc100SJani Nikula 	bool ret;
673379bc100SJani Nikula 
674379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
675379bc100SJani Nikula 						     encoder->power_domain);
676379bc100SJani Nikula 	if (!wakeref)
677379bc100SJani Nikula 		return false;
678379bc100SJani Nikula 
679379bc100SJani Nikula 	if (!encoder->get_hw_state(encoder, &pipe)) {
680379bc100SJani Nikula 		ret = false;
681379bc100SJani Nikula 		goto out;
682379bc100SJani Nikula 	}
683379bc100SJani Nikula 
68410cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
685379bc100SJani Nikula 		cpu_transcoder = TRANSCODER_EDP;
686379bc100SJani Nikula 	else
687379bc100SJani Nikula 		cpu_transcoder = (enum transcoder) pipe;
688379bc100SJani Nikula 
689f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
690379bc100SJani Nikula 
691379bc100SJani Nikula 	switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
692379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_HDMI:
693379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DVI:
694379bc100SJani Nikula 		ret = type == DRM_MODE_CONNECTOR_HDMIA;
695379bc100SJani Nikula 		break;
696379bc100SJani Nikula 
697379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_SST:
698379bc100SJani Nikula 		ret = type == DRM_MODE_CONNECTOR_eDP ||
699379bc100SJani Nikula 		      type == DRM_MODE_CONNECTOR_DisplayPort;
700379bc100SJani Nikula 		break;
701379bc100SJani Nikula 
702379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_MST:
703379bc100SJani Nikula 		/* if the transcoder is in MST state then
704379bc100SJani Nikula 		 * connector isn't connected */
705379bc100SJani Nikula 		ret = false;
706379bc100SJani Nikula 		break;
707379bc100SJani Nikula 
7087bb97db8SJani Nikula 	case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
70965213594SJani Nikula 		if (HAS_DP20(dev_priv))
71065213594SJani Nikula 			/* 128b/132b */
71165213594SJani Nikula 			ret = false;
71265213594SJani Nikula 		else
71365213594SJani Nikula 			/* FDI */
714379bc100SJani Nikula 			ret = type == DRM_MODE_CONNECTOR_VGA;
715379bc100SJani Nikula 		break;
716379bc100SJani Nikula 
717379bc100SJani Nikula 	default:
718379bc100SJani Nikula 		ret = false;
719379bc100SJani Nikula 		break;
720379bc100SJani Nikula 	}
721379bc100SJani Nikula 
722379bc100SJani Nikula out:
723379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
724379bc100SJani Nikula 
725379bc100SJani Nikula 	return ret;
726379bc100SJani Nikula }
727379bc100SJani Nikula 
728379bc100SJani Nikula static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
729379bc100SJani Nikula 					u8 *pipe_mask, bool *is_dp_mst)
730379bc100SJani Nikula {
731379bc100SJani Nikula 	struct drm_device *dev = encoder->base.dev;
732379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(dev);
733379bc100SJani Nikula 	enum port port = encoder->port;
734379bc100SJani Nikula 	intel_wakeref_t wakeref;
735379bc100SJani Nikula 	enum pipe p;
736379bc100SJani Nikula 	u32 tmp;
737379bc100SJani Nikula 	u8 mst_pipe_mask;
738379bc100SJani Nikula 
739379bc100SJani Nikula 	*pipe_mask = 0;
740379bc100SJani Nikula 	*is_dp_mst = false;
741379bc100SJani Nikula 
742379bc100SJani Nikula 	wakeref = intel_display_power_get_if_enabled(dev_priv,
743379bc100SJani Nikula 						     encoder->power_domain);
744379bc100SJani Nikula 	if (!wakeref)
745379bc100SJani Nikula 		return;
746379bc100SJani Nikula 
747f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, DDI_BUF_CTL(port));
748379bc100SJani Nikula 	if (!(tmp & DDI_BUF_CTL_ENABLE))
749379bc100SJani Nikula 		goto out;
750379bc100SJani Nikula 
75110cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A) {
752f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv,
753f7960e7fSJani Nikula 				    TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));
754379bc100SJani Nikula 
755379bc100SJani Nikula 		switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
756379bc100SJani Nikula 		default:
757379bc100SJani Nikula 			MISSING_CASE(tmp & TRANS_DDI_EDP_INPUT_MASK);
758df561f66SGustavo A. R. Silva 			fallthrough;
759379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ON:
760379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_A_ONOFF:
761379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_A);
762379bc100SJani Nikula 			break;
763379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_B_ONOFF:
764379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_B);
765379bc100SJani Nikula 			break;
766379bc100SJani Nikula 		case TRANS_DDI_EDP_INPUT_C_ONOFF:
767379bc100SJani Nikula 			*pipe_mask = BIT(PIPE_C);
768379bc100SJani Nikula 			break;
769379bc100SJani Nikula 		}
770379bc100SJani Nikula 
771379bc100SJani Nikula 		goto out;
772379bc100SJani Nikula 	}
773379bc100SJani Nikula 
774379bc100SJani Nikula 	mst_pipe_mask = 0;
775379bc100SJani Nikula 	for_each_pipe(dev_priv, p) {
776379bc100SJani Nikula 		enum transcoder cpu_transcoder = (enum transcoder)p;
777df16b636SMahesh Kumar 		unsigned int port_mask, ddi_select;
7786aa3bef1SJosé Roberto de Souza 		intel_wakeref_t trans_wakeref;
7796aa3bef1SJosé Roberto de Souza 
7806aa3bef1SJosé Roberto de Souza 		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
7816aa3bef1SJosé Roberto de Souza 								   POWER_DOMAIN_TRANSCODER(cpu_transcoder));
7826aa3bef1SJosé Roberto de Souza 		if (!trans_wakeref)
7836aa3bef1SJosé Roberto de Souza 			continue;
784df16b636SMahesh Kumar 
785005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12) {
786df16b636SMahesh Kumar 			port_mask = TGL_TRANS_DDI_PORT_MASK;
787df16b636SMahesh Kumar 			ddi_select = TGL_TRANS_DDI_SELECT_PORT(port);
788df16b636SMahesh Kumar 		} else {
789df16b636SMahesh Kumar 			port_mask = TRANS_DDI_PORT_MASK;
790df16b636SMahesh Kumar 			ddi_select = TRANS_DDI_SELECT_PORT(port);
791df16b636SMahesh Kumar 		}
792379bc100SJani Nikula 
793f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv,
794f7960e7fSJani Nikula 				    TRANS_DDI_FUNC_CTL(cpu_transcoder));
7956aa3bef1SJosé Roberto de Souza 		intel_display_power_put(dev_priv, POWER_DOMAIN_TRANSCODER(cpu_transcoder),
7966aa3bef1SJosé Roberto de Souza 					trans_wakeref);
797379bc100SJani Nikula 
798df16b636SMahesh Kumar 		if ((tmp & port_mask) != ddi_select)
799379bc100SJani Nikula 			continue;
800379bc100SJani Nikula 
80165213594SJani Nikula 		if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST ||
80265213594SJani Nikula 		    (HAS_DP20(dev_priv) &&
80365213594SJani Nikula 		     (tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B))
804379bc100SJani Nikula 			mst_pipe_mask |= BIT(p);
805379bc100SJani Nikula 
806379bc100SJani Nikula 		*pipe_mask |= BIT(p);
807379bc100SJani Nikula 	}
808379bc100SJani Nikula 
809379bc100SJani Nikula 	if (!*pipe_mask)
81047bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
81147bdb1caSJani Nikula 			    "No pipe for [ENCODER:%d:%s] found\n",
81266a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name);
813379bc100SJani Nikula 
814379bc100SJani Nikula 	if (!mst_pipe_mask && hweight8(*pipe_mask) > 1) {
81547bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
81647bdb1caSJani Nikula 			    "Multiple pipes for [ENCODER:%d:%s] (pipe_mask %02x)\n",
81766a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name,
81866a990ddSVille Syrjälä 			    *pipe_mask);
819379bc100SJani Nikula 		*pipe_mask = BIT(ffs(*pipe_mask) - 1);
820379bc100SJani Nikula 	}
821379bc100SJani Nikula 
822379bc100SJani Nikula 	if (mst_pipe_mask && mst_pipe_mask != *pipe_mask)
82347bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
82447bdb1caSJani Nikula 			    "Conflicting MST and non-MST state for [ENCODER:%d:%s] (pipe_mask %02x mst_pipe_mask %02x)\n",
82566a990ddSVille Syrjälä 			    encoder->base.base.id, encoder->base.name,
82666a990ddSVille Syrjälä 			    *pipe_mask, mst_pipe_mask);
827379bc100SJani Nikula 	else
828379bc100SJani Nikula 		*is_dp_mst = mst_pipe_mask;
829379bc100SJani Nikula 
830379bc100SJani Nikula out:
8312446e1d6SMatt Roper 	if (*pipe_mask && (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))) {
832f7960e7fSJani Nikula 		tmp = intel_de_read(dev_priv, BXT_PHY_CTL(port));
833379bc100SJani Nikula 		if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
834379bc100SJani Nikula 			    BXT_PHY_LANE_POWERDOWN_ACK |
835379bc100SJani Nikula 			    BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED)
83647bdb1caSJani Nikula 			drm_err(&dev_priv->drm,
83747bdb1caSJani Nikula 				"[ENCODER:%d:%s] enabled but PHY powered down? (PHY_CTL %08x)\n",
83847bdb1caSJani Nikula 				encoder->base.base.id, encoder->base.name, tmp);
839379bc100SJani Nikula 	}
840379bc100SJani Nikula 
841379bc100SJani Nikula 	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
842379bc100SJani Nikula }
843379bc100SJani Nikula 
844379bc100SJani Nikula bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
845379bc100SJani Nikula 			    enum pipe *pipe)
846379bc100SJani Nikula {
847379bc100SJani Nikula 	u8 pipe_mask;
848379bc100SJani Nikula 	bool is_mst;
849379bc100SJani Nikula 
850379bc100SJani Nikula 	intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
851379bc100SJani Nikula 
852379bc100SJani Nikula 	if (is_mst || !pipe_mask)
853379bc100SJani Nikula 		return false;
854379bc100SJani Nikula 
855379bc100SJani Nikula 	*pipe = ffs(pipe_mask) - 1;
856379bc100SJani Nikula 
857379bc100SJani Nikula 	return true;
858379bc100SJani Nikula }
859379bc100SJani Nikula 
86081b55ef1SJani Nikula static enum intel_display_power_domain
861637c7aa2SImre Deak intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port,
862637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
863379bc100SJani Nikula {
864f645cbdaSImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
865637c7aa2SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
866f645cbdaSImre Deak 
867637c7aa2SImre Deak 	/*
868637c7aa2SImre Deak 	 * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
869379bc100SJani Nikula 	 * DC states enabled at the same time, while for driver initiated AUX
870379bc100SJani Nikula 	 * transfers we need the same AUX IOs to be powered but with DC states
871637c7aa2SImre Deak 	 * disabled. Accordingly use the AUX_IO_<port> power domain here which
872637c7aa2SImre Deak 	 * leaves DC states enabled.
873637c7aa2SImre Deak 	 *
874637c7aa2SImre Deak 	 * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require
875637c7aa2SImre Deak 	 * AUX IO to be enabled, but all these require DC_OFF to be enabled as
876637c7aa2SImre Deak 	 * well, so we can acquire a wider AUX_<port> power domain reference
877637c7aa2SImre Deak 	 * instead of a specific AUX_IO_<port> reference without powering up any
878637c7aa2SImre Deak 	 * extra wells.
879379bc100SJani Nikula 	 */
880f645cbdaSImre Deak 	if (intel_encoder_can_psr(&dig_port->base))
881f645cbdaSImre Deak 		return intel_display_power_aux_io_domain(i915, dig_port->aux_ch);
8821acefacaSImre Deak 	else if (DISPLAY_VER(i915) < 14 &&
8831acefacaSImre Deak 		 (intel_crtc_has_dp_encoder(crtc_state) ||
8841acefacaSImre Deak 		  intel_phy_is_tc(i915, phy)))
885b2e00dd3SImre Deak 		return intel_aux_power_domain(dig_port);
886637c7aa2SImre Deak 	else
887637c7aa2SImre Deak 		return POWER_DOMAIN_INVALID;
888637c7aa2SImre Deak }
889637c7aa2SImre Deak 
890637c7aa2SImre Deak static void
891637c7aa2SImre Deak main_link_aux_power_domain_get(struct intel_digital_port *dig_port,
892637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
893637c7aa2SImre Deak {
894637c7aa2SImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
895637c7aa2SImre Deak 	enum intel_display_power_domain domain =
896637c7aa2SImre Deak 		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
897637c7aa2SImre Deak 
898637c7aa2SImre Deak 	drm_WARN_ON(&i915->drm, dig_port->aux_wakeref);
899637c7aa2SImre Deak 
900637c7aa2SImre Deak 	if (domain == POWER_DOMAIN_INVALID)
901637c7aa2SImre Deak 		return;
902637c7aa2SImre Deak 
903637c7aa2SImre Deak 	dig_port->aux_wakeref = intel_display_power_get(i915, domain);
904637c7aa2SImre Deak }
905637c7aa2SImre Deak 
906637c7aa2SImre Deak static void
907637c7aa2SImre Deak main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
908637c7aa2SImre Deak 			       const struct intel_crtc_state *crtc_state)
909637c7aa2SImre Deak {
910637c7aa2SImre Deak 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
911637c7aa2SImre Deak 	enum intel_display_power_domain domain =
912637c7aa2SImre Deak 		intel_ddi_main_link_aux_domain(dig_port, crtc_state);
913637c7aa2SImre Deak 	intel_wakeref_t wf;
914637c7aa2SImre Deak 
915637c7aa2SImre Deak 	wf = fetch_and_zero(&dig_port->aux_wakeref);
916637c7aa2SImre Deak 	if (!wf)
917637c7aa2SImre Deak 		return;
918637c7aa2SImre Deak 
919637c7aa2SImre Deak 	intel_display_power_put(i915, domain, wf);
920379bc100SJani Nikula }
921379bc100SJani Nikula 
922379bc100SJani Nikula static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
923379bc100SJani Nikula 					struct intel_crtc_state *crtc_state)
924379bc100SJani Nikula {
925379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
926379bc100SJani Nikula 	struct intel_digital_port *dig_port;
927379bc100SJani Nikula 
928379bc100SJani Nikula 	/*
929379bc100SJani Nikula 	 * TODO: Add support for MST encoders. Atm, the following should never
930379bc100SJani Nikula 	 * happen since fake-MST encoders don't set their get_power_domains()
931379bc100SJani Nikula 	 * hook.
932379bc100SJani Nikula 	 */
9331de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
9341de143ccSPankaj Bharadiya 			intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
935379bc100SJani Nikula 		return;
936379bc100SJani Nikula 
937b7d02c3aSVille Syrjälä 	dig_port = enc_to_dig_port(encoder);
938f77a2db2SImre Deak 
93911a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
940a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
941a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
942f77a2db2SImre Deak 								   dig_port->ddi_io_power_domain);
943a4550977SImre Deak 	}
944379bc100SJani Nikula 
945637c7aa2SImre Deak 	main_link_aux_power_domain_get(dig_port, crtc_state);
946162e68e1SImre Deak }
947379bc100SJani Nikula 
94855a4679eSVille Syrjälä void intel_ddi_enable_transcoder_clock(struct intel_encoder *encoder,
94902a715c3SVille Syrjälä 				       const struct intel_crtc_state *crtc_state)
950379bc100SJani Nikula {
9512225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
952379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
953379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
954ed2615a8SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
955ed2615a8SMatt Roper 	u32 val;
956379bc100SJani Nikula 
95748630a31SVille Syrjälä 	if (cpu_transcoder == TRANSCODER_EDP)
95848630a31SVille Syrjälä 		return;
95948630a31SVille Syrjälä 
960ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
961ed2615a8SMatt Roper 		val = TGL_TRANS_CLK_SEL_PORT(phy);
962ed2615a8SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
963ed2615a8SMatt Roper 		val = TGL_TRANS_CLK_SEL_PORT(encoder->port);
964df16b636SMahesh Kumar 	else
965ed2615a8SMatt Roper 		val = TRANS_CLK_SEL_PORT(encoder->port);
966ed2615a8SMatt Roper 
967ed2615a8SMatt Roper 	intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
968379bc100SJani Nikula }
969379bc100SJani Nikula 
97055a4679eSVille Syrjälä void intel_ddi_disable_transcoder_clock(const struct intel_crtc_state *crtc_state)
971379bc100SJani Nikula {
9722225f3c6SMaarten Lankhorst 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
973379bc100SJani Nikula 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
97448630a31SVille Syrjälä 	u32 val;
975379bc100SJani Nikula 
97648630a31SVille Syrjälä 	if (cpu_transcoder == TRANSCODER_EDP)
97748630a31SVille Syrjälä 		return;
97848630a31SVille Syrjälä 
979005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
98048630a31SVille Syrjälä 		val = TGL_TRANS_CLK_SEL_DISABLED;
981df16b636SMahesh Kumar 	else
98248630a31SVille Syrjälä 		val = TRANS_CLK_SEL_DISABLED;
98348630a31SVille Syrjälä 
98448630a31SVille Syrjälä 	intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
985df16b636SMahesh Kumar }
986379bc100SJani Nikula 
987379bc100SJani Nikula static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
988379bc100SJani Nikula 				enum port port, u8 iboost)
989379bc100SJani Nikula {
990379bc100SJani Nikula 	u32 tmp;
991379bc100SJani Nikula 
992f7960e7fSJani Nikula 	tmp = intel_de_read(dev_priv, DISPIO_CR_TX_BMU_CR0);
993379bc100SJani Nikula 	tmp &= ~(BALANCE_LEG_MASK(port) | BALANCE_LEG_DISABLE(port));
994379bc100SJani Nikula 	if (iboost)
995379bc100SJani Nikula 		tmp |= iboost << BALANCE_LEG_SHIFT(port);
996379bc100SJani Nikula 	else
997379bc100SJani Nikula 		tmp |= BALANCE_LEG_DISABLE(port);
998f7960e7fSJani Nikula 	intel_de_write(dev_priv, DISPIO_CR_TX_BMU_CR0, tmp);
999379bc100SJani Nikula }
1000379bc100SJani Nikula 
1001379bc100SJani Nikula static void skl_ddi_set_iboost(struct intel_encoder *encoder,
1002a621860aSVille Syrjälä 			       const struct intel_crtc_state *crtc_state,
1003a621860aSVille Syrjälä 			       int level)
1004379bc100SJani Nikula {
10057801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1006379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1007379bc100SJani Nikula 	u8 iboost;
1008379bc100SJani Nikula 
1009a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
101002107ef1SVille Syrjälä 		iboost = intel_bios_hdmi_boost_level(encoder->devdata);
1011379bc100SJani Nikula 	else
101202107ef1SVille Syrjälä 		iboost = intel_bios_dp_boost_level(encoder->devdata);
1013379bc100SJani Nikula 
1014379bc100SJani Nikula 	if (iboost == 0) {
1015e505d764SVille Syrjälä 		const struct intel_ddi_buf_trans *trans;
1016379bc100SJani Nikula 		int n_entries;
1017379bc100SJani Nikula 
1018e505d764SVille Syrjälä 		trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1019e505d764SVille Syrjälä 		if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
1020379bc100SJani Nikula 			return;
1021379bc100SJani Nikula 
1022e505d764SVille Syrjälä 		iboost = trans->entries[level].hsw.i_boost;
1023379bc100SJani Nikula 	}
1024379bc100SJani Nikula 
1025379bc100SJani Nikula 	/* Make sure that the requested I_boost is valid */
1026379bc100SJani Nikula 	if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) {
102747bdb1caSJani Nikula 		drm_err(&dev_priv->drm, "Invalid I_boost value %u\n", iboost);
1028379bc100SJani Nikula 		return;
1029379bc100SJani Nikula 	}
1030379bc100SJani Nikula 
1031f0e86e05SJosé Roberto de Souza 	_skl_ddi_set_iboost(dev_priv, encoder->port, iboost);
1032379bc100SJani Nikula 
1033f0e86e05SJosé Roberto de Souza 	if (encoder->port == PORT_A && dig_port->max_lanes == 4)
1034379bc100SJani Nikula 		_skl_ddi_set_iboost(dev_priv, PORT_E, iboost);
1035379bc100SJani Nikula }
1036379bc100SJani Nikula 
1037a621860aSVille Syrjälä static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
1038a621860aSVille Syrjälä 				   const struct intel_crtc_state *crtc_state)
1039379bc100SJani Nikula {
104053de0a20SVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
1041379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1042379bc100SJani Nikula 	int n_entries;
1043379bc100SJani Nikula 
1044c40a253bSVille Syrjälä 	encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1045379bc100SJani Nikula 
10461de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, n_entries < 1))
1047379bc100SJani Nikula 		n_entries = 1;
10481de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm,
10491de143ccSPankaj Bharadiya 			n_entries > ARRAY_SIZE(index_to_dp_signal_levels)))
1050379bc100SJani Nikula 		n_entries = ARRAY_SIZE(index_to_dp_signal_levels);
1051379bc100SJani Nikula 
1052379bc100SJani Nikula 	return index_to_dp_signal_levels[n_entries - 1] &
1053379bc100SJani Nikula 		DP_TRAIN_VOLTAGE_SWING_MASK;
1054379bc100SJani Nikula }
1055379bc100SJani Nikula 
1056379bc100SJani Nikula /*
1057379bc100SJani Nikula  * We assume that the full set of pre-emphasis values can be
1058379bc100SJani Nikula  * used on all DDI platforms. Should that change we need to
1059379bc100SJani Nikula  * rethink this code.
1060379bc100SJani Nikula  */
106153de0a20SVille Syrjälä static u8 intel_ddi_dp_preemph_max(struct intel_dp *intel_dp)
1062379bc100SJani Nikula {
1063379bc100SJani Nikula 	return DP_TRAIN_PRE_EMPH_LEVEL_3;
1064379bc100SJani Nikula }
1065379bc100SJani Nikula 
10665e7fe4d9SVille Syrjälä static u32 icl_combo_phy_loadgen_select(const struct intel_crtc_state *crtc_state,
10675e7fe4d9SVille Syrjälä 					int lane)
10685e7fe4d9SVille Syrjälä {
10695e7fe4d9SVille Syrjälä 	if (crtc_state->port_clock > 600000)
10705e7fe4d9SVille Syrjälä 		return 0;
10715e7fe4d9SVille Syrjälä 
10725e7fe4d9SVille Syrjälä 	if (crtc_state->lane_count == 4)
10735e7fe4d9SVille Syrjälä 		return lane >= 1 ? LOADGEN_SELECT : 0;
10745e7fe4d9SVille Syrjälä 	else
10755e7fe4d9SVille Syrjälä 		return lane == 1 || lane == 2 ? LOADGEN_SELECT : 0;
10765e7fe4d9SVille Syrjälä }
10775e7fe4d9SVille Syrjälä 
1078a8143150SJosé Roberto de Souza static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
1079193299adSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
1080379bc100SJani Nikula {
1081a8143150SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1082e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1083f0e86e05SJosé Roberto de Souza 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
1084a621860aSVille Syrjälä 	int n_entries, ln;
1085a621860aSVille Syrjälä 	u32 val;
1086379bc100SJani Nikula 
1087e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1088e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
108985da0292SVille Syrjälä 		return;
1090379bc100SJani Nikula 
1091a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
109281619f4aSJosé Roberto de Souza 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
109381619f4aSJosé Roberto de Souza 
109481619f4aSJosé Roberto de Souza 		val = EDP4K2K_MODE_OVRD_EN | EDP4K2K_MODE_OVRD_OPTIMIZED;
1095e505d764SVille Syrjälä 		intel_dp->hobl_active = is_hobl_buf_trans(trans);
109681619f4aSJosé Roberto de Souza 		intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy), val,
109781619f4aSJosé Roberto de Souza 			     intel_dp->hobl_active ? val : 0);
109881619f4aSJosé Roberto de Souza 	}
109981619f4aSJosé Roberto de Souza 
1100379bc100SJani Nikula 	/* Set PORT_TX_DW5 */
1101e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1102379bc100SJani Nikula 	val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
1103379bc100SJani Nikula 		  TAP2_DISABLE | TAP3_DISABLE);
1104379bc100SJani Nikula 	val |= SCALING_MODE_SEL(0x2);
1105379bc100SJani Nikula 	val |= RTERM_SELECT(0x6);
1106379bc100SJani Nikula 	val |= TAP3_DISABLE;
1107f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1108379bc100SJani Nikula 
1109379bc100SJani Nikula 	/* Program PORT_TX_DW2 */
1110f20ca899SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
111131e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
111231e914a2SVille Syrjälä 
1113c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy),
1114c1d53cbdSVille Syrjälä 			     SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK | RCOMP_SCALAR_MASK,
1115c1d53cbdSVille Syrjälä 			     SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel) |
1116c1d53cbdSVille Syrjälä 			     SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel) |
1117c1d53cbdSVille Syrjälä 			     RCOMP_SCALAR(0x98));
1118f20ca899SVille Syrjälä 	}
1119379bc100SJani Nikula 
1120379bc100SJani Nikula 	/* Program PORT_TX_DW4 */
1121379bc100SJani Nikula 	/* We cannot write to GRP. It would overwrite individual loadgen. */
1122a1f01768SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
112331e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
112431e914a2SVille Syrjälä 
1125c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1126c1d53cbdSVille Syrjälä 			     POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK,
1127c1d53cbdSVille Syrjälä 			     POST_CURSOR_1(trans->entries[level].icl.dw4_post_cursor_1) |
1128c1d53cbdSVille Syrjälä 			     POST_CURSOR_2(trans->entries[level].icl.dw4_post_cursor_2) |
1129c1d53cbdSVille Syrjälä 			     CURSOR_COEFF(trans->entries[level].icl.dw4_cursor_coeff));
1130379bc100SJani Nikula 	}
1131379bc100SJani Nikula 
1132379bc100SJani Nikula 	/* Program PORT_TX_DW7 */
1133f20ca899SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
113431e914a2SVille Syrjälä 		int level = intel_ddi_level(encoder, crtc_state, ln);
113531e914a2SVille Syrjälä 
1136c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy),
1137c1d53cbdSVille Syrjälä 			     N_SCALAR_MASK,
1138c1d53cbdSVille Syrjälä 			     N_SCALAR(trans->entries[level].icl.dw7_n_scalar));
1139f20ca899SVille Syrjälä 	}
1140379bc100SJani Nikula }
1141379bc100SJani Nikula 
1142193299adSVille Syrjälä static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder,
1143193299adSVille Syrjälä 					    const struct intel_crtc_state *crtc_state)
1144379bc100SJani Nikula {
1145379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1146dc867bc7SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
1147379bc100SJani Nikula 	u32 val;
11485e7fe4d9SVille Syrjälä 	int ln;
1149379bc100SJani Nikula 
1150379bc100SJani Nikula 	/*
1151379bc100SJani Nikula 	 * 1. If port type is eDP or DP,
1152379bc100SJani Nikula 	 * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
1153379bc100SJani Nikula 	 * else clear to 0b.
1154379bc100SJani Nikula 	 */
1155e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
1156a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1157379bc100SJani Nikula 		val &= ~COMMON_KEEPER_EN;
1158379bc100SJani Nikula 	else
1159379bc100SJani Nikula 		val |= COMMON_KEEPER_EN;
1160f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
1161379bc100SJani Nikula 
1162379bc100SJani Nikula 	/* 2. Program loadgen select */
1163379bc100SJani Nikula 	/*
1164e6908588SVille Syrjälä 	 * Program PORT_TX_DW4 depending on Bit rate and used lanes
1165379bc100SJani Nikula 	 * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
1166379bc100SJani Nikula 	 * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
1167379bc100SJani Nikula 	 * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
1168379bc100SJani Nikula 	 */
1169a1f01768SVille Syrjälä 	for (ln = 0; ln < 4; ln++) {
1170c1d53cbdSVille Syrjälä 		intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1171c1d53cbdSVille Syrjälä 			     LOADGEN_SELECT,
1172c1d53cbdSVille Syrjälä 			     icl_combo_phy_loadgen_select(crtc_state, ln));
1173379bc100SJani Nikula 	}
1174379bc100SJani Nikula 
1175379bc100SJani Nikula 	/* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
1176c1d53cbdSVille Syrjälä 	intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy),
1177c1d53cbdSVille Syrjälä 		     0, SUS_CLOCK_CONFIG);
1178379bc100SJani Nikula 
1179379bc100SJani Nikula 	/* 4. Clear training enable to change swing values */
1180e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1181379bc100SJani Nikula 	val &= ~TX_TRAINING_EN;
1182f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1183379bc100SJani Nikula 
1184379bc100SJani Nikula 	/* 5. Program swing and de-emphasis */
1185193299adSVille Syrjälä 	icl_ddi_combo_vswing_program(encoder, crtc_state);
1186379bc100SJani Nikula 
1187379bc100SJani Nikula 	/* 6. Set training enable to trigger update */
1188e6908588SVille Syrjälä 	val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1189379bc100SJani Nikula 	val |= TX_TRAINING_EN;
1190f7960e7fSJani Nikula 	intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1191379bc100SJani Nikula }
1192379bc100SJani Nikula 
1193193299adSVille Syrjälä static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder,
1194193299adSVille Syrjälä 					 const struct intel_crtc_state *crtc_state)
1195379bc100SJani Nikula {
1196379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1197f21e8b80SJosé Roberto de Souza 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
1198e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1199a621860aSVille Syrjälä 	int n_entries, ln;
1200379bc100SJani Nikula 
120111a89708SImre Deak 	if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1202f8c6b615SVille Syrjälä 		return;
1203f8c6b615SVille Syrjälä 
1204e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1205e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
120685da0292SVille Syrjälä 		return;
1207379bc100SJani Nikula 
1208379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1209d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port),
1210d4e0f163SVille Syrjälä 			     CRI_USE_FS32, 0);
1211d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port),
1212d4e0f163SVille Syrjälä 			     CRI_USE_FS32, 0);
1213379bc100SJani Nikula 	}
1214379bc100SJani Nikula 
1215379bc100SJani Nikula 	/* Program MG_TX_SWINGCTRL with values from vswing table */
1216379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1217305448e5SVille Syrjälä 		int level;
1218305448e5SVille Syrjälä 
1219305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1220305448e5SVille Syrjälä 
1221d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port),
1222d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1223d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1224379bc100SJani Nikula 
1225305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1226305448e5SVille Syrjälä 
1227d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port),
1228d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1229d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1230379bc100SJani Nikula 	}
1231379bc100SJani Nikula 
1232379bc100SJani Nikula 	/* Program MG_TX_DRVCTRL with values from vswing table */
1233379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1234305448e5SVille Syrjälä 		int level;
1235305448e5SVille Syrjälä 
1236305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1237305448e5SVille Syrjälä 
1238d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_DRVCTRL(ln, tc_port),
1239d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1240d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1241d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1242d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1243d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_EN);
1244379bc100SJani Nikula 
1245305448e5SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1246305448e5SVille Syrjälä 
1247d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_DRVCTRL(ln, tc_port),
1248d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1249d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1250d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1251d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1252d4e0f163SVille Syrjälä 			     CRI_TXDEEMPH_OVERRIDE_EN);
1253379bc100SJani Nikula 
1254379bc100SJani Nikula 		/* FIXME: Program CRI_LOADGEN_SEL after the spec is updated */
1255379bc100SJani Nikula 	}
1256379bc100SJani Nikula 
1257379bc100SJani Nikula 	/*
1258379bc100SJani Nikula 	 * Program MG_CLKHUB<LN, port being used> with value from frequency table
1259379bc100SJani Nikula 	 * In case of Legacy mode on MG PHY, both TX1 and TX2 enabled so use the
1260379bc100SJani Nikula 	 * values from table for which TX1 and TX2 enabled.
1261379bc100SJani Nikula 	 */
1262379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1263d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_CLKHUB(ln, tc_port),
1264d4e0f163SVille Syrjälä 			     CFG_LOW_RATE_LKREN_EN,
1265d4e0f163SVille Syrjälä 			     crtc_state->port_clock < 300000 ? CFG_LOW_RATE_LKREN_EN : 0);
1266379bc100SJani Nikula 	}
1267379bc100SJani Nikula 
1268379bc100SJani Nikula 	/* Program the MG_TX_DCC<LN, port being used> based on the link frequency */
1269379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1270d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_DCC(ln, tc_port),
1271d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1272d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN,
1273d4e0f163SVille Syrjälä 			     crtc_state->port_clock > 500000 ?
1274d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1275d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1276379bc100SJani Nikula 
1277d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_DCC(ln, tc_port),
1278d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1279d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN,
1280d4e0f163SVille Syrjälä 			     crtc_state->port_clock > 500000 ?
1281d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1282d4e0f163SVille Syrjälä 			     CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1283379bc100SJani Nikula 	}
1284379bc100SJani Nikula 
1285379bc100SJani Nikula 	/* Program MG_TX_PISO_READLOAD with values from vswing table */
1286379bc100SJani Nikula 	for (ln = 0; ln < 2; ln++) {
1287d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX1_PISO_READLOAD(ln, tc_port),
1288d4e0f163SVille Syrjälä 			     0, CRI_CALCINIT);
1289d4e0f163SVille Syrjälä 		intel_de_rmw(dev_priv, MG_TX2_PISO_READLOAD(ln, tc_port),
1290d4e0f163SVille Syrjälä 			     0, CRI_CALCINIT);
1291379bc100SJani Nikula 	}
1292379bc100SJani Nikula }
1293379bc100SJani Nikula 
1294193299adSVille Syrjälä static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
1295193299adSVille Syrjälä 					  const struct intel_crtc_state *crtc_state)
1296978c3e53SClinton A Taylor {
1297978c3e53SClinton A Taylor 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1298978c3e53SClinton A Taylor 	enum tc_port tc_port = intel_port_to_tc(dev_priv, encoder->port);
1299e505d764SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
1300a621860aSVille Syrjälä 	int n_entries, ln;
1301978c3e53SClinton A Taylor 
130211a89708SImre Deak 	if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1303f8c6b615SVille Syrjälä 		return;
1304f8c6b615SVille Syrjälä 
1305e505d764SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1306e505d764SVille Syrjälä 	if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
130785da0292SVille Syrjälä 		return;
1308978c3e53SClinton A Taylor 
1309978c3e53SClinton A Taylor 	for (ln = 0; ln < 2; ln++) {
1310a905ced6SVille Syrjälä 		int level;
1311a905ced6SVille Syrjälä 
1312b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0);
13132d69c42eSJosé Roberto de Souza 
1314a905ced6SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1315a905ced6SVille Syrjälä 
1316b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln),
1317c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF_MASK |
1318a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1319c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL_MASK,
1320c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1321a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1322c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1323978c3e53SClinton A Taylor 
1324a905ced6SVille Syrjälä 		level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1325a905ced6SVille Syrjälä 
1326b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln),
1327c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF_MASK |
1328a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1329c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL_MASK,
1330c86e1873SVille Syrjälä 				  DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1331a905ced6SVille Syrjälä 				  DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1332c86e1873SVille Syrjälä 				  DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1333978c3e53SClinton A Taylor 
1334b8ed5533SImre Deak 		intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
1335c86e1873SVille Syrjälä 				  DKL_TX_DP20BITMODE, 0);
13365ff59dddSJosé Roberto de Souza 
13375ff59dddSJosé Roberto de Souza 		if (IS_ALDERLAKE_P(dev_priv)) {
13385ff59dddSJosé Roberto de Souza 			u32 val;
13395ff59dddSJosé Roberto de Souza 
13405ff59dddSJosé Roberto de Souza 			if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
13415ff59dddSJosé Roberto de Souza 				if (ln == 0) {
13425ff59dddSJosé Roberto de Souza 					val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13435ff59dddSJosé Roberto de Souza 					val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(2);
13445ff59dddSJosé Roberto de Souza 				} else {
13455ff59dddSJosé Roberto de Souza 					val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(3);
13465ff59dddSJosé Roberto de Souza 					val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(3);
13475ff59dddSJosé Roberto de Souza 				}
13485ff59dddSJosé Roberto de Souza 			} else {
13495ff59dddSJosé Roberto de Souza 				val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13505ff59dddSJosé Roberto de Souza 				val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0);
13515ff59dddSJosé Roberto de Souza 			}
13525ff59dddSJosé Roberto de Souza 
1353b8ed5533SImre Deak 			intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
13545ff59dddSJosé Roberto de Souza 					  DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
13555ff59dddSJosé Roberto de Souza 					  DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
13565ff59dddSJosé Roberto de Souza 					  val);
13575ff59dddSJosé Roberto de Souza 		}
1358978c3e53SClinton A Taylor 	}
1359978c3e53SClinton A Taylor }
1360978c3e53SClinton A Taylor 
1361a621860aSVille Syrjälä static int translate_signal_level(struct intel_dp *intel_dp,
1362a621860aSVille Syrjälä 				  u8 signal_levels)
1363379bc100SJani Nikula {
13648b4f2137SPankaj Bharadiya 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
1365379bc100SJani Nikula 	int i;
1366379bc100SJani Nikula 
1367379bc100SJani Nikula 	for (i = 0; i < ARRAY_SIZE(index_to_dp_signal_levels); i++) {
1368379bc100SJani Nikula 		if (index_to_dp_signal_levels[i] == signal_levels)
1369379bc100SJani Nikula 			return i;
1370379bc100SJani Nikula 	}
1371379bc100SJani Nikula 
13728b4f2137SPankaj Bharadiya 	drm_WARN(&i915->drm, 1,
13738b4f2137SPankaj Bharadiya 		 "Unsupported voltage swing/pre-emphasis level: 0x%x\n",
1374379bc100SJani Nikula 		 signal_levels);
1375379bc100SJani Nikula 
1376379bc100SJani Nikula 	return 0;
1377379bc100SJani Nikula }
1378379bc100SJani Nikula 
13795c31e9d0SJani Nikula static int intel_ddi_dp_level(struct intel_dp *intel_dp,
13805c31e9d0SJani Nikula 			      const struct intel_crtc_state *crtc_state,
13815c31e9d0SJani Nikula 			      int lane)
1382379bc100SJani Nikula {
1383d0920a45SVille Syrjälä 	u8 train_set = intel_dp->train_set[lane];
13845c31e9d0SJani Nikula 
13855c31e9d0SJani Nikula 	if (intel_dp_is_uhbr(crtc_state)) {
13865c31e9d0SJani Nikula 		return train_set & DP_TX_FFE_PRESET_VALUE_MASK;
13875c31e9d0SJani Nikula 	} else {
1388a621860aSVille Syrjälä 		u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
1389379bc100SJani Nikula 						DP_TRAIN_PRE_EMPHASIS_MASK);
1390379bc100SJani Nikula 
13918b4f2137SPankaj Bharadiya 		return translate_signal_level(intel_dp, signal_levels);
1392379bc100SJani Nikula 	}
13935c31e9d0SJani Nikula }
1394379bc100SJani Nikula 
1395193299adSVille Syrjälä int intel_ddi_level(struct intel_encoder *encoder,
1396d0920a45SVille Syrjälä 		    const struct intel_crtc_state *crtc_state,
1397d0920a45SVille Syrjälä 		    int lane)
1398a046a0daSMatt Roper {
13992c63e0f9SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
14002c63e0f9SVille Syrjälä 	const struct intel_ddi_buf_trans *trans;
14012c63e0f9SVille Syrjälä 	int level, n_entries;
14022c63e0f9SVille Syrjälä 
14032c63e0f9SVille Syrjälä 	trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
14042c63e0f9SVille Syrjälä 	if (drm_WARN_ON_ONCE(&i915->drm, !trans))
14052c63e0f9SVille Syrjälä 		return 0;
14062c63e0f9SVille Syrjälä 
1407e722ab8bSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
14083e022c1fSVille Syrjälä 		level = intel_ddi_hdmi_level(encoder, trans);
1409e722ab8bSVille Syrjälä 	else
14105c31e9d0SJani Nikula 		level = intel_ddi_dp_level(enc_to_intel_dp(encoder), crtc_state,
14115c31e9d0SJani Nikula 					   lane);
14122c63e0f9SVille Syrjälä 
14132c63e0f9SVille Syrjälä 	if (drm_WARN_ON_ONCE(&i915->drm, level >= n_entries))
14142c63e0f9SVille Syrjälä 		level = n_entries - 1;
14152c63e0f9SVille Syrjälä 
14162c63e0f9SVille Syrjälä 	return level;
1417e722ab8bSVille Syrjälä }
1418e722ab8bSVille Syrjälä 
1419e722ab8bSVille Syrjälä static void
1420e722ab8bSVille Syrjälä hsw_set_signal_levels(struct intel_encoder *encoder,
1421a621860aSVille Syrjälä 		      const struct intel_crtc_state *crtc_state)
1422fb83f72cSVille Syrjälä {
1423fb83f72cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1424e722ab8bSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1425d0920a45SVille Syrjälä 	int level = intel_ddi_level(encoder, crtc_state, 0);
1426fb83f72cSVille Syrjälä 	enum port port = encoder->port;
1427fb83f72cSVille Syrjälä 	u32 signal_levels;
1428fb83f72cSVille Syrjälä 
1429e722ab8bSVille Syrjälä 	if (has_iboost(dev_priv))
1430e722ab8bSVille Syrjälä 		skl_ddi_set_iboost(encoder, crtc_state, level);
1431e722ab8bSVille Syrjälä 
1432e722ab8bSVille Syrjälä 	/* HDMI ignores the rest */
1433e722ab8bSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1434e722ab8bSVille Syrjälä 		return;
1435e722ab8bSVille Syrjälä 
1436fb83f72cSVille Syrjälä 	signal_levels = DDI_BUF_TRANS_SELECT(level);
1437fb83f72cSVille Syrjälä 
1438fb83f72cSVille Syrjälä 	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
1439fb83f72cSVille Syrjälä 		    signal_levels);
1440fb83f72cSVille Syrjälä 
1441fb83f72cSVille Syrjälä 	intel_dp->DP &= ~DDI_BUF_EMP_MASK;
1442fb83f72cSVille Syrjälä 	intel_dp->DP |= signal_levels;
1443fb83f72cSVille Syrjälä 
1444fb83f72cSVille Syrjälä 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
1445fb83f72cSVille Syrjälä 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
1446379bc100SJani Nikula }
1447379bc100SJani Nikula 
14484da27d5dSLucas De Marchi static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14499c6a5c35SVille Syrjälä 				  u32 clk_sel_mask, u32 clk_sel, u32 clk_off)
14509c6a5c35SVille Syrjälä {
145136d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
14529c6a5c35SVille Syrjälä 
14539c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, clk_sel_mask, clk_sel);
14549c6a5c35SVille Syrjälä 
14559c6a5c35SVille Syrjälä 	/*
14569c6a5c35SVille Syrjälä 	 * "This step and the step before must be
14579c6a5c35SVille Syrjälä 	 *  done with separate register writes."
14589c6a5c35SVille Syrjälä 	 */
14599c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, clk_off, 0);
14609c6a5c35SVille Syrjälä 
146136d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
14629c6a5c35SVille Syrjälä }
14639c6a5c35SVille Syrjälä 
14644da27d5dSLucas De Marchi static void _icl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14659c6a5c35SVille Syrjälä 				   u32 clk_off)
14669c6a5c35SVille Syrjälä {
146736d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
14689c6a5c35SVille Syrjälä 
14699c6a5c35SVille Syrjälä 	intel_de_rmw(i915, reg, 0, clk_off);
14709c6a5c35SVille Syrjälä 
147136d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
14729c6a5c35SVille Syrjälä }
14739c6a5c35SVille Syrjälä 
14744da27d5dSLucas De Marchi static bool _icl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg,
14750fbd8694SVille Syrjälä 				      u32 clk_off)
14760fbd8694SVille Syrjälä {
14770fbd8694SVille Syrjälä 	return !(intel_de_read(i915, reg) & clk_off);
14780fbd8694SVille Syrjälä }
14790fbd8694SVille Syrjälä 
1480351221ffSVille Syrjälä static struct intel_shared_dpll *
14814da27d5dSLucas De Marchi _icl_ddi_get_pll(struct drm_i915_private *i915, i915_reg_t reg,
1482351221ffSVille Syrjälä 		 u32 clk_sel_mask, u32 clk_sel_shift)
1483351221ffSVille Syrjälä {
1484351221ffSVille Syrjälä 	enum intel_dpll_id id;
1485351221ffSVille Syrjälä 
1486351221ffSVille Syrjälä 	id = (intel_de_read(i915, reg) & clk_sel_mask) >> clk_sel_shift;
1487351221ffSVille Syrjälä 
1488351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1489351221ffSVille Syrjälä }
1490351221ffSVille Syrjälä 
149140b316d4SVille Syrjälä static void adls_ddi_enable_clock(struct intel_encoder *encoder,
149240b316d4SVille Syrjälä 				  const struct intel_crtc_state *crtc_state)
149340b316d4SVille Syrjälä {
149440b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
149540b316d4SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
149640b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
149740b316d4SVille Syrjälä 
149840b316d4SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
149940b316d4SVille Syrjälä 		return;
150040b316d4SVille Syrjälä 
15014da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
150240b316d4SVille Syrjälä 			      ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
150340b316d4SVille Syrjälä 			      pll->info->id << ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy),
150440b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
150540b316d4SVille Syrjälä }
150640b316d4SVille Syrjälä 
150740b316d4SVille Syrjälä static void adls_ddi_disable_clock(struct intel_encoder *encoder)
150840b316d4SVille Syrjälä {
150940b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
151040b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
151140b316d4SVille Syrjälä 
15124da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
151340b316d4SVille Syrjälä 			       ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
151440b316d4SVille Syrjälä }
151540b316d4SVille Syrjälä 
15160fbd8694SVille Syrjälä static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder)
15170fbd8694SVille Syrjälä {
15180fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15190fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
15200fbd8694SVille Syrjälä 
15214da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy),
15220fbd8694SVille Syrjälä 					 ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15230fbd8694SVille Syrjälä }
15240fbd8694SVille Syrjälä 
1525351221ffSVille Syrjälä static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
1526351221ffSVille Syrjälä {
1527351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1528351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1529351221ffSVille Syrjälä 
15304da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy),
1531351221ffSVille Syrjälä 				ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
1532351221ffSVille Syrjälä 				ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy));
1533351221ffSVille Syrjälä }
1534351221ffSVille Syrjälä 
153540b316d4SVille Syrjälä static void rkl_ddi_enable_clock(struct intel_encoder *encoder,
153640b316d4SVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
153740b316d4SVille Syrjälä {
153840b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
153940b316d4SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
154040b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
154140b316d4SVille Syrjälä 
154240b316d4SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
154340b316d4SVille Syrjälä 		return;
154440b316d4SVille Syrjälä 
15454da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
154640b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
154740b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
154840b316d4SVille Syrjälä 			      RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
154940b316d4SVille Syrjälä }
155040b316d4SVille Syrjälä 
155140b316d4SVille Syrjälä static void rkl_ddi_disable_clock(struct intel_encoder *encoder)
155240b316d4SVille Syrjälä {
155340b316d4SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
155440b316d4SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
155540b316d4SVille Syrjälä 
15564da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
155740b316d4SVille Syrjälä 			       RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
155840b316d4SVille Syrjälä }
155940b316d4SVille Syrjälä 
15600fbd8694SVille Syrjälä static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder)
15610fbd8694SVille Syrjälä {
15620fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15630fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
15640fbd8694SVille Syrjälä 
15654da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
15660fbd8694SVille Syrjälä 					 RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15670fbd8694SVille Syrjälä }
15680fbd8694SVille Syrjälä 
1569351221ffSVille Syrjälä static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
1570351221ffSVille Syrjälä {
1571351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1572351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1573351221ffSVille Syrjälä 
15744da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1575351221ffSVille Syrjälä 				RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1576351221ffSVille Syrjälä 				RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1577351221ffSVille Syrjälä }
1578351221ffSVille Syrjälä 
157935bb6b1aSVille Syrjälä static void dg1_ddi_enable_clock(struct intel_encoder *encoder,
158011ffe972SLucas De Marchi 				 const struct intel_crtc_state *crtc_state)
158111ffe972SLucas De Marchi {
158297a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15839c6a5c35SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
158497a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
158511ffe972SLucas De Marchi 
158697a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1587f67a008eSVille Syrjälä 		return;
1588f67a008eSVille Syrjälä 
158911ffe972SLucas De Marchi 	/*
159011ffe972SLucas De Marchi 	 * If we fail this, something went very wrong: first 2 PLLs should be
159111ffe972SLucas De Marchi 	 * used by first 2 phys and last 2 PLLs by last phys
159211ffe972SLucas De Marchi 	 */
159397a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm,
159411ffe972SLucas De Marchi 			(pll->info->id < DPLL_ID_DG1_DPLL2 && phy >= PHY_C) ||
159511ffe972SLucas De Marchi 			(pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C)))
159611ffe972SLucas De Marchi 		return;
159711ffe972SLucas De Marchi 
15984da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
15997815ed88SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
16009c6a5c35SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
16019c6a5c35SVille Syrjälä 			      DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
160211ffe972SLucas De Marchi }
160311ffe972SLucas De Marchi 
160435bb6b1aSVille Syrjälä static void dg1_ddi_disable_clock(struct intel_encoder *encoder)
160535bb6b1aSVille Syrjälä {
160697a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
160797a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
160835bb6b1aSVille Syrjälä 
16094da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16109c6a5c35SVille Syrjälä 			       DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
161135bb6b1aSVille Syrjälä }
161235bb6b1aSVille Syrjälä 
16130fbd8694SVille Syrjälä static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder)
16140fbd8694SVille Syrjälä {
16150fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16160fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16170fbd8694SVille Syrjälä 
16184da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy),
16190fbd8694SVille Syrjälä 					 DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
16200fbd8694SVille Syrjälä }
16210fbd8694SVille Syrjälä 
1622351221ffSVille Syrjälä static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
1623351221ffSVille Syrjälä {
1624351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1625351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16263352d86dSJosé Roberto de Souza 	enum intel_dpll_id id;
16273352d86dSJosé Roberto de Souza 	u32 val;
1628351221ffSVille Syrjälä 
16293352d86dSJosé Roberto de Souza 	val = intel_de_read(i915, DG1_DPCLKA_CFGCR0(phy));
16303352d86dSJosé Roberto de Souza 	val &= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
16313352d86dSJosé Roberto de Souza 	val >>= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
16323352d86dSJosé Roberto de Souza 	id = val;
16333352d86dSJosé Roberto de Souza 
16343352d86dSJosé Roberto de Souza 	/*
16353352d86dSJosé Roberto de Souza 	 * _DG1_DPCLKA0_CFGCR0 maps between DPLL 0 and 1 with one bit for phy A
16363352d86dSJosé Roberto de Souza 	 * and B while _DG1_DPCLKA1_CFGCR0 maps between DPLL 2 and 3 with one
16373352d86dSJosé Roberto de Souza 	 * bit for phy C and D.
16383352d86dSJosé Roberto de Souza 	 */
16393352d86dSJosé Roberto de Souza 	if (phy >= PHY_C)
16403352d86dSJosé Roberto de Souza 		id += DPLL_ID_DG1_DPLL2;
16413352d86dSJosé Roberto de Souza 
16423352d86dSJosé Roberto de Souza 	return intel_get_shared_dpll_by_id(i915, id);
1643351221ffSVille Syrjälä }
1644351221ffSVille Syrjälä 
164536ecb0ecSVille Syrjälä static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder,
1646379bc100SJani Nikula 				       const struct intel_crtc_state *crtc_state)
1647379bc100SJani Nikula {
164897a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16499c6a5c35SVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
165097a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1651cd803bb4SMatt Roper 
165297a24a70SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1653f67a008eSVille Syrjälä 		return;
1654f67a008eSVille Syrjälä 
16554da27d5dSLucas De Marchi 	_icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
165640b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
165740b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
165840b316d4SVille Syrjälä 			      ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1659379bc100SJani Nikula }
1660379bc100SJani Nikula 
166136ecb0ecSVille Syrjälä static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder)
1662379bc100SJani Nikula {
166397a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
166497a24a70SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1665379bc100SJani Nikula 
16664da27d5dSLucas De Marchi 	_icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
166740b316d4SVille Syrjälä 			       ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1668379bc100SJani Nikula }
1669379bc100SJani Nikula 
16700fbd8694SVille Syrjälä static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder)
16710fbd8694SVille Syrjälä {
16720fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16730fbd8694SVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
16740fbd8694SVille Syrjälä 
16754da27d5dSLucas De Marchi 	return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
16760fbd8694SVille Syrjälä 					 ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
16770fbd8694SVille Syrjälä }
16780fbd8694SVille Syrjälä 
1679351221ffSVille Syrjälä struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
1680351221ffSVille Syrjälä {
1681351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1682351221ffSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
1683351221ffSVille Syrjälä 
16844da27d5dSLucas De Marchi 	return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1685351221ffSVille Syrjälä 				ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1686351221ffSVille Syrjälä 				ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1687351221ffSVille Syrjälä }
1688351221ffSVille Syrjälä 
168936ecb0ecSVille Syrjälä static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder,
1690379bc100SJani Nikula 				    const struct intel_crtc_state *crtc_state)
1691379bc100SJani Nikula {
169236ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1693379bc100SJani Nikula 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
169436ecb0ecSVille Syrjälä 	enum port port = encoder->port;
1695379bc100SJani Nikula 
169636ecb0ecSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1697379bc100SJani Nikula 		return;
1698379bc100SJani Nikula 
1699c2052d6eSJosé Roberto de Souza 	/*
170036ecb0ecSVille Syrjälä 	 * "For DDIC and DDID, program DDI_CLK_SEL to map the MG clock to the port.
170136ecb0ecSVille Syrjälä 	 *  MG does not exist, but the programming is required to ungate DDIC and DDID."
1702c2052d6eSJosé Roberto de Souza 	 */
170336ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_MG);
170436ecb0ecSVille Syrjälä 
170536ecb0ecSVille Syrjälä 	icl_ddi_combo_enable_clock(encoder, crtc_state);
1706379bc100SJani Nikula }
1707379bc100SJani Nikula 
170836ecb0ecSVille Syrjälä static void jsl_ddi_tc_disable_clock(struct intel_encoder *encoder)
1709379bc100SJani Nikula {
171036ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1711379bc100SJani Nikula 	enum port port = encoder->port;
1712379bc100SJani Nikula 
171336ecb0ecSVille Syrjälä 	icl_ddi_combo_disable_clock(encoder);
171436ecb0ecSVille Syrjälä 
171536ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1716379bc100SJani Nikula }
171736ecb0ecSVille Syrjälä 
17180fbd8694SVille Syrjälä static bool jsl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17190fbd8694SVille Syrjälä {
17200fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17210fbd8694SVille Syrjälä 	enum port port = encoder->port;
17220fbd8694SVille Syrjälä 	u32 tmp;
17230fbd8694SVille Syrjälä 
17240fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
17250fbd8694SVille Syrjälä 
17260fbd8694SVille Syrjälä 	if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
17270fbd8694SVille Syrjälä 		return false;
17280fbd8694SVille Syrjälä 
17290fbd8694SVille Syrjälä 	return icl_ddi_combo_is_clock_enabled(encoder);
17300fbd8694SVille Syrjälä }
17310fbd8694SVille Syrjälä 
173236ecb0ecSVille Syrjälä static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder,
173336ecb0ecSVille Syrjälä 				    const struct intel_crtc_state *crtc_state)
173436ecb0ecSVille Syrjälä {
173536ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
173636ecb0ecSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
173736ecb0ecSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
173836ecb0ecSVille Syrjälä 	enum port port = encoder->port;
173936ecb0ecSVille Syrjälä 
174036ecb0ecSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
174136ecb0ecSVille Syrjälä 		return;
174236ecb0ecSVille Syrjälä 
174336ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port),
174436ecb0ecSVille Syrjälä 		       icl_pll_to_ddi_clk_sel(encoder, crtc_state));
174536ecb0ecSVille Syrjälä 
174636d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
174736ecb0ecSVille Syrjälä 
174836ecb0ecSVille Syrjälä 	intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
174936ecb0ecSVille Syrjälä 		     ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port), 0);
175036ecb0ecSVille Syrjälä 
175136d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
175236ecb0ecSVille Syrjälä }
175336ecb0ecSVille Syrjälä 
175436ecb0ecSVille Syrjälä static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder)
175536ecb0ecSVille Syrjälä {
175636ecb0ecSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
175736ecb0ecSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
175836ecb0ecSVille Syrjälä 	enum port port = encoder->port;
175936ecb0ecSVille Syrjälä 
176036d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
176136ecb0ecSVille Syrjälä 
176236ecb0ecSVille Syrjälä 	intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
176336ecb0ecSVille Syrjälä 		     0, ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
176436ecb0ecSVille Syrjälä 
176536d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
176636ecb0ecSVille Syrjälä 
176736ecb0ecSVille Syrjälä 	intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1768379bc100SJani Nikula }
1769379bc100SJani Nikula 
17700fbd8694SVille Syrjälä static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17710fbd8694SVille Syrjälä {
17720fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17730fbd8694SVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
17740fbd8694SVille Syrjälä 	enum port port = encoder->port;
17750fbd8694SVille Syrjälä 	u32 tmp;
17760fbd8694SVille Syrjälä 
17770fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
17780fbd8694SVille Syrjälä 
17790fbd8694SVille Syrjälä 	if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
17800fbd8694SVille Syrjälä 		return false;
17810fbd8694SVille Syrjälä 
17820fbd8694SVille Syrjälä 	tmp = intel_de_read(i915, ICL_DPCLKA_CFGCR0);
17830fbd8694SVille Syrjälä 
17840fbd8694SVille Syrjälä 	return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
17850fbd8694SVille Syrjälä }
17860fbd8694SVille Syrjälä 
1787351221ffSVille Syrjälä static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder)
1788351221ffSVille Syrjälä {
1789351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1790351221ffSVille Syrjälä 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
1791351221ffSVille Syrjälä 	enum port port = encoder->port;
1792351221ffSVille Syrjälä 	enum intel_dpll_id id;
1793351221ffSVille Syrjälä 	u32 tmp;
1794351221ffSVille Syrjälä 
1795351221ffSVille Syrjälä 	tmp = intel_de_read(i915, DDI_CLK_SEL(port));
1796351221ffSVille Syrjälä 
1797351221ffSVille Syrjälä 	switch (tmp & DDI_CLK_SEL_MASK) {
1798351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_162:
1799351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_270:
1800351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_540:
1801351221ffSVille Syrjälä 	case DDI_CLK_SEL_TBT_810:
1802351221ffSVille Syrjälä 		id = DPLL_ID_ICL_TBTPLL;
1803351221ffSVille Syrjälä 		break;
1804351221ffSVille Syrjälä 	case DDI_CLK_SEL_MG:
1805351221ffSVille Syrjälä 		id = icl_tc_port_to_pll_id(tc_port);
1806351221ffSVille Syrjälä 		break;
1807351221ffSVille Syrjälä 	default:
1808351221ffSVille Syrjälä 		MISSING_CASE(tmp);
1809351221ffSVille Syrjälä 		fallthrough;
1810351221ffSVille Syrjälä 	case DDI_CLK_SEL_NONE:
1811351221ffSVille Syrjälä 		return NULL;
1812351221ffSVille Syrjälä 	}
1813351221ffSVille Syrjälä 
1814351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1815351221ffSVille Syrjälä }
1816351221ffSVille Syrjälä 
1817351221ffSVille Syrjälä static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
1818351221ffSVille Syrjälä {
1819351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1820351221ffSVille Syrjälä 	enum intel_dpll_id id;
1821351221ffSVille Syrjälä 
1822351221ffSVille Syrjälä 	switch (encoder->port) {
1823351221ffSVille Syrjälä 	case PORT_A:
1824351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL0;
1825351221ffSVille Syrjälä 		break;
1826351221ffSVille Syrjälä 	case PORT_B:
1827351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL1;
1828351221ffSVille Syrjälä 		break;
1829351221ffSVille Syrjälä 	case PORT_C:
1830351221ffSVille Syrjälä 		id = DPLL_ID_SKL_DPLL2;
1831351221ffSVille Syrjälä 		break;
1832351221ffSVille Syrjälä 	default:
1833351221ffSVille Syrjälä 		MISSING_CASE(encoder->port);
1834351221ffSVille Syrjälä 		return NULL;
1835351221ffSVille Syrjälä 	}
1836351221ffSVille Syrjälä 
1837351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1838351221ffSVille Syrjälä }
1839351221ffSVille Syrjälä 
184038e31f1aSVille Syrjälä static void skl_ddi_enable_clock(struct intel_encoder *encoder,
184138e31f1aSVille Syrjälä 				 const struct intel_crtc_state *crtc_state)
184238e31f1aSVille Syrjälä {
184338e31f1aSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
184438e31f1aSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
184538e31f1aSVille Syrjälä 	enum port port = encoder->port;
184638e31f1aSVille Syrjälä 
184738e31f1aSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
184838e31f1aSVille Syrjälä 		return;
184938e31f1aSVille Syrjälä 
185036d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
185138e31f1aSVille Syrjälä 
18527815ed88SVille Syrjälä 	intel_de_rmw(i915, DPLL_CTRL2,
18537815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_OFF(port) |
18547815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_SEL_MASK(port),
18557815ed88SVille Syrjälä 		     DPLL_CTRL2_DDI_CLK_SEL(pll->info->id, port) |
185638e31f1aSVille Syrjälä 		     DPLL_CTRL2_DDI_SEL_OVERRIDE(port));
185738e31f1aSVille Syrjälä 
185836d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
185938e31f1aSVille Syrjälä }
186038e31f1aSVille Syrjälä 
186138e31f1aSVille Syrjälä static void skl_ddi_disable_clock(struct intel_encoder *encoder)
186238e31f1aSVille Syrjälä {
186338e31f1aSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
186438e31f1aSVille Syrjälä 	enum port port = encoder->port;
186538e31f1aSVille Syrjälä 
186636d225f3SJani Nikula 	mutex_lock(&i915->display.dpll.lock);
1867be317ca0SVille Syrjälä 
18687815ed88SVille Syrjälä 	intel_de_rmw(i915, DPLL_CTRL2,
18697815ed88SVille Syrjälä 		     0, DPLL_CTRL2_DDI_CLK_OFF(port));
1870be317ca0SVille Syrjälä 
187136d225f3SJani Nikula 	mutex_unlock(&i915->display.dpll.lock);
187238e31f1aSVille Syrjälä }
187338e31f1aSVille Syrjälä 
18740fbd8694SVille Syrjälä static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder)
18750fbd8694SVille Syrjälä {
18760fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
18770fbd8694SVille Syrjälä 	enum port port = encoder->port;
18780fbd8694SVille Syrjälä 
18790fbd8694SVille Syrjälä 	/*
18800fbd8694SVille Syrjälä 	 * FIXME Not sure if the override affects both
18810fbd8694SVille Syrjälä 	 * the PLL selection and the CLK_OFF bit.
18820fbd8694SVille Syrjälä 	 */
18830fbd8694SVille Syrjälä 	return !(intel_de_read(i915, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port));
18840fbd8694SVille Syrjälä }
18850fbd8694SVille Syrjälä 
1886351221ffSVille Syrjälä static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
1887351221ffSVille Syrjälä {
1888351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1889351221ffSVille Syrjälä 	enum port port = encoder->port;
1890351221ffSVille Syrjälä 	enum intel_dpll_id id;
1891351221ffSVille Syrjälä 	u32 tmp;
1892351221ffSVille Syrjälä 
1893351221ffSVille Syrjälä 	tmp = intel_de_read(i915, DPLL_CTRL2);
1894351221ffSVille Syrjälä 
1895351221ffSVille Syrjälä 	/*
1896351221ffSVille Syrjälä 	 * FIXME Not sure if the override affects both
1897351221ffSVille Syrjälä 	 * the PLL selection and the CLK_OFF bit.
1898351221ffSVille Syrjälä 	 */
1899351221ffSVille Syrjälä 	if ((tmp & DPLL_CTRL2_DDI_SEL_OVERRIDE(port)) == 0)
1900351221ffSVille Syrjälä 		return NULL;
1901351221ffSVille Syrjälä 
1902351221ffSVille Syrjälä 	id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >>
1903351221ffSVille Syrjälä 		DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port);
1904351221ffSVille Syrjälä 
1905351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1906351221ffSVille Syrjälä }
1907351221ffSVille Syrjälä 
1908d135368dSVille Syrjälä void hsw_ddi_enable_clock(struct intel_encoder *encoder,
1909d135368dSVille Syrjälä 			  const struct intel_crtc_state *crtc_state)
1910d135368dSVille Syrjälä {
1911d135368dSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1912d135368dSVille Syrjälä 	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
1913d135368dSVille Syrjälä 	enum port port = encoder->port;
1914d135368dSVille Syrjälä 
1915d135368dSVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
1916d135368dSVille Syrjälä 		return;
1917d135368dSVille Syrjälä 
1918d135368dSVille Syrjälä 	intel_de_write(i915, PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll));
1919d135368dSVille Syrjälä }
1920d135368dSVille Syrjälä 
1921d135368dSVille Syrjälä void hsw_ddi_disable_clock(struct intel_encoder *encoder)
1922d135368dSVille Syrjälä {
1923d135368dSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1924d135368dSVille Syrjälä 	enum port port = encoder->port;
1925d135368dSVille Syrjälä 
1926d135368dSVille Syrjälä 	intel_de_write(i915, PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
1927d135368dSVille Syrjälä }
1928d135368dSVille Syrjälä 
19290fbd8694SVille Syrjälä bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder)
19300fbd8694SVille Syrjälä {
19310fbd8694SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19320fbd8694SVille Syrjälä 	enum port port = encoder->port;
19330fbd8694SVille Syrjälä 
19340fbd8694SVille Syrjälä 	return intel_de_read(i915, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE;
19350fbd8694SVille Syrjälä }
19360fbd8694SVille Syrjälä 
1937351221ffSVille Syrjälä static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
1938351221ffSVille Syrjälä {
1939351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1940351221ffSVille Syrjälä 	enum port port = encoder->port;
1941351221ffSVille Syrjälä 	enum intel_dpll_id id;
1942351221ffSVille Syrjälä 	u32 tmp;
1943351221ffSVille Syrjälä 
1944351221ffSVille Syrjälä 	tmp = intel_de_read(i915, PORT_CLK_SEL(port));
1945351221ffSVille Syrjälä 
1946351221ffSVille Syrjälä 	switch (tmp & PORT_CLK_SEL_MASK) {
1947351221ffSVille Syrjälä 	case PORT_CLK_SEL_WRPLL1:
1948351221ffSVille Syrjälä 		id = DPLL_ID_WRPLL1;
1949351221ffSVille Syrjälä 		break;
1950351221ffSVille Syrjälä 	case PORT_CLK_SEL_WRPLL2:
1951351221ffSVille Syrjälä 		id = DPLL_ID_WRPLL2;
1952351221ffSVille Syrjälä 		break;
1953351221ffSVille Syrjälä 	case PORT_CLK_SEL_SPLL:
1954351221ffSVille Syrjälä 		id = DPLL_ID_SPLL;
1955351221ffSVille Syrjälä 		break;
1956351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_810:
1957351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_810;
1958351221ffSVille Syrjälä 		break;
1959351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_1350:
1960351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_1350;
1961351221ffSVille Syrjälä 		break;
1962351221ffSVille Syrjälä 	case PORT_CLK_SEL_LCPLL_2700:
1963351221ffSVille Syrjälä 		id = DPLL_ID_LCPLL_2700;
1964351221ffSVille Syrjälä 		break;
1965351221ffSVille Syrjälä 	default:
1966351221ffSVille Syrjälä 		MISSING_CASE(tmp);
1967351221ffSVille Syrjälä 		fallthrough;
1968351221ffSVille Syrjälä 	case PORT_CLK_SEL_NONE:
1969351221ffSVille Syrjälä 		return NULL;
1970351221ffSVille Syrjälä 	}
1971351221ffSVille Syrjälä 
1972351221ffSVille Syrjälä 	return intel_get_shared_dpll_by_id(i915, id);
1973351221ffSVille Syrjälä }
1974351221ffSVille Syrjälä 
1975c133df69SVille Syrjälä void intel_ddi_enable_clock(struct intel_encoder *encoder,
1976c133df69SVille Syrjälä 			    const struct intel_crtc_state *crtc_state)
1977c133df69SVille Syrjälä {
1978c133df69SVille Syrjälä 	if (encoder->enable_clock)
1979c133df69SVille Syrjälä 		encoder->enable_clock(encoder, crtc_state);
1980c133df69SVille Syrjälä }
1981c133df69SVille Syrjälä 
1982d39ef5d5SVille Syrjälä void intel_ddi_disable_clock(struct intel_encoder *encoder)
1983c133df69SVille Syrjälä {
1984c133df69SVille Syrjälä 	if (encoder->disable_clock)
1985c133df69SVille Syrjälä 		encoder->disable_clock(encoder);
1986c133df69SVille Syrjälä }
1987c133df69SVille Syrjälä 
1988aaca50efSVille Syrjälä void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
1989dc1ddac6SVille Syrjälä {
199097a24a70SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1991dc1ddac6SVille Syrjälä 	u32 port_mask;
1992dc1ddac6SVille Syrjälä 	bool ddi_clk_needed;
1993dc1ddac6SVille Syrjälä 
1994dc1ddac6SVille Syrjälä 	/*
1995dc1ddac6SVille Syrjälä 	 * In case of DP MST, we sanitize the primary encoder only, not the
1996dc1ddac6SVille Syrjälä 	 * virtual ones.
1997dc1ddac6SVille Syrjälä 	 */
1998dc1ddac6SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_DP_MST)
1999dc1ddac6SVille Syrjälä 		return;
2000dc1ddac6SVille Syrjälä 
2001dc1ddac6SVille Syrjälä 	if (!encoder->base.crtc && intel_encoder_is_dp(encoder)) {
2002dc1ddac6SVille Syrjälä 		u8 pipe_mask;
2003dc1ddac6SVille Syrjälä 		bool is_mst;
2004dc1ddac6SVille Syrjälä 
2005dc1ddac6SVille Syrjälä 		intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
2006dc1ddac6SVille Syrjälä 		/*
2007dc1ddac6SVille Syrjälä 		 * In the unlikely case that BIOS enables DP in MST mode, just
2008dc1ddac6SVille Syrjälä 		 * warn since our MST HW readout is incomplete.
2009dc1ddac6SVille Syrjälä 		 */
201097a24a70SVille Syrjälä 		if (drm_WARN_ON(&i915->drm, is_mst))
2011dc1ddac6SVille Syrjälä 			return;
2012dc1ddac6SVille Syrjälä 	}
2013dc1ddac6SVille Syrjälä 
2014dc1ddac6SVille Syrjälä 	port_mask = BIT(encoder->port);
2015dc1ddac6SVille Syrjälä 	ddi_clk_needed = encoder->base.crtc;
2016dc1ddac6SVille Syrjälä 
2017dc1ddac6SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_DSI) {
2018dc1ddac6SVille Syrjälä 		struct intel_encoder *other_encoder;
2019dc1ddac6SVille Syrjälä 
2020dc1ddac6SVille Syrjälä 		port_mask = intel_dsi_encoder_ports(encoder);
2021dc1ddac6SVille Syrjälä 		/*
2022dc1ddac6SVille Syrjälä 		 * Sanity check that we haven't incorrectly registered another
2023dc1ddac6SVille Syrjälä 		 * encoder using any of the ports of this DSI encoder.
2024dc1ddac6SVille Syrjälä 		 */
202597a24a70SVille Syrjälä 		for_each_intel_encoder(&i915->drm, other_encoder) {
2026dc1ddac6SVille Syrjälä 			if (other_encoder == encoder)
2027dc1ddac6SVille Syrjälä 				continue;
2028dc1ddac6SVille Syrjälä 
202997a24a70SVille Syrjälä 			if (drm_WARN_ON(&i915->drm,
2030dc1ddac6SVille Syrjälä 					port_mask & BIT(other_encoder->port)))
2031dc1ddac6SVille Syrjälä 				return;
2032dc1ddac6SVille Syrjälä 		}
2033dc1ddac6SVille Syrjälä 		/*
2034dc1ddac6SVille Syrjälä 		 * For DSI we keep the ddi clocks gated
2035dc1ddac6SVille Syrjälä 		 * except during enable/disable sequence.
2036dc1ddac6SVille Syrjälä 		 */
2037dc1ddac6SVille Syrjälä 		ddi_clk_needed = false;
2038dc1ddac6SVille Syrjälä 	}
2039dc1ddac6SVille Syrjälä 
2040f82f2563SMatt Roper 	if (ddi_clk_needed || !encoder->is_clock_enabled ||
20410fbd8694SVille Syrjälä 	    !encoder->is_clock_enabled(encoder))
20420fbd8694SVille Syrjälä 		return;
20430fbd8694SVille Syrjälä 
20440fbd8694SVille Syrjälä 	drm_notice(&i915->drm,
20450fbd8694SVille Syrjälä 		   "[ENCODER:%d:%s] is disabled/in DSI mode with an ungated DDI clock, gate it\n",
20460fbd8694SVille Syrjälä 		   encoder->base.base.id, encoder->base.name);
20470fbd8694SVille Syrjälä 
2048dc1ddac6SVille Syrjälä 	encoder->disable_clock(encoder);
2049dc1ddac6SVille Syrjälä }
2050dc1ddac6SVille Syrjälä 
20518aaf5cbdSJosé Roberto de Souza static void
20527801f3b7SLucas De Marchi icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
20533b51be4eSClinton A Taylor 		       const struct intel_crtc_state *crtc_state)
2054379bc100SJani Nikula {
20557801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
20567801f3b7SLucas De Marchi 	enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
20575b6a9ba9SVille Syrjälä 	enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port);
20583b51be4eSClinton A Taylor 	u32 ln0, ln1, pin_assignment;
20593b51be4eSClinton A Taylor 	u8 width;
2060379bc100SJani Nikula 
20615b6a9ba9SVille Syrjälä 	if (!intel_phy_is_tc(dev_priv, phy) ||
206211a89708SImre Deak 	    intel_tc_port_in_tbt_alt_mode(dig_port))
2063379bc100SJani Nikula 		return;
2064379bc100SJani Nikula 
2065005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2066b8ed5533SImre Deak 		ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0));
2067b8ed5533SImre Deak 		ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1));
2068978c3e53SClinton A Taylor 	} else {
2069f7960e7fSJani Nikula 		ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port));
2070f7960e7fSJani Nikula 		ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
2071978c3e53SClinton A Taylor 	}
2072379bc100SJani Nikula 
20734f72a8eeSKhaled Almahallawy 	ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2074379bc100SJani Nikula 	ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2075379bc100SJani Nikula 
20763b51be4eSClinton A Taylor 	/* DPPATC */
20777801f3b7SLucas De Marchi 	pin_assignment = intel_tc_port_get_pin_assignment_mask(dig_port);
20783b51be4eSClinton A Taylor 	width = crtc_state->lane_count;
2079379bc100SJani Nikula 
20803b51be4eSClinton A Taylor 	switch (pin_assignment) {
20813b51be4eSClinton A Taylor 	case 0x0:
20821de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm,
208311a89708SImre Deak 			    !intel_tc_port_in_legacy_mode(dig_port));
20843b51be4eSClinton A Taylor 		if (width == 1) {
2085379bc100SJani Nikula 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
20863b51be4eSClinton A Taylor 		} else {
20873b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
20883b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
2089379bc100SJani Nikula 		}
2090379bc100SJani Nikula 		break;
20913b51be4eSClinton A Taylor 	case 0x1:
20923b51be4eSClinton A Taylor 		if (width == 4) {
20933b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
20943b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
20953b51be4eSClinton A Taylor 		}
2096379bc100SJani Nikula 		break;
20973b51be4eSClinton A Taylor 	case 0x2:
20983b51be4eSClinton A Taylor 		if (width == 2) {
20993b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21003b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21013b51be4eSClinton A Taylor 		}
21023b51be4eSClinton A Taylor 		break;
21033b51be4eSClinton A Taylor 	case 0x3:
21043b51be4eSClinton A Taylor 	case 0x5:
21053b51be4eSClinton A Taylor 		if (width == 1) {
21063b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21073b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21083b51be4eSClinton A Taylor 		} else {
21093b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21103b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21113b51be4eSClinton A Taylor 		}
21123b51be4eSClinton A Taylor 		break;
21133b51be4eSClinton A Taylor 	case 0x4:
21143b51be4eSClinton A Taylor 	case 0x6:
21153b51be4eSClinton A Taylor 		if (width == 1) {
21163b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21173b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21183b51be4eSClinton A Taylor 		} else {
21193b51be4eSClinton A Taylor 			ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21203b51be4eSClinton A Taylor 			ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21213b51be4eSClinton A Taylor 		}
21223b51be4eSClinton A Taylor 		break;
2123379bc100SJani Nikula 	default:
21243b51be4eSClinton A Taylor 		MISSING_CASE(pin_assignment);
2125379bc100SJani Nikula 	}
2126379bc100SJani Nikula 
2127005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2128b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0);
2129b8ed5533SImre Deak 		intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1);
2130978c3e53SClinton A Taylor 	} else {
2131f7960e7fSJani Nikula 		intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0);
2132f7960e7fSJani Nikula 		intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1);
2133379bc100SJani Nikula 	}
2134978c3e53SClinton A Taylor }
2135379bc100SJani Nikula 
2136ef79fafeSVille Syrjälä static enum transcoder
2137ef79fafeSVille Syrjälä tgl_dp_tp_transcoder(const struct intel_crtc_state *crtc_state)
2138ef79fafeSVille Syrjälä {
2139ef79fafeSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
2140ef79fafeSVille Syrjälä 		return crtc_state->mst_master_transcoder;
2141ef79fafeSVille Syrjälä 	else
2142ef79fafeSVille Syrjälä 		return crtc_state->cpu_transcoder;
2143ef79fafeSVille Syrjälä }
2144ef79fafeSVille Syrjälä 
2145ef79fafeSVille Syrjälä i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
2146ef79fafeSVille Syrjälä 			 const struct intel_crtc_state *crtc_state)
2147ef79fafeSVille Syrjälä {
2148ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2149ef79fafeSVille Syrjälä 
2150005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
2151ef79fafeSVille Syrjälä 		return TGL_DP_TP_CTL(tgl_dp_tp_transcoder(crtc_state));
2152ef79fafeSVille Syrjälä 	else
2153ef79fafeSVille Syrjälä 		return DP_TP_CTL(encoder->port);
2154ef79fafeSVille Syrjälä }
2155ef79fafeSVille Syrjälä 
2156ef79fafeSVille Syrjälä i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
2157ef79fafeSVille Syrjälä 			    const struct intel_crtc_state *crtc_state)
2158ef79fafeSVille Syrjälä {
2159ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2160ef79fafeSVille Syrjälä 
2161005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
2162ef79fafeSVille Syrjälä 		return TGL_DP_TP_STATUS(tgl_dp_tp_transcoder(crtc_state));
2163ef79fafeSVille Syrjälä 	else
2164ef79fafeSVille Syrjälä 		return DP_TP_STATUS(encoder->port);
2165ef79fafeSVille Syrjälä }
2166ef79fafeSVille Syrjälä 
21671639406aSManasi Navare static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
21681639406aSManasi Navare 							  const struct intel_crtc_state *crtc_state,
21691639406aSManasi Navare 							  bool enable)
21701639406aSManasi Navare {
21711639406aSManasi Navare 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
21721639406aSManasi Navare 
21731639406aSManasi Navare 	if (!crtc_state->vrr.enable)
21741639406aSManasi Navare 		return;
21751639406aSManasi Navare 
21761639406aSManasi Navare 	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL,
21771639406aSManasi Navare 			       enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
21781639406aSManasi Navare 		drm_dbg_kms(&i915->drm,
21790868b1ceSVille Syrjälä 			    "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
2180707c3a7dSLucas De Marchi 			    str_enable_disable(enable));
21811639406aSManasi Navare }
21821639406aSManasi Navare 
2183379bc100SJani Nikula static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
2184379bc100SJani Nikula 					const struct intel_crtc_state *crtc_state)
2185379bc100SJani Nikula {
218647bdb1caSJani Nikula 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
218747bdb1caSJani Nikula 
2188379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2189379bc100SJani Nikula 		return;
2190379bc100SJani Nikula 
2191379bc100SJani Nikula 	if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION, DP_FEC_READY) <= 0)
219247bdb1caSJani Nikula 		drm_dbg_kms(&i915->drm,
219347bdb1caSJani Nikula 			    "Failed to set FEC_READY in the sink\n");
2194379bc100SJani Nikula }
2195379bc100SJani Nikula 
2196379bc100SJani Nikula static void intel_ddi_enable_fec(struct intel_encoder *encoder,
2197379bc100SJani Nikula 				 const struct intel_crtc_state *crtc_state)
2198379bc100SJani Nikula {
2199379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
22004444df6eSLucas De Marchi 	struct intel_dp *intel_dp;
2201379bc100SJani Nikula 
2202379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2203379bc100SJani Nikula 		return;
2204379bc100SJani Nikula 
2205b7d02c3aSVille Syrjälä 	intel_dp = enc_to_intel_dp(encoder);
22068910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
22078910d8b7SAndrzej Hajda 		     0, DP_TP_CTL_FEC_ENABLE);
2208379bc100SJani Nikula }
2209379bc100SJani Nikula 
2210379bc100SJani Nikula static void intel_ddi_disable_fec_state(struct intel_encoder *encoder,
2211379bc100SJani Nikula 					const struct intel_crtc_state *crtc_state)
2212379bc100SJani Nikula {
2213379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
22144444df6eSLucas De Marchi 	struct intel_dp *intel_dp;
2215379bc100SJani Nikula 
2216379bc100SJani Nikula 	if (!crtc_state->fec_enable)
2217379bc100SJani Nikula 		return;
2218379bc100SJani Nikula 
2219b7d02c3aSVille Syrjälä 	intel_dp = enc_to_intel_dp(encoder);
22208910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
22218910d8b7SAndrzej Hajda 		     DP_TP_CTL_FEC_ENABLE, 0);
2222ef79fafeSVille Syrjälä 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
2223379bc100SJani Nikula }
2224379bc100SJani Nikula 
22255cdf706fSVille Syrjälä static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
22265cdf706fSVille Syrjälä 				     const struct intel_crtc_state *crtc_state)
22275cdf706fSVille Syrjälä {
22285cdf706fSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
22295cdf706fSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
22305cdf706fSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
22315cdf706fSVille Syrjälä 
22325cdf706fSVille Syrjälä 	if (intel_phy_is_combo(i915, phy)) {
22335cdf706fSVille Syrjälä 		bool lane_reversal =
22345cdf706fSVille Syrjälä 			dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
22355cdf706fSVille Syrjälä 
22365cdf706fSVille Syrjälä 		intel_combo_phy_power_up_lanes(i915, phy, false,
22375cdf706fSVille Syrjälä 					       crtc_state->lane_count,
22385cdf706fSVille Syrjälä 					       lane_reversal);
22395cdf706fSVille Syrjälä 	}
22405cdf706fSVille Syrjälä }
22415cdf706fSVille Syrjälä 
2242f6864b27SJani Nikula /* Splitter enable for eDP MSO is limited to certain pipes. */
2243f6864b27SJani Nikula static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915)
2244f6864b27SJani Nikula {
2245f6864b27SJani Nikula 	if (IS_ALDERLAKE_P(i915))
2246f6864b27SJani Nikula 		return BIT(PIPE_A) | BIT(PIPE_B);
2247f6864b27SJani Nikula 	else
2248f6864b27SJani Nikula 		return BIT(PIPE_A);
2249f6864b27SJani Nikula }
2250f6864b27SJani Nikula 
22515b616a29SJani Nikula static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
22525b616a29SJani Nikula 				     struct intel_crtc_state *pipe_config)
22535b616a29SJani Nikula {
22545b616a29SJani Nikula 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
22555b616a29SJani Nikula 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
22565b616a29SJani Nikula 	enum pipe pipe = crtc->pipe;
22575b616a29SJani Nikula 	u32 dss1;
22585b616a29SJani Nikula 
22595b616a29SJani Nikula 	if (!HAS_MSO(i915))
22605b616a29SJani Nikula 		return;
22615b616a29SJani Nikula 
22625b616a29SJani Nikula 	dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe));
22635b616a29SJani Nikula 
22645b616a29SJani Nikula 	pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE;
22655b616a29SJani Nikula 	if (!pipe_config->splitter.enable)
22665b616a29SJani Nikula 		return;
22675b616a29SJani Nikula 
2268f6864b27SJani Nikula 	if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) {
22695b616a29SJani Nikula 		pipe_config->splitter.enable = false;
22705b616a29SJani Nikula 		return;
22715b616a29SJani Nikula 	}
22725b616a29SJani Nikula 
22735b616a29SJani Nikula 	switch (dss1 & SPLITTER_CONFIGURATION_MASK) {
22745b616a29SJani Nikula 	default:
22755b616a29SJani Nikula 		drm_WARN(&i915->drm, true,
22765b616a29SJani Nikula 			 "Invalid splitter configuration, dss1=0x%08x\n", dss1);
22775b616a29SJani Nikula 		fallthrough;
22785b616a29SJani Nikula 	case SPLITTER_CONFIGURATION_2_SEGMENT:
22795b616a29SJani Nikula 		pipe_config->splitter.link_count = 2;
22805b616a29SJani Nikula 		break;
22815b616a29SJani Nikula 	case SPLITTER_CONFIGURATION_4_SEGMENT:
22825b616a29SJani Nikula 		pipe_config->splitter.link_count = 4;
22835b616a29SJani Nikula 		break;
22845b616a29SJani Nikula 	}
22855b616a29SJani Nikula 
22865b616a29SJani Nikula 	pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1);
22875b616a29SJani Nikula }
22885b616a29SJani Nikula 
2289bc71194eSJani Nikula static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
2290bc71194eSJani Nikula {
2291bc71194eSJani Nikula 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2292bc71194eSJani Nikula 	struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2293bc71194eSJani Nikula 	enum pipe pipe = crtc->pipe;
2294bc71194eSJani Nikula 	u32 dss1 = 0;
2295bc71194eSJani Nikula 
2296bc71194eSJani Nikula 	if (!HAS_MSO(i915))
2297bc71194eSJani Nikula 		return;
2298bc71194eSJani Nikula 
2299bc71194eSJani Nikula 	if (crtc_state->splitter.enable) {
2300bc71194eSJani Nikula 		dss1 |= SPLITTER_ENABLE;
2301bc71194eSJani Nikula 		dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
2302bc71194eSJani Nikula 		if (crtc_state->splitter.link_count == 2)
2303bc71194eSJani Nikula 			dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT;
2304bc71194eSJani Nikula 		else
2305bc71194eSJani Nikula 			dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT;
2306bc71194eSJani Nikula 	}
2307bc71194eSJani Nikula 
2308bc71194eSJani Nikula 	intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe),
2309bc71194eSJani Nikula 		     SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK |
2310bc71194eSJani Nikula 		     OVERLAP_PIXELS_MASK, dss1);
2311bc71194eSJani Nikula }
2312bc71194eSJani Nikula 
2313ede9771dSVille Syrjälä static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
2314ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
231599389390SJosé Roberto de Souza 				  const struct intel_crtc_state *crtc_state,
231699389390SJosé Roberto de Souza 				  const struct drm_connector_state *conn_state)
231799389390SJosé Roberto de Souza {
2318b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
231999389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2320b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
232199389390SJosé Roberto de Souza 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
232299389390SJosé Roberto de Souza 
2323a621860aSVille Syrjälä 	intel_dp_set_link_params(intel_dp,
2324a621860aSVille Syrjälä 				 crtc_state->port_clock,
2325a621860aSVille Syrjälä 				 crtc_state->lane_count);
232699389390SJosé Roberto de Souza 
23275e19c0b0SMatt Roper 	/*
23289f620f1dSVille Syrjälä 	 * We only configure what the register value will be here.  Actual
23299f620f1dSVille Syrjälä 	 * enabling happens during link training farther down.
23309f620f1dSVille Syrjälä 	 */
23319f620f1dSVille Syrjälä 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
23329f620f1dSVille Syrjälä 
23339f620f1dSVille Syrjälä 	/*
23345e19c0b0SMatt Roper 	 * 1. Enable Power Wells
23355e19c0b0SMatt Roper 	 *
23365e19c0b0SMatt Roper 	 * This was handled at the beginning of intel_atomic_commit_tail(),
23375e19c0b0SMatt Roper 	 * before we called down into this function.
23385e19c0b0SMatt Roper 	 */
233999389390SJosé Roberto de Souza 
23405e19c0b0SMatt Roper 	/* 2. Enable Panel Power if PPS is required */
2341eb46f498SJani Nikula 	intel_pps_on(intel_dp);
234299389390SJosé Roberto de Souza 
234399389390SJosé Roberto de Souza 	/*
23445e19c0b0SMatt Roper 	 * 3. For non-TBT Type-C ports, set FIA lane count
23455e19c0b0SMatt Roper 	 * (DFLEXDPSP.DPX4TXLATC)
23465e19c0b0SMatt Roper 	 *
23475e19c0b0SMatt Roper 	 * This was done before tgl_ddi_pre_enable_dp by
23481e98f88cSLucas De Marchi 	 * hsw_crtc_enable()->intel_encoders_pre_pll_enable().
234999389390SJosé Roberto de Souza 	 */
235099389390SJosé Roberto de Souza 
23515e19c0b0SMatt Roper 	/*
23525e19c0b0SMatt Roper 	 * 4. Enable the port PLL.
23535e19c0b0SMatt Roper 	 *
23545e19c0b0SMatt Roper 	 * The PLL enabling itself was already done before this function by
23551e98f88cSLucas De Marchi 	 * hsw_crtc_enable()->intel_enable_shared_dpll().  We need only
23565e19c0b0SMatt Roper 	 * configure the PLL to port mapping here.
23575e19c0b0SMatt Roper 	 */
2358c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
23596171e58bSClinton A Taylor 
23605e19c0b0SMatt Roper 	/* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */
236111a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2362a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2363a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
236499389390SJosé Roberto de Souza 								   dig_port->ddi_io_power_domain);
2365a4550977SImre Deak 	}
236699389390SJosé Roberto de Souza 
23675e19c0b0SMatt Roper 	/* 6. Program DP_MODE */
23683b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
236999389390SJosé Roberto de Souza 
237099389390SJosé Roberto de Souza 	/*
23715e19c0b0SMatt Roper 	 * 7. The rest of the below are substeps under the bspec's "Enable and
23725e19c0b0SMatt Roper 	 * Train Display Port" step.  Note that steps that are specific to
23735e19c0b0SMatt Roper 	 * MST will be handled by intel_mst_pre_enable_dp() before/after it
23745e19c0b0SMatt Roper 	 * calls into this function.  Also intel_mst_pre_enable_dp() only calls
23755e19c0b0SMatt Roper 	 * us when active_mst_links==0, so any steps designated for "single
23765e19c0b0SMatt Roper 	 * stream or multi-stream master transcoder" can just be performed
23775e19c0b0SMatt Roper 	 * unconditionally here.
23785e19c0b0SMatt Roper 	 */
23795e19c0b0SMatt Roper 
23805e19c0b0SMatt Roper 	/*
23815e19c0b0SMatt Roper 	 * 7.a Configure Transcoder Clock Select to direct the Port clock to the
23825e19c0b0SMatt Roper 	 * Transcoder.
238399389390SJosé Roberto de Souza 	 */
238455a4679eSVille Syrjälä 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
238599389390SJosé Roberto de Souza 
2386fe6959a6SVille Syrjälä 	if (HAS_DP20(dev_priv))
2387fe6959a6SVille Syrjälä 		intel_ddi_config_transcoder_dp2(encoder, crtc_state);
2388fe6959a6SVille Syrjälä 
23895e19c0b0SMatt Roper 	/*
23905e19c0b0SMatt Roper 	 * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
23915e19c0b0SMatt Roper 	 * Transport Select
23925e19c0b0SMatt Roper 	 */
2393eed22a46SVille Syrjälä 	intel_ddi_config_transcoder_func(encoder, crtc_state);
239499389390SJosé Roberto de Souza 
23955e19c0b0SMatt Roper 	/*
23965e19c0b0SMatt Roper 	 * 7.c Configure & enable DP_TP_CTL with link training pattern 1
23975e19c0b0SMatt Roper 	 * selected
23985e19c0b0SMatt Roper 	 *
23995e19c0b0SMatt Roper 	 * This will be handled by the intel_dp_start_link_train() farther
24005e19c0b0SMatt Roper 	 * down this function.
24015e19c0b0SMatt Roper 	 */
24025e19c0b0SMatt Roper 
24035e19c0b0SMatt Roper 	/* 7.e Configure voltage swing and related IO settings */
2404e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
240599389390SJosé Roberto de Souza 
24065e19c0b0SMatt Roper 	/*
24075e19c0b0SMatt Roper 	 * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up
24085e19c0b0SMatt Roper 	 * the used lanes of the DDI.
24095e19c0b0SMatt Roper 	 */
24105cdf706fSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
241199389390SJosé Roberto de Souza 
24125e19c0b0SMatt Roper 	/*
2413bc71194eSJani Nikula 	 * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected.
2414bc71194eSJani Nikula 	 */
2415bc71194eSJani Nikula 	intel_ddi_mso_configure(crtc_state);
2416bc71194eSJani Nikula 
241799389390SJosé Roberto de Souza 	if (!is_mst)
24180e634efdSVille Syrjälä 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
241999389390SJosé Roberto de Souza 
2420522508b6SAnkit Nautiyal 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
242199389390SJosé Roberto de Souza 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state, true);
242299389390SJosé Roberto de Souza 	/*
242399389390SJosé Roberto de Souza 	 * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
242499389390SJosé Roberto de Souza 	 * in the FEC_CONFIGURATION register to 1 before initiating link
242599389390SJosé Roberto de Souza 	 * training
242699389390SJosé Roberto de Souza 	 */
242799389390SJosé Roberto de Souza 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
24285e19c0b0SMatt Roper 
24294f3dd47aSAnkit Nautiyal 	intel_dp_check_frl_training(intel_dp);
243010fec80bSAnkit Nautiyal 	intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
24314f3dd47aSAnkit Nautiyal 
24325e19c0b0SMatt Roper 	/*
24335e19c0b0SMatt Roper 	 * 7.i Follow DisplayPort specification training sequence (see notes for
24345e19c0b0SMatt Roper 	 *     failure handling)
24355e19c0b0SMatt Roper 	 * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
24365e19c0b0SMatt Roper 	 *     Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
24375e19c0b0SMatt Roper 	 *     (timeout after 800 us)
24385e19c0b0SMatt Roper 	 */
2439a621860aSVille Syrjälä 	intel_dp_start_link_train(intel_dp, crtc_state);
244099389390SJosé Roberto de Souza 
24415e19c0b0SMatt Roper 	/* 7.k Set DP_TP_CTL link training to Normal */
2442eadf6f91SManasi Navare 	if (!is_trans_port_sync_mode(crtc_state))
2443a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
244499389390SJosé Roberto de Souza 
24455e19c0b0SMatt Roper 	/* 7.l Configure and enable FEC if needed */
244699389390SJosé Roberto de Souza 	intel_ddi_enable_fec(encoder, crtc_state);
24473126977dSVille Syrjälä 
24483126977dSVille Syrjälä 	intel_dsc_dp_pps_write(encoder, crtc_state);
244999389390SJosé Roberto de Souza }
245099389390SJosé Roberto de Souza 
2451ede9771dSVille Syrjälä static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
2452ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
2453379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state,
2454379bc100SJani Nikula 				  const struct drm_connector_state *conn_state)
2455379bc100SJani Nikula {
2456b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2457379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2458379bc100SJani Nikula 	enum port port = encoder->port;
2459b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2460379bc100SJani Nikula 	bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
2461379bc100SJani Nikula 
2462005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) < 11)
24631de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm,
24641de143ccSPankaj Bharadiya 			    is_mst && (port == PORT_A || port == PORT_E));
2465542dfab5SJosé Roberto de Souza 	else
24661de143ccSPankaj Bharadiya 		drm_WARN_ON(&dev_priv->drm, is_mst && port == PORT_A);
2467379bc100SJani Nikula 
2468a621860aSVille Syrjälä 	intel_dp_set_link_params(intel_dp,
2469a621860aSVille Syrjälä 				 crtc_state->port_clock,
2470a621860aSVille Syrjälä 				 crtc_state->lane_count);
2471379bc100SJani Nikula 
24729f620f1dSVille Syrjälä 	/*
24739f620f1dSVille Syrjälä 	 * We only configure what the register value will be here.  Actual
24749f620f1dSVille Syrjälä 	 * enabling happens during link training farther down.
24759f620f1dSVille Syrjälä 	 */
24769f620f1dSVille Syrjälä 	intel_ddi_init_dp_buf_reg(encoder, crtc_state);
24779f620f1dSVille Syrjälä 
2478eb46f498SJani Nikula 	intel_pps_on(intel_dp);
2479379bc100SJani Nikula 
2480c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
2481379bc100SJani Nikula 
248211a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2483a4550977SImre Deak 		drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2484a4550977SImre Deak 		dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
24853b2ed431SImre Deak 								   dig_port->ddi_io_power_domain);
2486a4550977SImre Deak 	}
2487379bc100SJani Nikula 
24883b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
2489379bc100SJani Nikula 
24905bafd85dSVille Syrjälä 	if (has_buf_trans_select(dev_priv))
2491266152aeSVille Syrjälä 		hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
2492379bc100SJani Nikula 
2493e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
2494e722ab8bSVille Syrjälä 
24955cdf706fSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
2496379bc100SJani Nikula 
2497379bc100SJani Nikula 	if (!is_mst)
24980e634efdSVille Syrjälä 		intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
2499522508b6SAnkit Nautiyal 	intel_dp_configure_protocol_converter(intel_dp, crtc_state);
2500379bc100SJani Nikula 	intel_dp_sink_set_decompression_state(intel_dp, crtc_state,
2501379bc100SJani Nikula 					      true);
2502379bc100SJani Nikula 	intel_dp_sink_set_fec_ready(intel_dp, crtc_state);
2503a621860aSVille Syrjälä 	intel_dp_start_link_train(intel_dp, crtc_state);
2504005e9537SMatt Roper 	if ((port != PORT_A || DISPLAY_VER(dev_priv) >= 9) &&
2505eadf6f91SManasi Navare 	    !is_trans_port_sync_mode(crtc_state))
2506a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
2507379bc100SJani Nikula 
2508379bc100SJani Nikula 	intel_ddi_enable_fec(encoder, crtc_state);
2509379bc100SJani Nikula 
2510379bc100SJani Nikula 	if (!is_mst)
251155a4679eSVille Syrjälä 		intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2512379bc100SJani Nikula 
25133126977dSVille Syrjälä 	intel_dsc_dp_pps_write(encoder, crtc_state);
2514379bc100SJani Nikula }
2515379bc100SJani Nikula 
2516ede9771dSVille Syrjälä static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
2517ede9771dSVille Syrjälä 				    struct intel_encoder *encoder,
251899389390SJosé Roberto de Souza 				    const struct intel_crtc_state *crtc_state,
251999389390SJosé Roberto de Souza 				    const struct drm_connector_state *conn_state)
252099389390SJosé Roberto de Souza {
252199389390SJosé Roberto de Souza 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
252299389390SJosé Roberto de Souza 
2523fe6959a6SVille Syrjälä 	if (DISPLAY_VER(dev_priv) >= 12)
2524ede9771dSVille Syrjälä 		tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
252599389390SJosé Roberto de Souza 	else
2526ede9771dSVille Syrjälä 		hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
25270c06fa15SGwan-gyeong Mun 
2528bd8c9ccaSGwan-gyeong Mun 	/* MST will call a setting of MSA after an allocating of Virtual Channel
2529bd8c9ccaSGwan-gyeong Mun 	 * from MST encoder pre_enable callback.
2530bd8c9ccaSGwan-gyeong Mun 	 */
25318de5df3bSVille Syrjälä 	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
25320c06fa15SGwan-gyeong Mun 		intel_ddi_set_dp_msa(crtc_state, conn_state);
25331fc1e8d4SJosé Roberto de Souza }
253499389390SJosé Roberto de Souza 
2535ede9771dSVille Syrjälä static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
2536ede9771dSVille Syrjälä 				      struct intel_encoder *encoder,
2537379bc100SJani Nikula 				      const struct intel_crtc_state *crtc_state,
2538379bc100SJani Nikula 				      const struct drm_connector_state *conn_state)
2539379bc100SJani Nikula {
25400ba7ffeaSLucas De Marchi 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
25410ba7ffeaSLucas De Marchi 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
2542379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2543379bc100SJani Nikula 
2544379bc100SJani Nikula 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
2545c133df69SVille Syrjälä 	intel_ddi_enable_clock(encoder, crtc_state);
2546379bc100SJani Nikula 
2547a4550977SImre Deak 	drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2548a4550977SImre Deak 	dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
2549a4550977SImre Deak 							   dig_port->ddi_io_power_domain);
2550379bc100SJani Nikula 
25513b51be4eSClinton A Taylor 	icl_program_mg_dp_mode(dig_port, crtc_state);
2552379bc100SJani Nikula 
255355a4679eSVille Syrjälä 	intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2554379bc100SJani Nikula 
25550ba7ffeaSLucas De Marchi 	dig_port->set_infoframes(encoder,
2556379bc100SJani Nikula 				 crtc_state->has_infoframe,
2557379bc100SJani Nikula 				 crtc_state, conn_state);
2558379bc100SJani Nikula }
2559379bc100SJani Nikula 
2560ede9771dSVille Syrjälä static void intel_ddi_pre_enable(struct intel_atomic_state *state,
2561ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
2562379bc100SJani Nikula 				 const struct intel_crtc_state *crtc_state,
2563379bc100SJani Nikula 				 const struct drm_connector_state *conn_state)
2564379bc100SJani Nikula {
25652225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2566379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2567379bc100SJani Nikula 	enum pipe pipe = crtc->pipe;
2568379bc100SJani Nikula 
2569379bc100SJani Nikula 	/*
2570379bc100SJani Nikula 	 * When called from DP MST code:
2571379bc100SJani Nikula 	 * - conn_state will be NULL
2572379bc100SJani Nikula 	 * - encoder will be the main encoder (ie. mst->primary)
2573379bc100SJani Nikula 	 * - the main connector associated with this port
2574379bc100SJani Nikula 	 *   won't be active or linked to a crtc
2575379bc100SJani Nikula 	 * - crtc_state will be the state of the first stream to
2576379bc100SJani Nikula 	 *   be activated on this port, and it may not be the same
2577379bc100SJani Nikula 	 *   stream that will be deactivated last, but each stream
2578379bc100SJani Nikula 	 *   should have a state that is identical when it comes to
2579379bc100SJani Nikula 	 *   the DP link parameteres
2580379bc100SJani Nikula 	 */
2581379bc100SJani Nikula 
25821de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
2583379bc100SJani Nikula 
2584379bc100SJani Nikula 	intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
2585379bc100SJani Nikula 
2586379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
2587ede9771dSVille Syrjälä 		intel_ddi_pre_enable_hdmi(state, encoder, crtc_state,
2588ede9771dSVille Syrjälä 					  conn_state);
2589379bc100SJani Nikula 	} else {
2590f7af425dSVille Syrjälä 		struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2591379bc100SJani Nikula 
2592ede9771dSVille Syrjälä 		intel_ddi_pre_enable_dp(state, encoder, crtc_state,
2593ede9771dSVille Syrjälä 					conn_state);
2594379bc100SJani Nikula 
2595f7af425dSVille Syrjälä 		/* FIXME precompute everything properly */
25960ea02bb8SJosé Roberto de Souza 		/* FIXME how do we turn infoframes off again? */
2597f7af425dSVille Syrjälä 		if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
2598379bc100SJani Nikula 			dig_port->set_infoframes(encoder,
2599379bc100SJani Nikula 						 crtc_state->has_infoframe,
2600379bc100SJani Nikula 						 crtc_state, conn_state);
2601379bc100SJani Nikula 	}
2602379bc100SJani Nikula }
2603379bc100SJani Nikula 
2604379bc100SJani Nikula static void intel_disable_ddi_buf(struct intel_encoder *encoder,
2605379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state)
2606379bc100SJani Nikula {
2607379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2608379bc100SJani Nikula 	enum port port = encoder->port;
2609379bc100SJani Nikula 	bool wait = false;
2610379bc100SJani Nikula 	u32 val;
2611379bc100SJani Nikula 
2612f7960e7fSJani Nikula 	val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
2613379bc100SJani Nikula 	if (val & DDI_BUF_CTL_ENABLE) {
2614379bc100SJani Nikula 		val &= ~DDI_BUF_CTL_ENABLE;
2615f7960e7fSJani Nikula 		intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
2616379bc100SJani Nikula 		wait = true;
2617379bc100SJani Nikula 	}
2618379bc100SJani Nikula 
26198910d8b7SAndrzej Hajda 	if (intel_crtc_has_dp_encoder(crtc_state))
26208910d8b7SAndrzej Hajda 		intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
26218910d8b7SAndrzej Hajda 			     DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK,
26228910d8b7SAndrzej Hajda 			     DP_TP_CTL_LINK_TRAIN_PAT1);
2623379bc100SJani Nikula 
2624379bc100SJani Nikula 	/* Disable FEC in DP Sink */
2625379bc100SJani Nikula 	intel_ddi_disable_fec_state(encoder, crtc_state);
2626379bc100SJani Nikula 
2627379bc100SJani Nikula 	if (wait)
2628379bc100SJani Nikula 		intel_wait_ddi_buf_idle(dev_priv, port);
2629379bc100SJani Nikula }
2630379bc100SJani Nikula 
2631ede9771dSVille Syrjälä static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
2632ede9771dSVille Syrjälä 				      struct intel_encoder *encoder,
2633379bc100SJani Nikula 				      const struct intel_crtc_state *old_crtc_state,
2634379bc100SJani Nikula 				      const struct drm_connector_state *old_conn_state)
2635379bc100SJani Nikula {
2636379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2637b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2638379bc100SJani Nikula 	struct intel_dp *intel_dp = &dig_port->dp;
2639379bc100SJani Nikula 	bool is_mst = intel_crtc_has_type(old_crtc_state,
2640379bc100SJani Nikula 					  INTEL_OUTPUT_DP_MST);
2641379bc100SJani Nikula 
2642c980216dSImre Deak 	if (!is_mst)
2643c980216dSImre Deak 		intel_dp_set_infoframes(encoder, false,
2644c980216dSImre Deak 					old_crtc_state, old_conn_state);
2645fa37a213SGwan-gyeong Mun 
2646379bc100SJani Nikula 	/*
2647379bc100SJani Nikula 	 * Power down sink before disabling the port, otherwise we end
2648379bc100SJani Nikula 	 * up getting interrupts from the sink on detecting link loss.
2649379bc100SJani Nikula 	 */
26500e634efdSVille Syrjälä 	intel_dp_set_power(intel_dp, DP_SET_POWER_D3);
265178eaaba3SJosé Roberto de Souza 
2652005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12) {
2653c59053dcSJosé Roberto de Souza 		if (is_mst) {
2654c59053dcSJosé Roberto de Souza 			enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
2655c59053dcSJosé Roberto de Souza 
26568910d8b7SAndrzej Hajda 			intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder),
26578910d8b7SAndrzej Hajda 				     TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK,
26588910d8b7SAndrzej Hajda 				     0);
2659c59053dcSJosé Roberto de Souza 		}
2660c59053dcSJosé Roberto de Souza 	} else {
2661c59053dcSJosé Roberto de Souza 		if (!is_mst)
266255a4679eSVille Syrjälä 			intel_ddi_disable_transcoder_clock(old_crtc_state);
2663c59053dcSJosé Roberto de Souza 	}
2664379bc100SJani Nikula 
2665379bc100SJani Nikula 	intel_disable_ddi_buf(encoder, old_crtc_state);
2666379bc100SJani Nikula 
26673ca8f191SJosé Roberto de Souza 	/*
26683ca8f191SJosé Roberto de Souza 	 * From TGL spec: "If single stream or multi-stream master transcoder:
26693ca8f191SJosé Roberto de Souza 	 * Configure Transcoder Clock select to direct no clock to the
26703ca8f191SJosé Roberto de Souza 	 * transcoder"
26713ca8f191SJosé Roberto de Souza 	 */
2672005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12)
267355a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
26743ca8f191SJosé Roberto de Souza 
2675eb46f498SJani Nikula 	intel_pps_vdd_on(intel_dp);
2676eb46f498SJani Nikula 	intel_pps_off(intel_dp);
2677379bc100SJani Nikula 
267811a89708SImre Deak 	if (!intel_tc_port_in_tbt_alt_mode(dig_port))
2679a4550977SImre Deak 		intel_display_power_put(dev_priv,
2680a4550977SImre Deak 					dig_port->ddi_io_power_domain,
2681a4550977SImre Deak 					fetch_and_zero(&dig_port->ddi_io_wakeref));
2682379bc100SJani Nikula 
2683c133df69SVille Syrjälä 	intel_ddi_disable_clock(encoder);
2684379bc100SJani Nikula }
2685379bc100SJani Nikula 
2686ede9771dSVille Syrjälä static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
2687ede9771dSVille Syrjälä 					struct intel_encoder *encoder,
2688379bc100SJani Nikula 					const struct intel_crtc_state *old_crtc_state,
2689379bc100SJani Nikula 					const struct drm_connector_state *old_conn_state)
2690379bc100SJani Nikula {
2691379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2692b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2693379bc100SJani Nikula 	struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
2694379bc100SJani Nikula 
2695379bc100SJani Nikula 	dig_port->set_infoframes(encoder, false,
2696379bc100SJani Nikula 				 old_crtc_state, old_conn_state);
2697379bc100SJani Nikula 
2698c1949189SImre Deak 	if (DISPLAY_VER(dev_priv) < 12)
269955a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
2700379bc100SJani Nikula 
2701379bc100SJani Nikula 	intel_disable_ddi_buf(encoder, old_crtc_state);
2702379bc100SJani Nikula 
2703c1949189SImre Deak 	if (DISPLAY_VER(dev_priv) >= 12)
270455a4679eSVille Syrjälä 		intel_ddi_disable_transcoder_clock(old_crtc_state);
2705c1949189SImre Deak 
2706a4550977SImre Deak 	intel_display_power_put(dev_priv,
2707a4550977SImre Deak 				dig_port->ddi_io_power_domain,
2708a4550977SImre Deak 				fetch_and_zero(&dig_port->ddi_io_wakeref));
2709379bc100SJani Nikula 
2710c133df69SVille Syrjälä 	intel_ddi_disable_clock(encoder);
2711379bc100SJani Nikula 
2712379bc100SJani Nikula 	intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
2713379bc100SJani Nikula }
2714379bc100SJani Nikula 
2715ede9771dSVille Syrjälä static void intel_ddi_post_disable(struct intel_atomic_state *state,
2716ede9771dSVille Syrjälä 				   struct intel_encoder *encoder,
2717379bc100SJani Nikula 				   const struct intel_crtc_state *old_crtc_state,
2718379bc100SJani Nikula 				   const struct drm_connector_state *old_conn_state)
2719379bc100SJani Nikula {
2720379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2721b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
272217bef9baSVille Syrjälä 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
272317bef9baSVille Syrjälä 	bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
2724a6e7a006SVille Syrjälä 	struct intel_crtc *slave_crtc;
2725379bc100SJani Nikula 
27267829c92bSVille Syrjälä 	if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) {
2727773b4b54SVille Syrjälä 		intel_crtc_vblank_off(old_crtc_state);
2728773b4b54SVille Syrjälä 
2729f0651232SManasi Navare 		intel_vrr_disable(old_crtc_state);
2730f0651232SManasi Navare 
27310504d0acSVille Syrjälä 		intel_disable_transcoder(old_crtc_state);
27320504d0acSVille Syrjälä 
2733773b4b54SVille Syrjälä 		intel_ddi_disable_transcoder_func(old_crtc_state);
2734773b4b54SVille Syrjälä 
2735773b4b54SVille Syrjälä 		intel_dsc_disable(old_crtc_state);
2736773b4b54SVille Syrjälä 
2737005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 9)
2738f6df4d46SLucas De Marchi 			skl_scaler_disable(old_crtc_state);
2739773b4b54SVille Syrjälä 		else
27409eae5e27SLucas De Marchi 			ilk_pfit_disable(old_crtc_state);
27417829c92bSVille Syrjälä 	}
2742773b4b54SVille Syrjälä 
2743a6e7a006SVille Syrjälä 	for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, slave_crtc,
2744a6e7a006SVille Syrjälä 					 intel_crtc_bigjoiner_slave_pipes(old_crtc_state)) {
27454e3cdb45SManasi Navare 		const struct intel_crtc_state *old_slave_crtc_state =
2746f2e19b58SVille Syrjälä 			intel_atomic_get_old_crtc_state(state, slave_crtc);
27474e3cdb45SManasi Navare 
27484e3cdb45SManasi Navare 		intel_crtc_vblank_off(old_slave_crtc_state);
27494e3cdb45SManasi Navare 
27504e3cdb45SManasi Navare 		intel_dsc_disable(old_slave_crtc_state);
27514e3cdb45SManasi Navare 		skl_scaler_disable(old_slave_crtc_state);
27524e3cdb45SManasi Navare 	}
27534e3cdb45SManasi Navare 
2754379bc100SJani Nikula 	/*
2755379bc100SJani Nikula 	 * When called from DP MST code:
2756379bc100SJani Nikula 	 * - old_conn_state will be NULL
2757379bc100SJani Nikula 	 * - encoder will be the main encoder (ie. mst->primary)
2758379bc100SJani Nikula 	 * - the main connector associated with this port
2759379bc100SJani Nikula 	 *   won't be active or linked to a crtc
2760379bc100SJani Nikula 	 * - old_crtc_state will be the state of the last stream to
2761379bc100SJani Nikula 	 *   be deactivated on this port, and it may not be the same
2762379bc100SJani Nikula 	 *   stream that was activated last, but each stream
2763379bc100SJani Nikula 	 *   should have a state that is identical when it comes to
2764379bc100SJani Nikula 	 *   the DP link parameteres
2765379bc100SJani Nikula 	 */
2766379bc100SJani Nikula 
2767379bc100SJani Nikula 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
2768ede9771dSVille Syrjälä 		intel_ddi_post_disable_hdmi(state, encoder, old_crtc_state,
2769ede9771dSVille Syrjälä 					    old_conn_state);
2770379bc100SJani Nikula 	else
2771ede9771dSVille Syrjälä 		intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
2772ede9771dSVille Syrjälä 					  old_conn_state);
2773379bc100SJani Nikula 
2774637c7aa2SImre Deak 	main_link_aux_power_domain_put(dig_port, old_crtc_state);
277517bef9baSVille Syrjälä 
277617bef9baSVille Syrjälä 	if (is_tc_port)
277717bef9baSVille Syrjälä 		intel_tc_port_put_link(dig_port);
2778379bc100SJani Nikula }
2779379bc100SJani Nikula 
2780d82a855aSVille Syrjälä static void trans_port_sync_stop_link_train(struct intel_atomic_state *state,
2781d82a855aSVille Syrjälä 					    struct intel_encoder *encoder,
2782d82a855aSVille Syrjälä 					    const struct intel_crtc_state *crtc_state)
2783d82a855aSVille Syrjälä {
2784d82a855aSVille Syrjälä 	const struct drm_connector_state *conn_state;
2785d82a855aSVille Syrjälä 	struct drm_connector *conn;
2786d82a855aSVille Syrjälä 	int i;
2787d82a855aSVille Syrjälä 
2788d82a855aSVille Syrjälä 	if (!crtc_state->sync_mode_slaves_mask)
2789d82a855aSVille Syrjälä 		return;
2790d82a855aSVille Syrjälä 
2791d82a855aSVille Syrjälä 	for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
2792d82a855aSVille Syrjälä 		struct intel_encoder *slave_encoder =
2793d82a855aSVille Syrjälä 			to_intel_encoder(conn_state->best_encoder);
2794d82a855aSVille Syrjälä 		struct intel_crtc *slave_crtc = to_intel_crtc(conn_state->crtc);
2795d82a855aSVille Syrjälä 		const struct intel_crtc_state *slave_crtc_state;
2796d82a855aSVille Syrjälä 
2797d82a855aSVille Syrjälä 		if (!slave_crtc)
2798d82a855aSVille Syrjälä 			continue;
2799d82a855aSVille Syrjälä 
2800d82a855aSVille Syrjälä 		slave_crtc_state =
2801d82a855aSVille Syrjälä 			intel_atomic_get_new_crtc_state(state, slave_crtc);
2802d82a855aSVille Syrjälä 
2803d82a855aSVille Syrjälä 		if (slave_crtc_state->master_transcoder !=
2804d82a855aSVille Syrjälä 		    crtc_state->cpu_transcoder)
2805d82a855aSVille Syrjälä 			continue;
2806d82a855aSVille Syrjälä 
2807a621860aSVille Syrjälä 		intel_dp_stop_link_train(enc_to_intel_dp(slave_encoder),
2808a621860aSVille Syrjälä 					 slave_crtc_state);
2809d82a855aSVille Syrjälä 	}
2810d82a855aSVille Syrjälä 
2811d82a855aSVille Syrjälä 	usleep_range(200, 400);
2812d82a855aSVille Syrjälä 
2813a621860aSVille Syrjälä 	intel_dp_stop_link_train(enc_to_intel_dp(encoder),
2814a621860aSVille Syrjälä 				 crtc_state);
2815d82a855aSVille Syrjälä }
2816d82a855aSVille Syrjälä 
2817ede9771dSVille Syrjälä static void intel_enable_ddi_dp(struct intel_atomic_state *state,
2818ede9771dSVille Syrjälä 				struct intel_encoder *encoder,
2819379bc100SJani Nikula 				const struct intel_crtc_state *crtc_state,
2820379bc100SJani Nikula 				const struct drm_connector_state *conn_state)
2821379bc100SJani Nikula {
2822379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2823b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2824998cc864SUma Shankar 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2825379bc100SJani Nikula 	enum port port = encoder->port;
2826379bc100SJani Nikula 
2827005e9537SMatt Roper 	if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
2828a621860aSVille Syrjälä 		intel_dp_stop_link_train(intel_dp, crtc_state);
2829379bc100SJani Nikula 
28306306d8dbSHans de Goede 	drm_connector_update_privacy_screen(conn_state);
2831379bc100SJani Nikula 	intel_edp_backlight_on(crtc_state, conn_state);
2832998cc864SUma Shankar 
2833998cc864SUma Shankar 	if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink)
28341bf3657cSGwan-gyeong Mun 		intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
2835998cc864SUma Shankar 
2836379bc100SJani Nikula 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
2837d82a855aSVille Syrjälä 
2838d82a855aSVille Syrjälä 	trans_port_sync_stop_link_train(state, encoder, crtc_state);
2839379bc100SJani Nikula }
2840379bc100SJani Nikula 
2841379bc100SJani Nikula static i915_reg_t
2842379bc100SJani Nikula gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
2843379bc100SJani Nikula 			       enum port port)
2844379bc100SJani Nikula {
284512c4d4c1SVille Syrjälä 	static const enum transcoder trans[] = {
284612c4d4c1SVille Syrjälä 		[PORT_A] = TRANSCODER_EDP,
284712c4d4c1SVille Syrjälä 		[PORT_B] = TRANSCODER_A,
284812c4d4c1SVille Syrjälä 		[PORT_C] = TRANSCODER_B,
284912c4d4c1SVille Syrjälä 		[PORT_D] = TRANSCODER_C,
285012c4d4c1SVille Syrjälä 		[PORT_E] = TRANSCODER_A,
2851379bc100SJani Nikula 	};
2852379bc100SJani Nikula 
2853005e9537SMatt Roper 	drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9);
2854379bc100SJani Nikula 
28551de143ccSPankaj Bharadiya 	if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E))
2856379bc100SJani Nikula 		port = PORT_A;
2857379bc100SJani Nikula 
285812c4d4c1SVille Syrjälä 	return CHICKEN_TRANS(trans[port]);
2859379bc100SJani Nikula }
2860379bc100SJani Nikula 
2861ede9771dSVille Syrjälä static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
2862ede9771dSVille Syrjälä 				  struct intel_encoder *encoder,
2863379bc100SJani Nikula 				  const struct intel_crtc_state *crtc_state,
2864379bc100SJani Nikula 				  const struct drm_connector_state *conn_state)
2865379bc100SJani Nikula {
2866379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2867b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2868379bc100SJani Nikula 	struct drm_connector *connector = conn_state->connector;
2869379bc100SJani Nikula 	enum port port = encoder->port;
2870e99ba962SImre Deak 	enum phy phy = intel_port_to_phy(dev_priv, port);
2871e99ba962SImre Deak 	u32 buf_ctl;
2872379bc100SJani Nikula 
2873379bc100SJani Nikula 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
2874379bc100SJani Nikula 					       crtc_state->hdmi_high_tmds_clock_ratio,
2875379bc100SJani Nikula 					       crtc_state->hdmi_scrambling))
287647bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
287747bdb1caSJani Nikula 			    "[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
2878379bc100SJani Nikula 			    connector->base.id, connector->name);
2879379bc100SJani Nikula 
28805bafd85dSVille Syrjälä 	if (has_buf_trans_select(dev_priv))
2881e722ab8bSVille Syrjälä 		hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state);
2882c9b69041SVille Syrjälä 
2883e722ab8bSVille Syrjälä 	encoder->set_signal_levels(encoder, crtc_state);
2884c9b69041SVille Syrjälä 
2885379bc100SJani Nikula 	/* Display WA #1143: skl,kbl,cfl */
288693e7e61eSLucas De Marchi 	if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
2887379bc100SJani Nikula 		/*
2888379bc100SJani Nikula 		 * For some reason these chicken bits have been
2889379bc100SJani Nikula 		 * stuffed into a transcoder register, event though
2890379bc100SJani Nikula 		 * the bits affect a specific DDI port rather than
2891379bc100SJani Nikula 		 * a specific transcoder.
2892379bc100SJani Nikula 		 */
2893379bc100SJani Nikula 		i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port);
2894379bc100SJani Nikula 		u32 val;
2895379bc100SJani Nikula 
2896f7960e7fSJani Nikula 		val = intel_de_read(dev_priv, reg);
2897379bc100SJani Nikula 
2898379bc100SJani Nikula 		if (port == PORT_E)
2899379bc100SJani Nikula 			val |= DDIE_TRAINING_OVERRIDE_ENABLE |
2900379bc100SJani Nikula 				DDIE_TRAINING_OVERRIDE_VALUE;
2901379bc100SJani Nikula 		else
2902379bc100SJani Nikula 			val |= DDI_TRAINING_OVERRIDE_ENABLE |
2903379bc100SJani Nikula 				DDI_TRAINING_OVERRIDE_VALUE;
2904379bc100SJani Nikula 
2905f7960e7fSJani Nikula 		intel_de_write(dev_priv, reg, val);
2906f7960e7fSJani Nikula 		intel_de_posting_read(dev_priv, reg);
2907379bc100SJani Nikula 
2908379bc100SJani Nikula 		udelay(1);
2909379bc100SJani Nikula 
2910379bc100SJani Nikula 		if (port == PORT_E)
2911379bc100SJani Nikula 			val &= ~(DDIE_TRAINING_OVERRIDE_ENABLE |
2912379bc100SJani Nikula 				 DDIE_TRAINING_OVERRIDE_VALUE);
2913379bc100SJani Nikula 		else
2914379bc100SJani Nikula 			val &= ~(DDI_TRAINING_OVERRIDE_ENABLE |
2915379bc100SJani Nikula 				 DDI_TRAINING_OVERRIDE_VALUE);
2916379bc100SJani Nikula 
2917f7960e7fSJani Nikula 		intel_de_write(dev_priv, reg, val);
2918379bc100SJani Nikula 	}
2919379bc100SJani Nikula 
29201e0cb7beSVille Syrjälä 	intel_ddi_power_up_lanes(encoder, crtc_state);
29211e0cb7beSVille Syrjälä 
2922379bc100SJani Nikula 	/* In HDMI/DVI mode, the port width, and swing/emphasis values
2923379bc100SJani Nikula 	 * are ignored so nothing special needs to be done besides
2924379bc100SJani Nikula 	 * enabling the port.
2925414002f1SImre Deak 	 *
2926414002f1SImre Deak 	 * On ADL_P the PHY link rate and lane count must be programmed but
2927414002f1SImre Deak 	 * these are both 0 for HDMI.
2928379bc100SJani Nikula 	 */
2929e99ba962SImre Deak 	buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
2930e99ba962SImre Deak 	if (IS_ALDERLAKE_P(dev_priv) && intel_phy_is_tc(dev_priv, phy)) {
2931e99ba962SImre Deak 		drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port));
2932e99ba962SImre Deak 		buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
2933e99ba962SImre Deak 	}
2934e99ba962SImre Deak 	intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
2935379bc100SJani Nikula 
293665e75edaSAnkit Nautiyal 	intel_wait_ddi_buf_active(dev_priv, port);
293765e75edaSAnkit Nautiyal 
2938379bc100SJani Nikula 	intel_audio_codec_enable(encoder, crtc_state, conn_state);
2939379bc100SJani Nikula }
2940379bc100SJani Nikula 
2941ede9771dSVille Syrjälä static void intel_enable_ddi(struct intel_atomic_state *state,
2942ede9771dSVille Syrjälä 			     struct intel_encoder *encoder,
2943379bc100SJani Nikula 			     const struct intel_crtc_state *crtc_state,
2944379bc100SJani Nikula 			     const struct drm_connector_state *conn_state)
2945379bc100SJani Nikula {
29468b4f2137SPankaj Bharadiya 	drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);
294721fd23acSJani Nikula 
2948df529053SVille Syrjälä 	if (!intel_crtc_is_bigjoiner_slave(crtc_state))
2949eed22a46SVille Syrjälä 		intel_ddi_enable_transcoder_func(encoder, crtc_state);
29507c2fedd7SVille Syrjälä 
29518853750dSVinod Govindapillai 	/* Enable/Disable DP2.0 SDP split config before transcoder */
29528853750dSVinod Govindapillai 	intel_audio_sdp_split_update(encoder, crtc_state);
29538853750dSVinod Govindapillai 
29548c66081bSVille Syrjälä 	intel_enable_transcoder(crtc_state);
295521fd23acSJani Nikula 
29560504d0acSVille Syrjälä 	intel_vrr_enable(encoder, crtc_state);
29570504d0acSVille Syrjälä 
295821fd23acSJani Nikula 	intel_crtc_vblank_on(crtc_state);
295921fd23acSJani Nikula 
2960379bc100SJani Nikula 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
2961ede9771dSVille Syrjälä 		intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state);
2962379bc100SJani Nikula 	else
2963ede9771dSVille Syrjälä 		intel_enable_ddi_dp(state, encoder, crtc_state, conn_state);
2964379bc100SJani Nikula 
2965379bc100SJani Nikula 	/* Enable hdcp if it's desired */
2966379bc100SJani Nikula 	if (conn_state->content_protection ==
2967379bc100SJani Nikula 	    DRM_MODE_CONTENT_PROTECTION_DESIRED)
2968d456512cSRamalingam C 		intel_hdcp_enable(to_intel_connector(conn_state->connector),
2969fc6097d4SAnshuman Gupta 				  crtc_state,
2970d456512cSRamalingam C 				  (u8)conn_state->hdcp_content_type);
2971379bc100SJani Nikula }
2972379bc100SJani Nikula 
2973ede9771dSVille Syrjälä static void intel_disable_ddi_dp(struct intel_atomic_state *state,
2974ede9771dSVille Syrjälä 				 struct intel_encoder *encoder,
2975379bc100SJani Nikula 				 const struct intel_crtc_state *old_crtc_state,
2976379bc100SJani Nikula 				 const struct drm_connector_state *old_conn_state)
2977379bc100SJani Nikula {
2978b7d02c3aSVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2979379bc100SJani Nikula 
2980379bc100SJani Nikula 	intel_dp->link_trained = false;
2981379bc100SJani Nikula 
2982179db7c1SJani Nikula 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
2983f28c5950SVille Syrjälä 
2984f28c5950SVille Syrjälä 	intel_psr_disable(intel_dp, old_crtc_state);
2985379bc100SJani Nikula 	intel_edp_backlight_off(old_conn_state);
2986379bc100SJani Nikula 	/* Disable the decompression in DP Sink */
2987379bc100SJani Nikula 	intel_dp_sink_set_decompression_state(intel_dp, old_crtc_state,
2988379bc100SJani Nikula 					      false);
29891639406aSManasi Navare 	/* Disable Ignore_MSA bit in DP Sink */
29901639406aSManasi Navare 	intel_dp_sink_set_msa_timing_par_ignore_state(intel_dp, old_crtc_state,
29911639406aSManasi Navare 						      false);
2992379bc100SJani Nikula }
2993379bc100SJani Nikula 
2994ede9771dSVille Syrjälä static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
2995ede9771dSVille Syrjälä 				   struct intel_encoder *encoder,
2996379bc100SJani Nikula 				   const struct intel_crtc_state *old_crtc_state,
2997379bc100SJani Nikula 				   const struct drm_connector_state *old_conn_state)
2998379bc100SJani Nikula {
299947bdb1caSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3000379bc100SJani Nikula 	struct drm_connector *connector = old_conn_state->connector;
3001379bc100SJani Nikula 
3002179db7c1SJani Nikula 	intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state);
3003f28c5950SVille Syrjälä 
3004379bc100SJani Nikula 	if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3005379bc100SJani Nikula 					       false, false))
300647bdb1caSJani Nikula 		drm_dbg_kms(&i915->drm,
300747bdb1caSJani Nikula 			    "[CONNECTOR:%d:%s] Failed to reset sink scrambling/TMDS bit clock ratio\n",
3008379bc100SJani Nikula 			    connector->base.id, connector->name);
3009379bc100SJani Nikula }
3010379bc100SJani Nikula 
3011ede9771dSVille Syrjälä static void intel_disable_ddi(struct intel_atomic_state *state,
3012ede9771dSVille Syrjälä 			      struct intel_encoder *encoder,
3013379bc100SJani Nikula 			      const struct intel_crtc_state *old_crtc_state,
3014379bc100SJani Nikula 			      const struct drm_connector_state *old_conn_state)
3015379bc100SJani Nikula {
3016379bc100SJani Nikula 	intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
3017379bc100SJani Nikula 
3018379bc100SJani Nikula 	if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3019ede9771dSVille Syrjälä 		intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
3020ede9771dSVille Syrjälä 				       old_conn_state);
3021379bc100SJani Nikula 	else
3022ede9771dSVille Syrjälä 		intel_disable_ddi_dp(state, encoder, old_crtc_state,
3023ede9771dSVille Syrjälä 				     old_conn_state);
3024379bc100SJani Nikula }
3025379bc100SJani Nikula 
3026ede9771dSVille Syrjälä static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
3027ede9771dSVille Syrjälä 				     struct intel_encoder *encoder,
3028379bc100SJani Nikula 				     const struct intel_crtc_state *crtc_state,
3029379bc100SJani Nikula 				     const struct drm_connector_state *conn_state)
3030379bc100SJani Nikula {
30310c06fa15SGwan-gyeong Mun 	intel_ddi_set_dp_msa(crtc_state, conn_state);
3032379bc100SJani Nikula 
303376d45d06SGwan-gyeong Mun 	intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3034379bc100SJani Nikula 
3035c0a52f8bSJani Nikula 	intel_backlight_update(state, encoder, crtc_state, conn_state);
30366306d8dbSHans de Goede 	drm_connector_update_privacy_screen(conn_state);
3037379bc100SJani Nikula }
3038379bc100SJani Nikula 
3039f1c7a36bSSean Paul void intel_ddi_update_pipe(struct intel_atomic_state *state,
3040ede9771dSVille Syrjälä 			   struct intel_encoder *encoder,
3041379bc100SJani Nikula 			   const struct intel_crtc_state *crtc_state,
3042379bc100SJani Nikula 			   const struct drm_connector_state *conn_state)
3043379bc100SJani Nikula {
3044d456512cSRamalingam C 
3045f1c7a36bSSean Paul 	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
3046f1c7a36bSSean Paul 	    !intel_encoder_is_mst(encoder))
3047ede9771dSVille Syrjälä 		intel_ddi_update_pipe_dp(state, encoder, crtc_state,
3048ede9771dSVille Syrjälä 					 conn_state);
3049379bc100SJani Nikula 
3050ede9771dSVille Syrjälä 	intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state);
3051379bc100SJani Nikula }
3052379bc100SJani Nikula 
3053379bc100SJani Nikula static void
305424a7bfe0SImre Deak intel_ddi_update_prepare(struct intel_atomic_state *state,
305524a7bfe0SImre Deak 			 struct intel_encoder *encoder,
305624a7bfe0SImre Deak 			 struct intel_crtc *crtc)
305724a7bfe0SImre Deak {
3058a6e7a006SVille Syrjälä 	struct drm_i915_private *i915 = to_i915(state->base.dev);
305924a7bfe0SImre Deak 	struct intel_crtc_state *crtc_state =
306024a7bfe0SImre Deak 		crtc ? intel_atomic_get_new_crtc_state(state, crtc) : NULL;
306124a7bfe0SImre Deak 	int required_lanes = crtc_state ? crtc_state->lane_count : 1;
306224a7bfe0SImre Deak 
30638b4f2137SPankaj Bharadiya 	drm_WARN_ON(state->base.dev, crtc && crtc->active);
306424a7bfe0SImre Deak 
3065b7d02c3aSVille Syrjälä 	intel_tc_port_get_link(enc_to_dig_port(encoder),
3066b7d02c3aSVille Syrjälä 		               required_lanes);
3067c68dac96SVille Syrjälä 	if (crtc_state && crtc_state->hw.active) {
3068a6e7a006SVille Syrjälä 		struct intel_crtc *slave_crtc;
3069c68dac96SVille Syrjälä 
307024a7bfe0SImre Deak 		intel_update_active_dpll(state, crtc, encoder);
3071c68dac96SVille Syrjälä 
3072a6e7a006SVille Syrjälä 		for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
3073a6e7a006SVille Syrjälä 						 intel_crtc_bigjoiner_slave_pipes(crtc_state))
3074c68dac96SVille Syrjälä 			intel_update_active_dpll(state, slave_crtc, encoder);
3075c68dac96SVille Syrjälä 	}
307624a7bfe0SImre Deak }
307724a7bfe0SImre Deak 
307824a7bfe0SImre Deak static void
307924a7bfe0SImre Deak intel_ddi_update_complete(struct intel_atomic_state *state,
308024a7bfe0SImre Deak 			  struct intel_encoder *encoder,
308124a7bfe0SImre Deak 			  struct intel_crtc *crtc)
308224a7bfe0SImre Deak {
3083b7d02c3aSVille Syrjälä 	intel_tc_port_put_link(enc_to_dig_port(encoder));
308424a7bfe0SImre Deak }
308524a7bfe0SImre Deak 
308624a7bfe0SImre Deak static void
3087ede9771dSVille Syrjälä intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
3088ede9771dSVille Syrjälä 			 struct intel_encoder *encoder,
3089379bc100SJani Nikula 			 const struct intel_crtc_state *crtc_state,
3090379bc100SJani Nikula 			 const struct drm_connector_state *conn_state)
3091379bc100SJani Nikula {
3092379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3093b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3094d8fe2ab6SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
3095d8fe2ab6SMatt Roper 	bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
3096379bc100SJani Nikula 
309724a7bfe0SImre Deak 	if (is_tc_port)
309824a7bfe0SImre Deak 		intel_tc_port_get_link(dig_port, crtc_state->lane_count);
309924a7bfe0SImre Deak 
3100637c7aa2SImre Deak 	main_link_aux_power_domain_get(dig_port, crtc_state);
3101379bc100SJani Nikula 
310211a89708SImre Deak 	if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port))
31039d44dcb9SLucas De Marchi 		/*
31049d44dcb9SLucas De Marchi 		 * Program the lane count for static/dynamic connections on
31059d44dcb9SLucas De Marchi 		 * Type-C ports.  Skip this step for TBT.
31069d44dcb9SLucas De Marchi 		 */
31079d44dcb9SLucas De Marchi 		intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count);
31082446e1d6SMatt Roper 	else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3109379bc100SJani Nikula 		bxt_ddi_phy_set_lane_optim_mask(encoder,
3110379bc100SJani Nikula 						crtc_state->lane_lat_optim_mask);
3111379bc100SJani Nikula }
3112379bc100SJani Nikula 
311355223c3bSImre Deak static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
311455223c3bSImre Deak {
311555223c3bSImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
311655223c3bSImre Deak 	enum tc_port tc_port = intel_port_to_tc(i915, encoder->port);
311755223c3bSImre Deak 	int ln;
311855223c3bSImre Deak 
311989cb0ba4SImre Deak 	for (ln = 0; ln < 2; ln++)
3120b8ed5533SImre Deak 		intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0);
312155223c3bSImre Deak }
312255223c3bSImre Deak 
3123a621860aSVille Syrjälä static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
3124a621860aSVille Syrjälä 					   const struct intel_crtc_state *crtc_state)
3125379bc100SJani Nikula {
312655223c3bSImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
312755223c3bSImre Deak 	struct intel_encoder *encoder = &dig_port->base;
3128ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3129ef79fafeSVille Syrjälä 	enum port port = encoder->port;
313035ac28a8SLucas De Marchi 	u32 dp_tp_ctl, ddi_buf_ctl;
3131379bc100SJani Nikula 	bool wait = false;
3132379bc100SJani Nikula 
3133ef79fafeSVille Syrjälä 	dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
313435ac28a8SLucas De Marchi 
313535ac28a8SLucas De Marchi 	if (dp_tp_ctl & DP_TP_CTL_ENABLE) {
3136f7960e7fSJani Nikula 		ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port));
313735ac28a8SLucas De Marchi 		if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) {
3138f7960e7fSJani Nikula 			intel_de_write(dev_priv, DDI_BUF_CTL(port),
313935ac28a8SLucas De Marchi 				       ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE);
3140379bc100SJani Nikula 			wait = true;
3141379bc100SJani Nikula 		}
3142379bc100SJani Nikula 
314335ac28a8SLucas De Marchi 		dp_tp_ctl &= ~(DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_MASK);
314435ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_LINK_TRAIN_PAT1;
3145ef79fafeSVille Syrjälä 		intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3146ef79fafeSVille Syrjälä 		intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3147379bc100SJani Nikula 
3148379bc100SJani Nikula 		if (wait)
3149379bc100SJani Nikula 			intel_wait_ddi_buf_idle(dev_priv, port);
3150379bc100SJani Nikula 	}
3151379bc100SJani Nikula 
3152963501bdSImre Deak 	dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
3153a621860aSVille Syrjälä 	if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
315435ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_MODE_MST;
3155a621860aSVille Syrjälä 	} else {
315635ac28a8SLucas De Marchi 		dp_tp_ctl |= DP_TP_CTL_MODE_SST;
3157379bc100SJani Nikula 		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
315835ac28a8SLucas De Marchi 			dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
3159379bc100SJani Nikula 	}
3160ef79fafeSVille Syrjälä 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3161ef79fafeSVille Syrjälä 	intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3162379bc100SJani Nikula 
316355223c3bSImre Deak 	if (IS_ALDERLAKE_P(dev_priv) &&
316455223c3bSImre Deak 	    (intel_tc_port_in_dp_alt_mode(dig_port) || intel_tc_port_in_legacy_mode(dig_port)))
316555223c3bSImre Deak 		adlp_tbt_to_dp_alt_switch_wa(encoder);
316655223c3bSImre Deak 
3167379bc100SJani Nikula 	intel_dp->DP |= DDI_BUF_CTL_ENABLE;
3168f7960e7fSJani Nikula 	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
3169f7960e7fSJani Nikula 	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
3170379bc100SJani Nikula 
3171e828da30SManasi Navare 	intel_wait_ddi_buf_active(dev_priv, port);
3172379bc100SJani Nikula }
3173379bc100SJani Nikula 
3174eee3f911SVille Syrjälä static void intel_ddi_set_link_train(struct intel_dp *intel_dp,
3175a621860aSVille Syrjälä 				     const struct intel_crtc_state *crtc_state,
3176eee3f911SVille Syrjälä 				     u8 dp_train_pat)
3177eee3f911SVille Syrjälä {
3178ef79fafeSVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
3179ef79fafeSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3180eee3f911SVille Syrjälä 	u32 temp;
3181eee3f911SVille Syrjälä 
3182ef79fafeSVille Syrjälä 	temp = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3183eee3f911SVille Syrjälä 
3184eee3f911SVille Syrjälä 	temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
31856777a855SImre Deak 	switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
3186eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_DISABLE:
3187eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
3188eee3f911SVille Syrjälä 		break;
3189eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_1:
3190eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
3191eee3f911SVille Syrjälä 		break;
3192eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_2:
3193eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
3194eee3f911SVille Syrjälä 		break;
3195eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_3:
3196eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
3197eee3f911SVille Syrjälä 		break;
3198eee3f911SVille Syrjälä 	case DP_TRAINING_PATTERN_4:
3199eee3f911SVille Syrjälä 		temp |= DP_TP_CTL_LINK_TRAIN_PAT4;
3200eee3f911SVille Syrjälä 		break;
3201eee3f911SVille Syrjälä 	}
3202eee3f911SVille Syrjälä 
3203ef79fafeSVille Syrjälä 	intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), temp);
3204eee3f911SVille Syrjälä }
3205eee3f911SVille Syrjälä 
3206a621860aSVille Syrjälä static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp,
3207a621860aSVille Syrjälä 					  const struct intel_crtc_state *crtc_state)
32088fdda385SVille Syrjälä {
32098fdda385SVille Syrjälä 	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
32108fdda385SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
32118fdda385SVille Syrjälä 	enum port port = encoder->port;
32128fdda385SVille Syrjälä 
32138910d8b7SAndrzej Hajda 	intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
32148910d8b7SAndrzej Hajda 		     DP_TP_CTL_LINK_TRAIN_MASK, DP_TP_CTL_LINK_TRAIN_IDLE);
32158fdda385SVille Syrjälä 
32168fdda385SVille Syrjälä 	/*
32178fdda385SVille Syrjälä 	 * Until TGL on PORT_A we can have only eDP in SST mode. There the only
32188fdda385SVille Syrjälä 	 * reason we need to set idle transmission mode is to work around a HW
32198fdda385SVille Syrjälä 	 * issue where we enable the pipe while not in idle link-training mode.
32208fdda385SVille Syrjälä 	 * In this case there is requirement to wait for a minimum number of
32218fdda385SVille Syrjälä 	 * idle patterns to be sent.
32228fdda385SVille Syrjälä 	 */
3223005e9537SMatt Roper 	if (port == PORT_A && DISPLAY_VER(dev_priv) < 12)
32248fdda385SVille Syrjälä 		return;
32258fdda385SVille Syrjälä 
3226ef79fafeSVille Syrjälä 	if (intel_de_wait_for_set(dev_priv,
3227ef79fafeSVille Syrjälä 				  dp_tp_status_reg(encoder, crtc_state),
32288fdda385SVille Syrjälä 				  DP_TP_STATUS_IDLE_DONE, 1))
32298fdda385SVille Syrjälä 		drm_err(&dev_priv->drm,
32308fdda385SVille Syrjälä 			"Timed out waiting for DP idle patterns\n");
32318fdda385SVille Syrjälä }
32328fdda385SVille Syrjälä 
3233379bc100SJani Nikula static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
3234379bc100SJani Nikula 				       enum transcoder cpu_transcoder)
3235379bc100SJani Nikula {
3236379bc100SJani Nikula 	if (cpu_transcoder == TRANSCODER_EDP)
3237379bc100SJani Nikula 		return false;
3238379bc100SJani Nikula 
3239615a7724SAnshuman Gupta 	if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO_MMIO))
3240379bc100SJani Nikula 		return false;
3241379bc100SJani Nikula 
3242f7960e7fSJani Nikula 	return intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD) &
3243379bc100SJani Nikula 		AUDIO_OUTPUT_ENABLE(cpu_transcoder);
3244379bc100SJani Nikula }
3245379bc100SJani Nikula 
3246379bc100SJani Nikula void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
3247379bc100SJani Nikula 					 struct intel_crtc_state *crtc_state)
3248379bc100SJani Nikula {
3249005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 12 && crtc_state->port_clock > 594000)
32500fde0b1dSMatt Roper 		crtc_state->min_voltage_level = 2;
325124ea098bSTejas Upadhyay 	else if (IS_JSL_EHL(dev_priv) && crtc_state->port_clock > 594000)
32529d5fd37eSMatt Roper 		crtc_state->min_voltage_level = 3;
3253005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 11 && crtc_state->port_clock > 594000)
3254379bc100SJani Nikula 		crtc_state->min_voltage_level = 1;
3255379bc100SJani Nikula }
3256379bc100SJani Nikula 
3257dc5b8ed5SVille Syrjälä static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *dev_priv,
325802d8ea47SVille Syrjälä 						     enum transcoder cpu_transcoder)
325902d8ea47SVille Syrjälä {
3260dc5b8ed5SVille Syrjälä 	u32 master_select;
326102d8ea47SVille Syrjälä 
3262005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
3263dc5b8ed5SVille Syrjälä 		u32 ctl2 = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL2(cpu_transcoder));
326402d8ea47SVille Syrjälä 
326502d8ea47SVille Syrjälä 		if ((ctl2 & PORT_SYNC_MODE_ENABLE) == 0)
326602d8ea47SVille Syrjälä 			return INVALID_TRANSCODER;
326702d8ea47SVille Syrjälä 
3268d4d7d9caSVille Syrjälä 		master_select = REG_FIELD_GET(PORT_SYNC_MODE_MASTER_SELECT_MASK, ctl2);
3269dc5b8ed5SVille Syrjälä 	} else {
3270dc5b8ed5SVille Syrjälä 		u32 ctl = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
3271dc5b8ed5SVille Syrjälä 
3272dc5b8ed5SVille Syrjälä 		if ((ctl & TRANS_DDI_PORT_SYNC_ENABLE) == 0)
3273dc5b8ed5SVille Syrjälä 			return INVALID_TRANSCODER;
3274dc5b8ed5SVille Syrjälä 
3275dc5b8ed5SVille Syrjälä 		master_select = REG_FIELD_GET(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, ctl);
3276dc5b8ed5SVille Syrjälä 	}
327702d8ea47SVille Syrjälä 
327802d8ea47SVille Syrjälä 	if (master_select == 0)
327902d8ea47SVille Syrjälä 		return TRANSCODER_EDP;
328002d8ea47SVille Syrjälä 	else
328102d8ea47SVille Syrjälä 		return master_select - 1;
328202d8ea47SVille Syrjälä }
328302d8ea47SVille Syrjälä 
3284dc5b8ed5SVille Syrjälä static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
328502d8ea47SVille Syrjälä {
328602d8ea47SVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
328702d8ea47SVille Syrjälä 	u32 transcoders = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
328802d8ea47SVille Syrjälä 		BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
328902d8ea47SVille Syrjälä 	enum transcoder cpu_transcoder;
329002d8ea47SVille Syrjälä 
329102d8ea47SVille Syrjälä 	crtc_state->master_transcoder =
3292dc5b8ed5SVille Syrjälä 		bdw_transcoder_master_readout(dev_priv, crtc_state->cpu_transcoder);
329302d8ea47SVille Syrjälä 
329402d8ea47SVille Syrjälä 	for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
329502d8ea47SVille Syrjälä 		enum intel_display_power_domain power_domain;
329602d8ea47SVille Syrjälä 		intel_wakeref_t trans_wakeref;
329702d8ea47SVille Syrjälä 
329802d8ea47SVille Syrjälä 		power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
329902d8ea47SVille Syrjälä 		trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
330002d8ea47SVille Syrjälä 								   power_domain);
330102d8ea47SVille Syrjälä 
330202d8ea47SVille Syrjälä 		if (!trans_wakeref)
330302d8ea47SVille Syrjälä 			continue;
330402d8ea47SVille Syrjälä 
3305dc5b8ed5SVille Syrjälä 		if (bdw_transcoder_master_readout(dev_priv, cpu_transcoder) ==
330602d8ea47SVille Syrjälä 		    crtc_state->cpu_transcoder)
330702d8ea47SVille Syrjälä 			crtc_state->sync_mode_slaves_mask |= BIT(cpu_transcoder);
330802d8ea47SVille Syrjälä 
330902d8ea47SVille Syrjälä 		intel_display_power_put(dev_priv, power_domain, trans_wakeref);
331002d8ea47SVille Syrjälä 	}
331102d8ea47SVille Syrjälä 
331202d8ea47SVille Syrjälä 	drm_WARN_ON(&dev_priv->drm,
331302d8ea47SVille Syrjälä 		    crtc_state->master_transcoder != INVALID_TRANSCODER &&
331402d8ea47SVille Syrjälä 		    crtc_state->sync_mode_slaves_mask);
331502d8ea47SVille Syrjälä }
331602d8ea47SVille Syrjälä 
33170385eceaSManasi Navare static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
3318379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config)
3319379bc100SJani Nikula {
3320379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3321f15f01a7SVille Syrjälä 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
3322379bc100SJani Nikula 	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
3323a44289b9SUma Shankar 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3324379bc100SJani Nikula 	u32 temp, flags = 0;
3325379bc100SJani Nikula 
3326f7960e7fSJani Nikula 	temp = intel_de_read(dev_priv, TRANS_DDI_FUNC_CTL(cpu_transcoder));
3327379bc100SJani Nikula 	if (temp & TRANS_DDI_PHSYNC)
3328379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_PHSYNC;
3329379bc100SJani Nikula 	else
3330379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_NHSYNC;
3331379bc100SJani Nikula 	if (temp & TRANS_DDI_PVSYNC)
3332379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_PVSYNC;
3333379bc100SJani Nikula 	else
3334379bc100SJani Nikula 		flags |= DRM_MODE_FLAG_NVSYNC;
3335379bc100SJani Nikula 
33361326a92cSMaarten Lankhorst 	pipe_config->hw.adjusted_mode.flags |= flags;
3337379bc100SJani Nikula 
3338379bc100SJani Nikula 	switch (temp & TRANS_DDI_BPC_MASK) {
3339379bc100SJani Nikula 	case TRANS_DDI_BPC_6:
3340379bc100SJani Nikula 		pipe_config->pipe_bpp = 18;
3341379bc100SJani Nikula 		break;
3342379bc100SJani Nikula 	case TRANS_DDI_BPC_8:
3343379bc100SJani Nikula 		pipe_config->pipe_bpp = 24;
3344379bc100SJani Nikula 		break;
3345379bc100SJani Nikula 	case TRANS_DDI_BPC_10:
3346379bc100SJani Nikula 		pipe_config->pipe_bpp = 30;
3347379bc100SJani Nikula 		break;
3348379bc100SJani Nikula 	case TRANS_DDI_BPC_12:
3349379bc100SJani Nikula 		pipe_config->pipe_bpp = 36;
3350379bc100SJani Nikula 		break;
3351379bc100SJani Nikula 	default:
3352379bc100SJani Nikula 		break;
3353379bc100SJani Nikula 	}
3354379bc100SJani Nikula 
3355379bc100SJani Nikula 	switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
3356379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_HDMI:
3357379bc100SJani Nikula 		pipe_config->has_hdmi_sink = true;
3358379bc100SJani Nikula 
3359379bc100SJani Nikula 		pipe_config->infoframes.enable |=
3360379bc100SJani Nikula 			intel_hdmi_infoframes_enabled(encoder, pipe_config);
3361379bc100SJani Nikula 
3362379bc100SJani Nikula 		if (pipe_config->infoframes.enable)
3363379bc100SJani Nikula 			pipe_config->has_infoframe = true;
3364379bc100SJani Nikula 
3365379bc100SJani Nikula 		if (temp & TRANS_DDI_HDMI_SCRAMBLING)
3366379bc100SJani Nikula 			pipe_config->hdmi_scrambling = true;
3367379bc100SJani Nikula 		if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
3368379bc100SJani Nikula 			pipe_config->hdmi_high_tmds_clock_ratio = true;
3369df561f66SGustavo A. R. Silva 		fallthrough;
3370379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DVI:
3371379bc100SJani Nikula 		pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
3372379bc100SJani Nikula 		pipe_config->lane_count = 4;
3373379bc100SJani Nikula 		break;
3374379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_SST:
3375379bc100SJani Nikula 		if (encoder->type == INTEL_OUTPUT_EDP)
3376379bc100SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP);
3377379bc100SJani Nikula 		else
3378379bc100SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
3379379bc100SJani Nikula 		pipe_config->lane_count =
3380379bc100SJani Nikula 			((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
33816149cb68SVille Syrjälä 
33825cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
33835cd06644SVille Syrjälä 					       &pipe_config->dp_m_n);
33845cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
33856149cb68SVille Syrjälä 					       &pipe_config->dp_m2_n2);
33868aa940c8SMaarten Lankhorst 
3387005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 11) {
3388ef79fafeSVille Syrjälä 			i915_reg_t dp_tp_ctl = dp_tp_ctl_reg(encoder, pipe_config);
33898aa940c8SMaarten Lankhorst 
33908aa940c8SMaarten Lankhorst 			pipe_config->fec_enable =
3391f7960e7fSJani Nikula 				intel_de_read(dev_priv, dp_tp_ctl) & DP_TP_CTL_FEC_ENABLE;
33928aa940c8SMaarten Lankhorst 
339347bdb1caSJani Nikula 			drm_dbg_kms(&dev_priv->drm,
339447bdb1caSJani Nikula 				    "[ENCODER:%d:%s] Fec status: %u\n",
33958aa940c8SMaarten Lankhorst 				    encoder->base.base.id, encoder->base.name,
33968aa940c8SMaarten Lankhorst 				    pipe_config->fec_enable);
33978aa940c8SMaarten Lankhorst 		}
33988aa940c8SMaarten Lankhorst 
3399a44289b9SUma Shankar 		if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink)
3400a44289b9SUma Shankar 			pipe_config->infoframes.enable |=
3401a44289b9SUma Shankar 				intel_lspcon_infoframes_enabled(encoder, pipe_config);
3402a44289b9SUma Shankar 		else
3403dee66f3eSGwan-gyeong Mun 			pipe_config->infoframes.enable |=
3404dee66f3eSGwan-gyeong Mun 				intel_hdmi_infoframes_enabled(encoder, pipe_config);
3405379bc100SJani Nikula 		break;
340665213594SJani Nikula 	case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
340765213594SJani Nikula 		if (!HAS_DP20(dev_priv)) {
340865213594SJani Nikula 			/* FDI */
340965213594SJani Nikula 			pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
341065213594SJani Nikula 			break;
341165213594SJani Nikula 		}
341265213594SJani Nikula 		fallthrough; /* 128b/132b */
3413379bc100SJani Nikula 	case TRANS_DDI_MODE_SELECT_DP_MST:
3414379bc100SJani Nikula 		pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
3415379bc100SJani Nikula 		pipe_config->lane_count =
3416379bc100SJani Nikula 			((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
34176671c367SJosé Roberto de Souza 
3418005e9537SMatt Roper 		if (DISPLAY_VER(dev_priv) >= 12)
34196671c367SJosé Roberto de Souza 			pipe_config->mst_master_transcoder =
34206671c367SJosé Roberto de Souza 					REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
34216671c367SJosé Roberto de Souza 
34225cd06644SVille Syrjälä 		intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
34235cd06644SVille Syrjälä 					       &pipe_config->dp_m_n);
3424dee66f3eSGwan-gyeong Mun 
3425dee66f3eSGwan-gyeong Mun 		pipe_config->infoframes.enable |=
3426dee66f3eSGwan-gyeong Mun 			intel_hdmi_infoframes_enabled(encoder, pipe_config);
3427379bc100SJani Nikula 		break;
3428379bc100SJani Nikula 	default:
3429379bc100SJani Nikula 		break;
3430379bc100SJani Nikula 	}
34310385eceaSManasi Navare }
34320385eceaSManasi Navare 
3433351221ffSVille Syrjälä static void intel_ddi_get_config(struct intel_encoder *encoder,
34340385eceaSManasi Navare 				 struct intel_crtc_state *pipe_config)
34350385eceaSManasi Navare {
34360385eceaSManasi Navare 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
34370385eceaSManasi Navare 	enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
34380385eceaSManasi Navare 
34390385eceaSManasi Navare 	/* XXX: DSI transcoder paranoia */
34400385eceaSManasi Navare 	if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)))
34410385eceaSManasi Navare 		return;
34420385eceaSManasi Navare 
34430385eceaSManasi Navare 	intel_ddi_read_func_ctl(encoder, pipe_config);
3444379bc100SJani Nikula 
34455b616a29SJani Nikula 	intel_ddi_mso_get_config(encoder, pipe_config);
34465b616a29SJani Nikula 
3447379bc100SJani Nikula 	pipe_config->has_audio =
3448379bc100SJani Nikula 		intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
3449379bc100SJani Nikula 
3450822e5ae7SVille Syrjälä 	if (encoder->type == INTEL_OUTPUT_EDP)
3451822e5ae7SVille Syrjälä 		intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp);
3452379bc100SJani Nikula 
3453351221ffSVille Syrjälä 	ddi_dotclock_get(pipe_config);
3454379bc100SJani Nikula 
34552446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3456379bc100SJani Nikula 		pipe_config->lane_lat_optim_mask =
3457379bc100SJani Nikula 			bxt_ddi_phy_get_lane_lat_optim_mask(encoder);
3458379bc100SJani Nikula 
3459379bc100SJani Nikula 	intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
3460379bc100SJani Nikula 
3461379bc100SJani Nikula 	intel_hdmi_read_gcp_infoframe(encoder, pipe_config);
3462379bc100SJani Nikula 
3463379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3464379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_AVI,
3465379bc100SJani Nikula 			     &pipe_config->infoframes.avi);
3466379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3467379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_SPD,
3468379bc100SJani Nikula 			     &pipe_config->infoframes.spd);
3469379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3470379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_VENDOR,
3471379bc100SJani Nikula 			     &pipe_config->infoframes.hdmi);
3472379bc100SJani Nikula 	intel_read_infoframe(encoder, pipe_config,
3473379bc100SJani Nikula 			     HDMI_INFOFRAME_TYPE_DRM,
3474379bc100SJani Nikula 			     &pipe_config->infoframes.drm);
347502d8ea47SVille Syrjälä 
3476005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 8)
3477dc5b8ed5SVille Syrjälä 		bdw_get_trans_port_sync_config(pipe_config);
3478dee66f3eSGwan-gyeong Mun 
3479dee66f3eSGwan-gyeong Mun 	intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
34802c3928e4SGwan-gyeong Mun 	intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
348178b772e1SJosé Roberto de Souza 
348278b772e1SJosé Roberto de Souza 	intel_psr_get_config(encoder, pipe_config);
348361a60df6SVille Syrjälä 
348461a60df6SVille Syrjälä 	intel_audio_codec_get_config(encoder, pipe_config);
3485379bc100SJani Nikula }
3486379bc100SJani Nikula 
3487351221ffSVille Syrjälä void intel_ddi_get_clock(struct intel_encoder *encoder,
3488351221ffSVille Syrjälä 			 struct intel_crtc_state *crtc_state,
3489351221ffSVille Syrjälä 			 struct intel_shared_dpll *pll)
3490351221ffSVille Syrjälä {
3491351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3492351221ffSVille Syrjälä 	enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
3493351221ffSVille Syrjälä 	struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
3494351221ffSVille Syrjälä 	bool pll_active;
3495351221ffSVille Syrjälä 
3496086877a1SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
3497086877a1SVille Syrjälä 		return;
3498086877a1SVille Syrjälä 
3499351221ffSVille Syrjälä 	port_dpll->pll = pll;
3500351221ffSVille Syrjälä 	pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
3501351221ffSVille Syrjälä 	drm_WARN_ON(&i915->drm, !pll_active);
3502351221ffSVille Syrjälä 
3503351221ffSVille Syrjälä 	icl_set_active_port_dpll(crtc_state, port_dpll_id);
3504351221ffSVille Syrjälä 
3505351221ffSVille Syrjälä 	crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
3506351221ffSVille Syrjälä 						     &crtc_state->dpll_hw_state);
3507351221ffSVille Syrjälä }
3508351221ffSVille Syrjälä 
3509865b73eaSMatt Roper static void dg2_ddi_get_config(struct intel_encoder *encoder,
3510865b73eaSMatt Roper 				struct intel_crtc_state *crtc_state)
3511865b73eaSMatt Roper {
3512865b73eaSMatt Roper 	intel_mpllb_readout_hw_state(encoder, &crtc_state->mpllb_state);
3513865b73eaSMatt Roper 	crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->mpllb_state);
3514865b73eaSMatt Roper 
3515865b73eaSMatt Roper 	intel_ddi_get_config(encoder, crtc_state);
3516865b73eaSMatt Roper }
3517865b73eaSMatt Roper 
3518351221ffSVille Syrjälä static void adls_ddi_get_config(struct intel_encoder *encoder,
3519351221ffSVille Syrjälä 				struct intel_crtc_state *crtc_state)
3520351221ffSVille Syrjälä {
3521351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, adls_ddi_get_pll(encoder));
3522351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3523351221ffSVille Syrjälä }
3524351221ffSVille Syrjälä 
3525351221ffSVille Syrjälä static void rkl_ddi_get_config(struct intel_encoder *encoder,
3526351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3527351221ffSVille Syrjälä {
3528351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, rkl_ddi_get_pll(encoder));
3529351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3530351221ffSVille Syrjälä }
3531351221ffSVille Syrjälä 
3532351221ffSVille Syrjälä static void dg1_ddi_get_config(struct intel_encoder *encoder,
3533351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3534351221ffSVille Syrjälä {
3535351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, dg1_ddi_get_pll(encoder));
3536351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3537351221ffSVille Syrjälä }
3538351221ffSVille Syrjälä 
3539351221ffSVille Syrjälä static void icl_ddi_combo_get_config(struct intel_encoder *encoder,
3540351221ffSVille Syrjälä 				     struct intel_crtc_state *crtc_state)
3541351221ffSVille Syrjälä {
3542351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, icl_ddi_combo_get_pll(encoder));
3543351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3544351221ffSVille Syrjälä }
3545351221ffSVille Syrjälä 
3546086877a1SVille Syrjälä static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
3547086877a1SVille Syrjälä 				 struct intel_crtc_state *crtc_state,
3548086877a1SVille Syrjälä 				 struct intel_shared_dpll *pll)
3549351221ffSVille Syrjälä {
3550351221ffSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3551351221ffSVille Syrjälä 	enum icl_port_dpll_id port_dpll_id;
3552351221ffSVille Syrjälä 	struct icl_port_dpll *port_dpll;
3553351221ffSVille Syrjälä 	bool pll_active;
3554351221ffSVille Syrjälä 
3555086877a1SVille Syrjälä 	if (drm_WARN_ON(&i915->drm, !pll))
3556086877a1SVille Syrjälä 		return;
3557351221ffSVille Syrjälä 
3558e731a2d2SVille Syrjälä 	if (pll->info->id == DPLL_ID_ICL_TBTPLL)
3559351221ffSVille Syrjälä 		port_dpll_id = ICL_PORT_DPLL_DEFAULT;
3560351221ffSVille Syrjälä 	else
3561351221ffSVille Syrjälä 		port_dpll_id = ICL_PORT_DPLL_MG_PHY;
3562351221ffSVille Syrjälä 
3563351221ffSVille Syrjälä 	port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
3564351221ffSVille Syrjälä 
3565351221ffSVille Syrjälä 	port_dpll->pll = pll;
3566351221ffSVille Syrjälä 	pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
3567351221ffSVille Syrjälä 	drm_WARN_ON(&i915->drm, !pll_active);
3568351221ffSVille Syrjälä 
3569351221ffSVille Syrjälä 	icl_set_active_port_dpll(crtc_state, port_dpll_id);
3570351221ffSVille Syrjälä 
3571e731a2d2SVille Syrjälä 	if (crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL)
3572351221ffSVille Syrjälä 		crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port);
3573351221ffSVille Syrjälä 	else
3574351221ffSVille Syrjälä 		crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
3575351221ffSVille Syrjälä 							     &crtc_state->dpll_hw_state);
3576086877a1SVille Syrjälä }
3577351221ffSVille Syrjälä 
3578086877a1SVille Syrjälä static void icl_ddi_tc_get_config(struct intel_encoder *encoder,
3579086877a1SVille Syrjälä 				  struct intel_crtc_state *crtc_state)
3580086877a1SVille Syrjälä {
3581086877a1SVille Syrjälä 	icl_ddi_tc_get_clock(encoder, crtc_state, icl_ddi_tc_get_pll(encoder));
3582351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3583351221ffSVille Syrjälä }
3584351221ffSVille Syrjälä 
3585351221ffSVille Syrjälä static void bxt_ddi_get_config(struct intel_encoder *encoder,
3586351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3587351221ffSVille Syrjälä {
3588351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, bxt_ddi_get_pll(encoder));
3589351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3590351221ffSVille Syrjälä }
3591351221ffSVille Syrjälä 
3592351221ffSVille Syrjälä static void skl_ddi_get_config(struct intel_encoder *encoder,
3593351221ffSVille Syrjälä 			       struct intel_crtc_state *crtc_state)
3594351221ffSVille Syrjälä {
3595351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, skl_ddi_get_pll(encoder));
3596351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3597351221ffSVille Syrjälä }
3598351221ffSVille Syrjälä 
3599351221ffSVille Syrjälä void hsw_ddi_get_config(struct intel_encoder *encoder,
3600351221ffSVille Syrjälä 			struct intel_crtc_state *crtc_state)
3601351221ffSVille Syrjälä {
3602351221ffSVille Syrjälä 	intel_ddi_get_clock(encoder, crtc_state, hsw_ddi_get_pll(encoder));
3603351221ffSVille Syrjälä 	intel_ddi_get_config(encoder, crtc_state);
3604351221ffSVille Syrjälä }
3605351221ffSVille Syrjälä 
3606f9e76a6eSImre Deak static void intel_ddi_sync_state(struct intel_encoder *encoder,
3607f9e76a6eSImre Deak 				 const struct intel_crtc_state *crtc_state)
3608f9e76a6eSImre Deak {
36097194dc99SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
36107194dc99SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
36117194dc99SImre Deak 
36127194dc99SImre Deak 	if (intel_phy_is_tc(i915, phy))
3613a82796a2SImre Deak 		intel_tc_port_sanitize_mode(enc_to_dig_port(encoder));
36147194dc99SImre Deak 
36157194dc99SImre Deak 	if (crtc_state && intel_crtc_has_dp_encoder(crtc_state))
3616f9e76a6eSImre Deak 		intel_dp_sync_state(encoder, crtc_state);
3617f9e76a6eSImre Deak }
3618f9e76a6eSImre Deak 
3619b671d6efSImre Deak static bool intel_ddi_initial_fastset_check(struct intel_encoder *encoder,
3620b671d6efSImre Deak 					    struct intel_crtc_state *crtc_state)
3621b671d6efSImre Deak {
3622eddb4afcSVille Syrjälä 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3623eddb4afcSVille Syrjälä 	enum phy phy = intel_port_to_phy(i915, encoder->port);
3624eddb4afcSVille Syrjälä 	bool fastset = true;
3625b671d6efSImre Deak 
3626eddb4afcSVille Syrjälä 	if (intel_phy_is_tc(i915, phy)) {
3627eddb4afcSVille Syrjälä 		drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute TC port DPLLs\n",
3628eddb4afcSVille Syrjälä 			    encoder->base.base.id, encoder->base.name);
3629eddb4afcSVille Syrjälä 		crtc_state->uapi.mode_changed = true;
3630eddb4afcSVille Syrjälä 		fastset = false;
3631eddb4afcSVille Syrjälä 	}
3632eddb4afcSVille Syrjälä 
3633eddb4afcSVille Syrjälä 	if (intel_crtc_has_dp_encoder(crtc_state) &&
3634eddb4afcSVille Syrjälä 	    !intel_dp_initial_fastset_check(encoder, crtc_state))
3635eddb4afcSVille Syrjälä 		fastset = false;
3636eddb4afcSVille Syrjälä 
3637eddb4afcSVille Syrjälä 	return fastset;
3638b671d6efSImre Deak }
3639b671d6efSImre Deak 
3640379bc100SJani Nikula static enum intel_output_type
3641379bc100SJani Nikula intel_ddi_compute_output_type(struct intel_encoder *encoder,
3642379bc100SJani Nikula 			      struct intel_crtc_state *crtc_state,
3643379bc100SJani Nikula 			      struct drm_connector_state *conn_state)
3644379bc100SJani Nikula {
3645379bc100SJani Nikula 	switch (conn_state->connector->connector_type) {
3646379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_HDMIA:
3647379bc100SJani Nikula 		return INTEL_OUTPUT_HDMI;
3648379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_eDP:
3649379bc100SJani Nikula 		return INTEL_OUTPUT_EDP;
3650379bc100SJani Nikula 	case DRM_MODE_CONNECTOR_DisplayPort:
3651379bc100SJani Nikula 		return INTEL_OUTPUT_DP;
3652379bc100SJani Nikula 	default:
3653379bc100SJani Nikula 		MISSING_CASE(conn_state->connector->connector_type);
3654379bc100SJani Nikula 		return INTEL_OUTPUT_UNUSED;
3655379bc100SJani Nikula 	}
3656379bc100SJani Nikula }
3657379bc100SJani Nikula 
3658379bc100SJani Nikula static int intel_ddi_compute_config(struct intel_encoder *encoder,
3659379bc100SJani Nikula 				    struct intel_crtc_state *pipe_config,
3660379bc100SJani Nikula 				    struct drm_connector_state *conn_state)
3661379bc100SJani Nikula {
36622225f3c6SMaarten Lankhorst 	struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
3663379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3664379bc100SJani Nikula 	enum port port = encoder->port;
3665379bc100SJani Nikula 	int ret;
3666379bc100SJani Nikula 
366710cf8e75SVille Syrjälä 	if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
3668379bc100SJani Nikula 		pipe_config->cpu_transcoder = TRANSCODER_EDP;
3669379bc100SJani Nikula 
3670bdacf087SAnshuman Gupta 	if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
3671379bc100SJani Nikula 		ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
3672bdacf087SAnshuman Gupta 	} else {
3673379bc100SJani Nikula 		ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
3674bdacf087SAnshuman Gupta 	}
3675bdacf087SAnshuman Gupta 
3676379bc100SJani Nikula 	if (ret)
3677379bc100SJani Nikula 		return ret;
3678379bc100SJani Nikula 
3679379bc100SJani Nikula 	if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A &&
3680379bc100SJani Nikula 	    pipe_config->cpu_transcoder == TRANSCODER_EDP)
3681379bc100SJani Nikula 		pipe_config->pch_pfit.force_thru =
3682379bc100SJani Nikula 			pipe_config->pch_pfit.enabled ||
3683379bc100SJani Nikula 			pipe_config->crc_enabled;
3684379bc100SJani Nikula 
36852446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3686379bc100SJani Nikula 		pipe_config->lane_lat_optim_mask =
3687379bc100SJani Nikula 			bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
3688379bc100SJani Nikula 
3689379bc100SJani Nikula 	intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
3690379bc100SJani Nikula 
3691379bc100SJani Nikula 	return 0;
3692379bc100SJani Nikula }
3693379bc100SJani Nikula 
3694b50a1aa6SManasi Navare static bool mode_equal(const struct drm_display_mode *mode1,
3695b50a1aa6SManasi Navare 		       const struct drm_display_mode *mode2)
3696b50a1aa6SManasi Navare {
3697b50a1aa6SManasi Navare 	return drm_mode_match(mode1, mode2,
3698b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_TIMINGS |
3699b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_FLAGS |
3700b50a1aa6SManasi Navare 			      DRM_MODE_MATCH_3D_FLAGS) &&
3701b50a1aa6SManasi Navare 		mode1->clock == mode2->clock; /* we want an exact match */
3702b50a1aa6SManasi Navare }
3703b50a1aa6SManasi Navare 
3704b50a1aa6SManasi Navare static bool m_n_equal(const struct intel_link_m_n *m_n_1,
3705b50a1aa6SManasi Navare 		      const struct intel_link_m_n *m_n_2)
3706b50a1aa6SManasi Navare {
3707b50a1aa6SManasi Navare 	return m_n_1->tu == m_n_2->tu &&
37085f721a5dSVille Syrjälä 		m_n_1->data_m == m_n_2->data_m &&
37095f721a5dSVille Syrjälä 		m_n_1->data_n == m_n_2->data_n &&
3710b50a1aa6SManasi Navare 		m_n_1->link_m == m_n_2->link_m &&
3711b50a1aa6SManasi Navare 		m_n_1->link_n == m_n_2->link_n;
3712b50a1aa6SManasi Navare }
3713b50a1aa6SManasi Navare 
3714b50a1aa6SManasi Navare static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
3715b50a1aa6SManasi Navare 				       const struct intel_crtc_state *crtc_state2)
3716b50a1aa6SManasi Navare {
3717b50a1aa6SManasi Navare 	return crtc_state1->hw.active && crtc_state2->hw.active &&
3718b50a1aa6SManasi Navare 		crtc_state1->output_types == crtc_state2->output_types &&
3719b50a1aa6SManasi Navare 		crtc_state1->output_format == crtc_state2->output_format &&
3720b50a1aa6SManasi Navare 		crtc_state1->lane_count == crtc_state2->lane_count &&
3721b50a1aa6SManasi Navare 		crtc_state1->port_clock == crtc_state2->port_clock &&
3722b50a1aa6SManasi Navare 		mode_equal(&crtc_state1->hw.adjusted_mode,
3723b50a1aa6SManasi Navare 			   &crtc_state2->hw.adjusted_mode) &&
3724b50a1aa6SManasi Navare 		m_n_equal(&crtc_state1->dp_m_n, &crtc_state2->dp_m_n);
3725b50a1aa6SManasi Navare }
3726b50a1aa6SManasi Navare 
3727b50a1aa6SManasi Navare static u8
3728b50a1aa6SManasi Navare intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state,
3729b50a1aa6SManasi Navare 				int tile_group_id)
3730b50a1aa6SManasi Navare {
3731b50a1aa6SManasi Navare 	struct drm_connector *connector;
3732b50a1aa6SManasi Navare 	const struct drm_connector_state *conn_state;
3733b50a1aa6SManasi Navare 	struct drm_i915_private *dev_priv = to_i915(ref_crtc_state->uapi.crtc->dev);
3734b50a1aa6SManasi Navare 	struct intel_atomic_state *state =
3735b50a1aa6SManasi Navare 		to_intel_atomic_state(ref_crtc_state->uapi.state);
3736b50a1aa6SManasi Navare 	u8 transcoders = 0;
3737b50a1aa6SManasi Navare 	int i;
3738b50a1aa6SManasi Navare 
3739dc5b8ed5SVille Syrjälä 	/*
3740dc5b8ed5SVille Syrjälä 	 * We don't enable port sync on BDW due to missing w/as and
3741dc5b8ed5SVille Syrjälä 	 * due to not having adjusted the modeset sequence appropriately.
3742dc5b8ed5SVille Syrjälä 	 */
3743005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) < 9)
3744b50a1aa6SManasi Navare 		return 0;
3745b50a1aa6SManasi Navare 
3746b50a1aa6SManasi Navare 	if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP))
3747b50a1aa6SManasi Navare 		return 0;
3748b50a1aa6SManasi Navare 
3749b50a1aa6SManasi Navare 	for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
3750b50a1aa6SManasi Navare 		struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
3751b50a1aa6SManasi Navare 		const struct intel_crtc_state *crtc_state;
3752b50a1aa6SManasi Navare 
3753b50a1aa6SManasi Navare 		if (!crtc)
3754b50a1aa6SManasi Navare 			continue;
3755b50a1aa6SManasi Navare 
3756b50a1aa6SManasi Navare 		if (!connector->has_tile ||
3757b50a1aa6SManasi Navare 		    connector->tile_group->id !=
3758b50a1aa6SManasi Navare 		    tile_group_id)
3759b50a1aa6SManasi Navare 			continue;
3760b50a1aa6SManasi Navare 		crtc_state = intel_atomic_get_new_crtc_state(state,
3761b50a1aa6SManasi Navare 							     crtc);
3762b50a1aa6SManasi Navare 		if (!crtcs_port_sync_compatible(ref_crtc_state,
3763b50a1aa6SManasi Navare 						crtc_state))
3764b50a1aa6SManasi Navare 			continue;
3765b50a1aa6SManasi Navare 		transcoders |= BIT(crtc_state->cpu_transcoder);
3766b50a1aa6SManasi Navare 	}
3767b50a1aa6SManasi Navare 
3768b50a1aa6SManasi Navare 	return transcoders;
3769b50a1aa6SManasi Navare }
3770b50a1aa6SManasi Navare 
3771b50a1aa6SManasi Navare static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
3772b50a1aa6SManasi Navare 					 struct intel_crtc_state *crtc_state,
3773b50a1aa6SManasi Navare 					 struct drm_connector_state *conn_state)
3774b50a1aa6SManasi Navare {
377547bdb1caSJani Nikula 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3776b50a1aa6SManasi Navare 	struct drm_connector *connector = conn_state->connector;
3777b50a1aa6SManasi Navare 	u8 port_sync_transcoders = 0;
3778b50a1aa6SManasi Navare 
377947bdb1caSJani Nikula 	drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]",
3780b50a1aa6SManasi Navare 		    encoder->base.base.id, encoder->base.name,
3781b50a1aa6SManasi Navare 		    crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
3782b50a1aa6SManasi Navare 
3783b50a1aa6SManasi Navare 	if (connector->has_tile)
3784b50a1aa6SManasi Navare 		port_sync_transcoders = intel_ddi_port_sync_transcoders(crtc_state,
3785b50a1aa6SManasi Navare 									connector->tile_group->id);
3786b50a1aa6SManasi Navare 
3787b50a1aa6SManasi Navare 	/*
3788b50a1aa6SManasi Navare 	 * EDP Transcoders cannot be ensalved
3789b50a1aa6SManasi Navare 	 * make them a master always when present
3790b50a1aa6SManasi Navare 	 */
3791b50a1aa6SManasi Navare 	if (port_sync_transcoders & BIT(TRANSCODER_EDP))
3792b50a1aa6SManasi Navare 		crtc_state->master_transcoder = TRANSCODER_EDP;
3793b50a1aa6SManasi Navare 	else
3794b50a1aa6SManasi Navare 		crtc_state->master_transcoder = ffs(port_sync_transcoders) - 1;
3795b50a1aa6SManasi Navare 
3796b50a1aa6SManasi Navare 	if (crtc_state->master_transcoder == crtc_state->cpu_transcoder) {
3797b50a1aa6SManasi Navare 		crtc_state->master_transcoder = INVALID_TRANSCODER;
3798b50a1aa6SManasi Navare 		crtc_state->sync_mode_slaves_mask =
3799b50a1aa6SManasi Navare 			port_sync_transcoders & ~BIT(crtc_state->cpu_transcoder);
3800b50a1aa6SManasi Navare 	}
3801b50a1aa6SManasi Navare 
3802b50a1aa6SManasi Navare 	return 0;
3803b50a1aa6SManasi Navare }
3804b50a1aa6SManasi Navare 
3805379bc100SJani Nikula static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
3806379bc100SJani Nikula {
38074a300e65SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->dev);
3808b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
38093e0abc76SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
3810379bc100SJani Nikula 
3811379bc100SJani Nikula 	intel_dp_encoder_flush_work(encoder);
38123e0abc76SImre Deak 	if (intel_phy_is_tc(i915, phy))
38133e0abc76SImre Deak 		intel_tc_port_flush_work(dig_port);
38144a300e65SImre Deak 	intel_display_power_flush_work(i915);
3815379bc100SJani Nikula 
3816379bc100SJani Nikula 	drm_encoder_cleanup(encoder);
3817a6c6eac9SAnshuman Gupta 	kfree(dig_port->hdcp_port_data.streams);
3818379bc100SJani Nikula 	kfree(dig_port);
3819379bc100SJani Nikula }
3820379bc100SJani Nikula 
3821764f6729SVille Syrjälä static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
3822764f6729SVille Syrjälä {
3823a82796a2SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->dev);
3824764f6729SVille Syrjälä 	struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
3825a82796a2SImre Deak 	struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
3826a82796a2SImre Deak 	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
3827764f6729SVille Syrjälä 
3828764f6729SVille Syrjälä 	intel_dp->reset_link_params = true;
3829764f6729SVille Syrjälä 
3830764f6729SVille Syrjälä 	intel_pps_encoder_reset(intel_dp);
3831a82796a2SImre Deak 
3832a82796a2SImre Deak 	if (intel_phy_is_tc(i915, phy))
3833a82796a2SImre Deak 		intel_tc_port_init_mode(dig_port);
3834764f6729SVille Syrjälä }
3835764f6729SVille Syrjälä 
3836379bc100SJani Nikula static const struct drm_encoder_funcs intel_ddi_funcs = {
3837764f6729SVille Syrjälä 	.reset = intel_ddi_encoder_reset,
3838379bc100SJani Nikula 	.destroy = intel_ddi_encoder_destroy,
3839379bc100SJani Nikula };
3840379bc100SJani Nikula 
3841379bc100SJani Nikula static struct intel_connector *
38427801f3b7SLucas De Marchi intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
3843379bc100SJani Nikula {
3844379bc100SJani Nikula 	struct intel_connector *connector;
38457801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
3846379bc100SJani Nikula 
3847379bc100SJani Nikula 	connector = intel_connector_alloc();
3848379bc100SJani Nikula 	if (!connector)
3849379bc100SJani Nikula 		return NULL;
3850379bc100SJani Nikula 
38517801f3b7SLucas De Marchi 	dig_port->dp.output_reg = DDI_BUF_CTL(port);
38527801f3b7SLucas De Marchi 	dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain;
38537801f3b7SLucas De Marchi 	dig_port->dp.set_link_train = intel_ddi_set_link_train;
38547801f3b7SLucas De Marchi 	dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train;
3855eee3f911SVille Syrjälä 
38567801f3b7SLucas De Marchi 	dig_port->dp.voltage_max = intel_ddi_dp_voltage_max;
38577801f3b7SLucas De Marchi 	dig_port->dp.preemph_max = intel_ddi_dp_preemph_max;
385853de0a20SVille Syrjälä 
38597801f3b7SLucas De Marchi 	if (!intel_dp_init_connector(dig_port, connector)) {
3860379bc100SJani Nikula 		kfree(connector);
3861379bc100SJani Nikula 		return NULL;
3862379bc100SJani Nikula 	}
3863379bc100SJani Nikula 
38646306d8dbSHans de Goede 	if (dig_port->base.type == INTEL_OUTPUT_EDP) {
38656306d8dbSHans de Goede 		struct drm_device *dev = dig_port->base.base.dev;
38666306d8dbSHans de Goede 		struct drm_privacy_screen *privacy_screen;
38676306d8dbSHans de Goede 
38686306d8dbSHans de Goede 		privacy_screen = drm_privacy_screen_get(dev->dev, NULL);
38696306d8dbSHans de Goede 		if (!IS_ERR(privacy_screen)) {
38706306d8dbSHans de Goede 			drm_connector_attach_privacy_screen_provider(&connector->base,
38716306d8dbSHans de Goede 								     privacy_screen);
38726306d8dbSHans de Goede 		} else if (PTR_ERR(privacy_screen) != -ENODEV) {
38736306d8dbSHans de Goede 			drm_warn(dev, "Error getting privacy-screen\n");
38746306d8dbSHans de Goede 		}
38756306d8dbSHans de Goede 	}
38766306d8dbSHans de Goede 
3877379bc100SJani Nikula 	return connector;
3878379bc100SJani Nikula }
3879379bc100SJani Nikula 
3880379bc100SJani Nikula static int modeset_pipe(struct drm_crtc *crtc,
3881379bc100SJani Nikula 			struct drm_modeset_acquire_ctx *ctx)
3882379bc100SJani Nikula {
3883379bc100SJani Nikula 	struct drm_atomic_state *state;
3884379bc100SJani Nikula 	struct drm_crtc_state *crtc_state;
3885379bc100SJani Nikula 	int ret;
3886379bc100SJani Nikula 
3887379bc100SJani Nikula 	state = drm_atomic_state_alloc(crtc->dev);
3888379bc100SJani Nikula 	if (!state)
3889379bc100SJani Nikula 		return -ENOMEM;
3890379bc100SJani Nikula 
3891379bc100SJani Nikula 	state->acquire_ctx = ctx;
3892379bc100SJani Nikula 
3893379bc100SJani Nikula 	crtc_state = drm_atomic_get_crtc_state(state, crtc);
3894379bc100SJani Nikula 	if (IS_ERR(crtc_state)) {
3895379bc100SJani Nikula 		ret = PTR_ERR(crtc_state);
3896379bc100SJani Nikula 		goto out;
3897379bc100SJani Nikula 	}
3898379bc100SJani Nikula 
3899379bc100SJani Nikula 	crtc_state->connectors_changed = true;
3900379bc100SJani Nikula 
3901379bc100SJani Nikula 	ret = drm_atomic_commit(state);
3902379bc100SJani Nikula out:
3903379bc100SJani Nikula 	drm_atomic_state_put(state);
3904379bc100SJani Nikula 
3905379bc100SJani Nikula 	return ret;
3906379bc100SJani Nikula }
3907379bc100SJani Nikula 
3908379bc100SJani Nikula static int intel_hdmi_reset_link(struct intel_encoder *encoder,
3909379bc100SJani Nikula 				 struct drm_modeset_acquire_ctx *ctx)
3910379bc100SJani Nikula {
3911379bc100SJani Nikula 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3912b7d02c3aSVille Syrjälä 	struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
3913379bc100SJani Nikula 	struct intel_connector *connector = hdmi->attached_connector;
3914379bc100SJani Nikula 	struct i2c_adapter *adapter =
3915379bc100SJani Nikula 		intel_gmbus_get_adapter(dev_priv, hdmi->ddc_bus);
3916379bc100SJani Nikula 	struct drm_connector_state *conn_state;
3917379bc100SJani Nikula 	struct intel_crtc_state *crtc_state;
3918379bc100SJani Nikula 	struct intel_crtc *crtc;
3919379bc100SJani Nikula 	u8 config;
3920379bc100SJani Nikula 	int ret;
3921379bc100SJani Nikula 
3922379bc100SJani Nikula 	if (!connector || connector->base.status != connector_status_connected)
3923379bc100SJani Nikula 		return 0;
3924379bc100SJani Nikula 
3925379bc100SJani Nikula 	ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex,
3926379bc100SJani Nikula 			       ctx);
3927379bc100SJani Nikula 	if (ret)
3928379bc100SJani Nikula 		return ret;
3929379bc100SJani Nikula 
3930379bc100SJani Nikula 	conn_state = connector->base.state;
3931379bc100SJani Nikula 
3932379bc100SJani Nikula 	crtc = to_intel_crtc(conn_state->crtc);
3933379bc100SJani Nikula 	if (!crtc)
3934379bc100SJani Nikula 		return 0;
3935379bc100SJani Nikula 
3936379bc100SJani Nikula 	ret = drm_modeset_lock(&crtc->base.mutex, ctx);
3937379bc100SJani Nikula 	if (ret)
3938379bc100SJani Nikula 		return ret;
3939379bc100SJani Nikula 
3940379bc100SJani Nikula 	crtc_state = to_intel_crtc_state(crtc->base.state);
3941379bc100SJani Nikula 
39421de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm,
39431de143ccSPankaj Bharadiya 		    !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI));
3944379bc100SJani Nikula 
39451326a92cSMaarten Lankhorst 	if (!crtc_state->hw.active)
3946379bc100SJani Nikula 		return 0;
3947379bc100SJani Nikula 
3948379bc100SJani Nikula 	if (!crtc_state->hdmi_high_tmds_clock_ratio &&
3949379bc100SJani Nikula 	    !crtc_state->hdmi_scrambling)
3950379bc100SJani Nikula 		return 0;
3951379bc100SJani Nikula 
3952379bc100SJani Nikula 	if (conn_state->commit &&
3953379bc100SJani Nikula 	    !try_wait_for_completion(&conn_state->commit->hw_done))
3954379bc100SJani Nikula 		return 0;
3955379bc100SJani Nikula 
3956379bc100SJani Nikula 	ret = drm_scdc_readb(adapter, SCDC_TMDS_CONFIG, &config);
3957379bc100SJani Nikula 	if (ret < 0) {
395847bdb1caSJani Nikula 		drm_err(&dev_priv->drm, "Failed to read TMDS config: %d\n",
395947bdb1caSJani Nikula 			ret);
3960379bc100SJani Nikula 		return 0;
3961379bc100SJani Nikula 	}
3962379bc100SJani Nikula 
3963379bc100SJani Nikula 	if (!!(config & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) ==
3964379bc100SJani Nikula 	    crtc_state->hdmi_high_tmds_clock_ratio &&
3965379bc100SJani Nikula 	    !!(config & SCDC_SCRAMBLING_ENABLE) ==
3966379bc100SJani Nikula 	    crtc_state->hdmi_scrambling)
3967379bc100SJani Nikula 		return 0;
3968379bc100SJani Nikula 
3969379bc100SJani Nikula 	/*
3970379bc100SJani Nikula 	 * HDMI 2.0 says that one should not send scrambled data
3971379bc100SJani Nikula 	 * prior to configuring the sink scrambling, and that
3972379bc100SJani Nikula 	 * TMDS clock/data transmission should be suspended when
3973379bc100SJani Nikula 	 * changing the TMDS clock rate in the sink. So let's
3974379bc100SJani Nikula 	 * just do a full modeset here, even though some sinks
3975379bc100SJani Nikula 	 * would be perfectly happy if were to just reconfigure
3976379bc100SJani Nikula 	 * the SCDC settings on the fly.
3977379bc100SJani Nikula 	 */
3978379bc100SJani Nikula 	return modeset_pipe(&crtc->base, ctx);
3979379bc100SJani Nikula }
3980379bc100SJani Nikula 
39813944709dSImre Deak static enum intel_hotplug_state
39823944709dSImre Deak intel_ddi_hotplug(struct intel_encoder *encoder,
39838c8919c7SImre Deak 		  struct intel_connector *connector)
3984379bc100SJani Nikula {
3985b4df5405SImre Deak 	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3986b7d02c3aSVille Syrjälä 	struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3987699390f7SVille Syrjälä 	struct intel_dp *intel_dp = &dig_port->dp;
3988b4df5405SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
3989b4df5405SImre Deak 	bool is_tc = intel_phy_is_tc(i915, phy);
3990379bc100SJani Nikula 	struct drm_modeset_acquire_ctx ctx;
39913944709dSImre Deak 	enum intel_hotplug_state state;
3992379bc100SJani Nikula 	int ret;
3993379bc100SJani Nikula 
3994699390f7SVille Syrjälä 	if (intel_dp->compliance.test_active &&
3995699390f7SVille Syrjälä 	    intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
3996699390f7SVille Syrjälä 		intel_dp_phy_test(encoder);
3997699390f7SVille Syrjälä 		/* just do the PHY test and nothing else */
3998699390f7SVille Syrjälä 		return INTEL_HOTPLUG_UNCHANGED;
3999699390f7SVille Syrjälä 	}
4000699390f7SVille Syrjälä 
40018c8919c7SImre Deak 	state = intel_encoder_hotplug(encoder, connector);
4002379bc100SJani Nikula 
4003379bc100SJani Nikula 	drm_modeset_acquire_init(&ctx, 0);
4004379bc100SJani Nikula 
4005379bc100SJani Nikula 	for (;;) {
4006379bc100SJani Nikula 		if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA)
4007379bc100SJani Nikula 			ret = intel_hdmi_reset_link(encoder, &ctx);
4008379bc100SJani Nikula 		else
4009379bc100SJani Nikula 			ret = intel_dp_retrain_link(encoder, &ctx);
4010379bc100SJani Nikula 
4011379bc100SJani Nikula 		if (ret == -EDEADLK) {
4012379bc100SJani Nikula 			drm_modeset_backoff(&ctx);
4013379bc100SJani Nikula 			continue;
4014379bc100SJani Nikula 		}
4015379bc100SJani Nikula 
4016379bc100SJani Nikula 		break;
4017379bc100SJani Nikula 	}
4018379bc100SJani Nikula 
4019379bc100SJani Nikula 	drm_modeset_drop_locks(&ctx);
4020379bc100SJani Nikula 	drm_modeset_acquire_fini(&ctx);
40213a47ae20SPankaj Bharadiya 	drm_WARN(encoder->base.dev, ret,
40223a47ae20SPankaj Bharadiya 		 "Acquiring modeset locks failed with %i\n", ret);
4023379bc100SJani Nikula 
4024bb80c925SJosé Roberto de Souza 	/*
4025bb80c925SJosé Roberto de Souza 	 * Unpowered type-c dongles can take some time to boot and be
4026bb80c925SJosé Roberto de Souza 	 * responsible, so here giving some time to those dongles to power up
4027bb80c925SJosé Roberto de Souza 	 * and then retrying the probe.
4028bb80c925SJosé Roberto de Souza 	 *
4029bb80c925SJosé Roberto de Souza 	 * On many platforms the HDMI live state signal is known to be
4030bb80c925SJosé Roberto de Souza 	 * unreliable, so we can't use it to detect if a sink is connected or
4031bb80c925SJosé Roberto de Souza 	 * not. Instead we detect if it's connected based on whether we can
4032bb80c925SJosé Roberto de Souza 	 * read the EDID or not. That in turn has a problem during disconnect,
4033bb80c925SJosé Roberto de Souza 	 * since the HPD interrupt may be raised before the DDC lines get
4034bb80c925SJosé Roberto de Souza 	 * disconnected (due to how the required length of DDC vs. HPD
4035bb80c925SJosé Roberto de Souza 	 * connector pins are specified) and so we'll still be able to get a
4036bb80c925SJosé Roberto de Souza 	 * valid EDID. To solve this schedule another detection cycle if this
4037bb80c925SJosé Roberto de Souza 	 * time around we didn't detect any change in the sink's connection
4038bb80c925SJosé Roberto de Souza 	 * status.
4039b4df5405SImre Deak 	 *
4040b4df5405SImre Deak 	 * Type-c connectors which get their HPD signal deasserted then
4041b4df5405SImre Deak 	 * reasserted, without unplugging/replugging the sink from the
4042b4df5405SImre Deak 	 * connector, introduce a delay until the AUX channel communication
4043b4df5405SImre Deak 	 * becomes functional. Retry the detection for 5 seconds on type-c
4044b4df5405SImre Deak 	 * connectors to account for this delay.
4045bb80c925SJosé Roberto de Souza 	 */
4046b4df5405SImre Deak 	if (state == INTEL_HOTPLUG_UNCHANGED &&
4047b4df5405SImre Deak 	    connector->hotplug_retries < (is_tc ? 5 : 1) &&
4048bb80c925SJosé Roberto de Souza 	    !dig_port->dp.is_mst)
4049bb80c925SJosé Roberto de Souza 		state = INTEL_HOTPLUG_RETRY;
4050bb80c925SJosé Roberto de Souza 
40513944709dSImre Deak 	return state;
4052379bc100SJani Nikula }
4053379bc100SJani Nikula 
4054edc0e09cSVille Syrjälä static bool lpt_digital_port_connected(struct intel_encoder *encoder)
4055edc0e09cSVille Syrjälä {
4056edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
40575a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin];
4058edc0e09cSVille Syrjälä 
4059edc0e09cSVille Syrjälä 	return intel_de_read(dev_priv, SDEISR) & bit;
4060edc0e09cSVille Syrjälä }
4061edc0e09cSVille Syrjälä 
4062edc0e09cSVille Syrjälä static bool hsw_digital_port_connected(struct intel_encoder *encoder)
4063edc0e09cSVille Syrjälä {
4064edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
40655a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4066edc0e09cSVille Syrjälä 
4067c7e8a3d6SVille Syrjälä 	return intel_de_read(dev_priv, DEISR) & bit;
4068edc0e09cSVille Syrjälä }
4069edc0e09cSVille Syrjälä 
4070edc0e09cSVille Syrjälä static bool bdw_digital_port_connected(struct intel_encoder *encoder)
4071edc0e09cSVille Syrjälä {
4072edc0e09cSVille Syrjälä 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
40735a4dd6f0SJani Nikula 	u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4074edc0e09cSVille Syrjälä 
4075edc0e09cSVille Syrjälä 	return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit;
4076edc0e09cSVille Syrjälä }
4077edc0e09cSVille Syrjälä 
4078379bc100SJani Nikula static struct intel_connector *
40797801f3b7SLucas De Marchi intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port)
4080379bc100SJani Nikula {
4081379bc100SJani Nikula 	struct intel_connector *connector;
40827801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4083379bc100SJani Nikula 
4084379bc100SJani Nikula 	connector = intel_connector_alloc();
4085379bc100SJani Nikula 	if (!connector)
4086379bc100SJani Nikula 		return NULL;
4087379bc100SJani Nikula 
40887801f3b7SLucas De Marchi 	dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
40897801f3b7SLucas De Marchi 	intel_hdmi_init_connector(dig_port, connector);
4090379bc100SJani Nikula 
4091379bc100SJani Nikula 	return connector;
4092379bc100SJani Nikula }
4093379bc100SJani Nikula 
40947801f3b7SLucas De Marchi static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
4095379bc100SJani Nikula {
40967801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
4097379bc100SJani Nikula 
40987801f3b7SLucas De Marchi 	if (dig_port->base.port != PORT_A)
4099379bc100SJani Nikula 		return false;
4100379bc100SJani Nikula 
41017801f3b7SLucas De Marchi 	if (dig_port->saved_port_bits & DDI_A_4_LANES)
4102379bc100SJani Nikula 		return false;
4103379bc100SJani Nikula 
4104379bc100SJani Nikula 	/* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
4105379bc100SJani Nikula 	 *                     supported configuration
4106379bc100SJani Nikula 	 */
41072446e1d6SMatt Roper 	if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4108379bc100SJani Nikula 		return true;
4109379bc100SJani Nikula 
4110379bc100SJani Nikula 	return false;
4111379bc100SJani Nikula }
4112379bc100SJani Nikula 
4113379bc100SJani Nikula static int
41147801f3b7SLucas De Marchi intel_ddi_max_lanes(struct intel_digital_port *dig_port)
4115379bc100SJani Nikula {
41167801f3b7SLucas De Marchi 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
41177801f3b7SLucas De Marchi 	enum port port = dig_port->base.port;
4118379bc100SJani Nikula 	int max_lanes = 4;
4119379bc100SJani Nikula 
4120005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
4121379bc100SJani Nikula 		return max_lanes;
4122379bc100SJani Nikula 
4123379bc100SJani Nikula 	if (port == PORT_A || port == PORT_E) {
4124f7960e7fSJani Nikula 		if (intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
4125379bc100SJani Nikula 			max_lanes = port == PORT_A ? 4 : 0;
4126379bc100SJani Nikula 		else
4127379bc100SJani Nikula 			/* Both A and E share 2 lanes */
4128379bc100SJani Nikula 			max_lanes = 2;
4129379bc100SJani Nikula 	}
4130379bc100SJani Nikula 
4131379bc100SJani Nikula 	/*
4132379bc100SJani Nikula 	 * Some BIOS might fail to set this bit on port A if eDP
4133379bc100SJani Nikula 	 * wasn't lit up at boot.  Force this bit set when needed
4134379bc100SJani Nikula 	 * so we use the proper lane count for our calculations.
4135379bc100SJani Nikula 	 */
41367801f3b7SLucas De Marchi 	if (intel_ddi_a_force_4_lanes(dig_port)) {
413747bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
413847bdb1caSJani Nikula 			    "Forcing DDI_A_4_LANES for port A\n");
41397801f3b7SLucas De Marchi 		dig_port->saved_port_bits |= DDI_A_4_LANES;
4140379bc100SJani Nikula 		max_lanes = 4;
4141379bc100SJani Nikula 	}
4142379bc100SJani Nikula 
4143379bc100SJani Nikula 	return max_lanes;
4144379bc100SJani Nikula }
4145379bc100SJani Nikula 
4146ed2615a8SMatt Roper static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv,
4147ed2615a8SMatt Roper 				  enum port port)
4148ed2615a8SMatt Roper {
4149ed2615a8SMatt Roper 	if (port >= PORT_D_XELPD)
4150ed2615a8SMatt Roper 		return HPD_PORT_D + port - PORT_D_XELPD;
4151ed2615a8SMatt Roper 	else if (port >= PORT_TC1)
4152ed2615a8SMatt Roper 		return HPD_PORT_TC1 + port - PORT_TC1;
4153ed2615a8SMatt Roper 	else
4154ed2615a8SMatt Roper 		return HPD_PORT_A + port - PORT_A;
4155ed2615a8SMatt Roper }
4156ed2615a8SMatt Roper 
4157229f31e2SLucas De Marchi static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv,
4158229f31e2SLucas De Marchi 				enum port port)
4159229f31e2SLucas De Marchi {
41601d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
41611d8ca002SVille Syrjälä 		return HPD_PORT_C + port - PORT_TC1;
4162229f31e2SLucas De Marchi 	else
4163229f31e2SLucas De Marchi 		return HPD_PORT_A + port - PORT_A;
4164229f31e2SLucas De Marchi }
4165229f31e2SLucas De Marchi 
4166da51e4baSVille Syrjälä static enum hpd_pin tgl_hpd_pin(struct drm_i915_private *dev_priv,
4167da51e4baSVille Syrjälä 				enum port port)
4168da51e4baSVille Syrjälä {
41691d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
41701d8ca002SVille Syrjälä 		return HPD_PORT_TC1 + port - PORT_TC1;
4171da51e4baSVille Syrjälä 	else
4172da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4173da51e4baSVille Syrjälä }
4174da51e4baSVille Syrjälä 
4175da51e4baSVille Syrjälä static enum hpd_pin rkl_hpd_pin(struct drm_i915_private *dev_priv,
4176da51e4baSVille Syrjälä 				enum port port)
4177da51e4baSVille Syrjälä {
4178da51e4baSVille Syrjälä 	if (HAS_PCH_TGP(dev_priv))
4179da51e4baSVille Syrjälä 		return tgl_hpd_pin(dev_priv, port);
4180da51e4baSVille Syrjälä 
41811d8ca002SVille Syrjälä 	if (port >= PORT_TC1)
41821d8ca002SVille Syrjälä 		return HPD_PORT_C + port - PORT_TC1;
4183da51e4baSVille Syrjälä 	else
4184da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4185da51e4baSVille Syrjälä }
4186da51e4baSVille Syrjälä 
4187da51e4baSVille Syrjälä static enum hpd_pin icl_hpd_pin(struct drm_i915_private *dev_priv,
4188da51e4baSVille Syrjälä 				enum port port)
4189da51e4baSVille Syrjälä {
4190da51e4baSVille Syrjälä 	if (port >= PORT_C)
4191da51e4baSVille Syrjälä 		return HPD_PORT_TC1 + port - PORT_C;
4192da51e4baSVille Syrjälä 	else
4193da51e4baSVille Syrjälä 		return HPD_PORT_A + port - PORT_A;
4194da51e4baSVille Syrjälä }
4195da51e4baSVille Syrjälä 
4196da51e4baSVille Syrjälä static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv,
4197da51e4baSVille Syrjälä 				enum port port)
4198da51e4baSVille Syrjälä {
4199da51e4baSVille Syrjälä 	if (port == PORT_D)
4200da51e4baSVille Syrjälä 		return HPD_PORT_A;
4201da51e4baSVille Syrjälä 
4202f24d1d45SVille Syrjälä 	if (HAS_PCH_TGP(dev_priv))
4203da51e4baSVille Syrjälä 		return icl_hpd_pin(dev_priv, port);
4204da51e4baSVille Syrjälä 
4205da51e4baSVille Syrjälä 	return HPD_PORT_A + port - PORT_A;
4206da51e4baSVille Syrjälä }
4207da51e4baSVille Syrjälä 
4208c8455098SLyude Paul static enum hpd_pin skl_hpd_pin(struct drm_i915_private *dev_priv, enum port port)
4209c8455098SLyude Paul {
4210c8455098SLyude Paul 	if (HAS_PCH_TGP(dev_priv))
4211c8455098SLyude Paul 		return icl_hpd_pin(dev_priv, port);
4212c8455098SLyude Paul 
4213c8455098SLyude Paul 	return HPD_PORT_A + port - PORT_A;
4214c8455098SLyude Paul }
4215c8455098SLyude Paul 
421636ecb0ecSVille Syrjälä static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port)
421736ecb0ecSVille Syrjälä {
4218005e9537SMatt Roper 	if (DISPLAY_VER(i915) >= 12)
421936ecb0ecSVille Syrjälä 		return port >= PORT_TC1;
4220005e9537SMatt Roper 	else if (DISPLAY_VER(i915) >= 11)
422136ecb0ecSVille Syrjälä 		return port >= PORT_C;
422236ecb0ecSVille Syrjälä 	else
422336ecb0ecSVille Syrjälä 		return false;
422436ecb0ecSVille Syrjälä }
422536ecb0ecSVille Syrjälä 
4226151ec347SImre Deak static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
4227151ec347SImre Deak {
4228151ec347SImre Deak 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4229151ec347SImre Deak 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
4230151ec347SImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4231151ec347SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4232151ec347SImre Deak 
4233151ec347SImre Deak 	intel_dp_encoder_suspend(encoder);
4234151ec347SImre Deak 
4235151ec347SImre Deak 	if (!intel_phy_is_tc(i915, phy))
4236151ec347SImre Deak 		return;
4237151ec347SImre Deak 
42383e0abc76SImre Deak 	intel_tc_port_flush_work(dig_port);
4239151ec347SImre Deak }
4240151ec347SImre Deak 
4241151ec347SImre Deak static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
4242151ec347SImre Deak {
4243151ec347SImre Deak 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4244151ec347SImre Deak 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
4245151ec347SImre Deak 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4246151ec347SImre Deak 	enum phy phy = intel_port_to_phy(i915, encoder->port);
4247151ec347SImre Deak 
4248151ec347SImre Deak 	intel_dp_encoder_shutdown(encoder);
424949c55f7bSVille Syrjälä 	intel_hdmi_encoder_shutdown(encoder);
4250151ec347SImre Deak 
4251151ec347SImre Deak 	if (!intel_phy_is_tc(i915, phy))
4252151ec347SImre Deak 		return;
4253151ec347SImre Deak 
42543e0abc76SImre Deak 	intel_tc_port_flush_work(dig_port);
4255151ec347SImre Deak }
4256151ec347SImre Deak 
425783566d13SVille Syrjälä #define port_tc_name(port) ((port) - PORT_TC1 + '1')
425883566d13SVille Syrjälä #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1')
425983566d13SVille Syrjälä 
4260379bc100SJani Nikula void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
4261379bc100SJani Nikula {
42627801f3b7SLucas De Marchi 	struct intel_digital_port *dig_port;
426370dfbc29SLucas De Marchi 	struct intel_encoder *encoder;
426445c0673aSJani Nikula 	const struct intel_bios_encoder_data *devdata;
4265f542d671SKai-Heng Feng 	bool init_hdmi, init_dp;
4266d8fe2ab6SMatt Roper 	enum phy phy = intel_port_to_phy(dev_priv, port);
4267379bc100SJani Nikula 
4268ddff9a60SMatt Roper 	/*
4269ddff9a60SMatt Roper 	 * On platforms with HTI (aka HDPORT), if it's enabled at boot it may
4270ddff9a60SMatt Roper 	 * have taken over some of the PHYs and made them unavailable to the
4271ddff9a60SMatt Roper 	 * driver.  In that case we should skip initializing the corresponding
4272ddff9a60SMatt Roper 	 * outputs.
4273ddff9a60SMatt Roper 	 */
427403120fefSJani Nikula 	if (intel_hti_uses_phy(dev_priv, phy)) {
4275ddff9a60SMatt Roper 		drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n",
4276ddff9a60SMatt Roper 			    port_name(port), phy_name(phy));
4277ddff9a60SMatt Roper 		return;
4278ddff9a60SMatt Roper 	}
4279ddff9a60SMatt Roper 
428045c0673aSJani Nikula 	devdata = intel_bios_encoder_data_lookup(dev_priv, port);
428145c0673aSJani Nikula 	if (!devdata) {
428245c0673aSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
428345c0673aSJani Nikula 			    "VBT says port %c is not present\n",
428445c0673aSJani Nikula 			    port_name(port));
428545c0673aSJani Nikula 		return;
428645c0673aSJani Nikula 	}
428745c0673aSJani Nikula 
428845c0673aSJani Nikula 	init_hdmi = intel_bios_encoder_supports_dvi(devdata) ||
428945c0673aSJani Nikula 		intel_bios_encoder_supports_hdmi(devdata);
429045c0673aSJani Nikula 	init_dp = intel_bios_encoder_supports_dp(devdata);
4291379bc100SJani Nikula 
4292db5d650fSVille Syrjälä 	if (intel_bios_encoder_is_lspcon(devdata)) {
4293379bc100SJani Nikula 		/*
4294379bc100SJani Nikula 		 * Lspcon device needs to be driven with DP connector
4295379bc100SJani Nikula 		 * with special detection sequence. So make sure DP
4296379bc100SJani Nikula 		 * is initialized before lspcon.
4297379bc100SJani Nikula 		 */
4298379bc100SJani Nikula 		init_dp = true;
4299379bc100SJani Nikula 		init_hdmi = false;
430047bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm, "VBT says port %c has lspcon\n",
430147bdb1caSJani Nikula 			    port_name(port));
4302379bc100SJani Nikula 	}
4303379bc100SJani Nikula 
4304379bc100SJani Nikula 	if (!init_dp && !init_hdmi) {
430547bdb1caSJani Nikula 		drm_dbg_kms(&dev_priv->drm,
430647bdb1caSJani Nikula 			    "VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
4307379bc100SJani Nikula 			    port_name(port));
4308379bc100SJani Nikula 		return;
4309379bc100SJani Nikula 	}
4310379bc100SJani Nikula 
4311b4eb76d8SMatt Roper 	if (intel_phy_is_snps(dev_priv, phy) &&
43123a7e2d58SJani Nikula 	    dev_priv->display.snps.phy_failed_calibration & BIT(phy)) {
4313b4eb76d8SMatt Roper 		drm_dbg_kms(&dev_priv->drm,
431482c362f2SLucas De Marchi 			    "SNPS PHY %c failed to calibrate, proceeding anyway\n",
4315b4eb76d8SMatt Roper 			    phy_name(phy));
4316b4eb76d8SMatt Roper 	}
4317b4eb76d8SMatt Roper 
43187801f3b7SLucas De Marchi 	dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
43197801f3b7SLucas De Marchi 	if (!dig_port)
4320379bc100SJani Nikula 		return;
4321379bc100SJani Nikula 
43227801f3b7SLucas De Marchi 	encoder = &dig_port->base;
4323c0a950d1SJani Nikula 	encoder->devdata = devdata;
4324379bc100SJani Nikula 
4325ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) {
4326ed2615a8SMatt Roper 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
4327ed2615a8SMatt Roper 				 DRM_MODE_ENCODER_TMDS,
4328ed2615a8SMatt Roper 				 "DDI %c/PHY %c",
4329ed2615a8SMatt Roper 				 port_name(port - PORT_D_XELPD + PORT_D),
4330ed2615a8SMatt Roper 				 phy_name(phy));
4331ed2615a8SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 12) {
43322d709a5aSVille Syrjälä 		enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
43332d709a5aSVille Syrjälä 
433470dfbc29SLucas De Marchi 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
43352d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
43362d709a5aSVille Syrjälä 				 "DDI %s%c/PHY %s%c",
43372d709a5aSVille Syrjälä 				 port >= PORT_TC1 ? "TC" : "",
433883566d13SVille Syrjälä 				 port >= PORT_TC1 ? port_tc_name(port) : port_name(port),
43392d709a5aSVille Syrjälä 				 tc_port != TC_PORT_NONE ? "TC" : "",
434083566d13SVille Syrjälä 				 tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
4341005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
43422d709a5aSVille Syrjälä 		enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
43432d709a5aSVille Syrjälä 
43442d709a5aSVille Syrjälä 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
43452d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
43462d709a5aSVille Syrjälä 				 "DDI %c%s/PHY %s%c",
43472d709a5aSVille Syrjälä 				 port_name(port),
43482d709a5aSVille Syrjälä 				 port >= PORT_C ? " (TC)" : "",
43492d709a5aSVille Syrjälä 				 tc_port != TC_PORT_NONE ? "TC" : "",
435083566d13SVille Syrjälä 				 tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
43512d709a5aSVille Syrjälä 	} else {
43522d709a5aSVille Syrjälä 		drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
43532d709a5aSVille Syrjälä 				 DRM_MODE_ENCODER_TMDS,
43542d709a5aSVille Syrjälä 				 "DDI %c/PHY %c", port_name(port),  phy_name(phy));
43552d709a5aSVille Syrjälä 	}
4356379bc100SJani Nikula 
435736e5e704SSean Paul 	mutex_init(&dig_port->hdcp_mutex);
435836e5e704SSean Paul 	dig_port->num_hdcp_streams = 0;
435936e5e704SSean Paul 
436070dfbc29SLucas De Marchi 	encoder->hotplug = intel_ddi_hotplug;
436170dfbc29SLucas De Marchi 	encoder->compute_output_type = intel_ddi_compute_output_type;
436270dfbc29SLucas De Marchi 	encoder->compute_config = intel_ddi_compute_config;
4363b50a1aa6SManasi Navare 	encoder->compute_config_late = intel_ddi_compute_config_late;
436470dfbc29SLucas De Marchi 	encoder->enable = intel_enable_ddi;
436570dfbc29SLucas De Marchi 	encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
436670dfbc29SLucas De Marchi 	encoder->pre_enable = intel_ddi_pre_enable;
436770dfbc29SLucas De Marchi 	encoder->disable = intel_disable_ddi;
436870dfbc29SLucas De Marchi 	encoder->post_disable = intel_ddi_post_disable;
436970dfbc29SLucas De Marchi 	encoder->update_pipe = intel_ddi_update_pipe;
437070dfbc29SLucas De Marchi 	encoder->get_hw_state = intel_ddi_get_hw_state;
4371f9e76a6eSImre Deak 	encoder->sync_state = intel_ddi_sync_state;
4372b671d6efSImre Deak 	encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
4373151ec347SImre Deak 	encoder->suspend = intel_ddi_encoder_suspend;
4374151ec347SImre Deak 	encoder->shutdown = intel_ddi_encoder_shutdown;
437570dfbc29SLucas De Marchi 	encoder->get_power_domains = intel_ddi_get_power_domains;
437670dfbc29SLucas De Marchi 
437770dfbc29SLucas De Marchi 	encoder->type = INTEL_OUTPUT_DDI;
4378979e1b32SImre Deak 	encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
437970dfbc29SLucas De Marchi 	encoder->port = port;
438070dfbc29SLucas De Marchi 	encoder->cloneable = 0;
438170dfbc29SLucas De Marchi 	encoder->pipe_mask = ~0;
4382da51e4baSVille Syrjälä 
4383865b73eaSMatt Roper 	if (IS_DG2(dev_priv)) {
4384f82f2563SMatt Roper 		encoder->enable_clock = intel_mpllb_enable;
4385f82f2563SMatt Roper 		encoder->disable_clock = intel_mpllb_disable;
4386865b73eaSMatt Roper 		encoder->get_config = dg2_ddi_get_config;
4387865b73eaSMatt Roper 	} else if (IS_ALDERLAKE_S(dev_priv)) {
438840b316d4SVille Syrjälä 		encoder->enable_clock = adls_ddi_enable_clock;
438940b316d4SVille Syrjälä 		encoder->disable_clock = adls_ddi_disable_clock;
43900fbd8694SVille Syrjälä 		encoder->is_clock_enabled = adls_ddi_is_clock_enabled;
4391351221ffSVille Syrjälä 		encoder->get_config = adls_ddi_get_config;
439240b316d4SVille Syrjälä 	} else if (IS_ROCKETLAKE(dev_priv)) {
439340b316d4SVille Syrjälä 		encoder->enable_clock = rkl_ddi_enable_clock;
439440b316d4SVille Syrjälä 		encoder->disable_clock = rkl_ddi_disable_clock;
43950fbd8694SVille Syrjälä 		encoder->is_clock_enabled = rkl_ddi_is_clock_enabled;
4396351221ffSVille Syrjälä 		encoder->get_config = rkl_ddi_get_config;
439736ecb0ecSVille Syrjälä 	} else if (IS_DG1(dev_priv)) {
439835bb6b1aSVille Syrjälä 		encoder->enable_clock = dg1_ddi_enable_clock;
439935bb6b1aSVille Syrjälä 		encoder->disable_clock = dg1_ddi_disable_clock;
44000fbd8694SVille Syrjälä 		encoder->is_clock_enabled = dg1_ddi_is_clock_enabled;
4401351221ffSVille Syrjälä 		encoder->get_config = dg1_ddi_get_config;
440236ecb0ecSVille Syrjälä 	} else if (IS_JSL_EHL(dev_priv)) {
440336ecb0ecSVille Syrjälä 		if (intel_ddi_is_tc(dev_priv, port)) {
440436ecb0ecSVille Syrjälä 			encoder->enable_clock = jsl_ddi_tc_enable_clock;
440536ecb0ecSVille Syrjälä 			encoder->disable_clock = jsl_ddi_tc_disable_clock;
44060fbd8694SVille Syrjälä 			encoder->is_clock_enabled = jsl_ddi_tc_is_clock_enabled;
4407351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
440836ecb0ecSVille Syrjälä 		} else {
440936ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_combo_enable_clock;
441036ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_combo_disable_clock;
44110fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
4412351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
441336ecb0ecSVille Syrjälä 		}
4414005e9537SMatt Roper 	} else if (DISPLAY_VER(dev_priv) >= 11) {
441536ecb0ecSVille Syrjälä 		if (intel_ddi_is_tc(dev_priv, port)) {
441636ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_tc_enable_clock;
441736ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_tc_disable_clock;
44180fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_tc_is_clock_enabled;
4419351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_tc_get_config;
442036ecb0ecSVille Syrjälä 		} else {
442136ecb0ecSVille Syrjälä 			encoder->enable_clock = icl_ddi_combo_enable_clock;
442236ecb0ecSVille Syrjälä 			encoder->disable_clock = icl_ddi_combo_disable_clock;
44230fbd8694SVille Syrjälä 			encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
4424351221ffSVille Syrjälä 			encoder->get_config = icl_ddi_combo_get_config;
442536ecb0ecSVille Syrjälä 		}
44262446e1d6SMatt Roper 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
4427351221ffSVille Syrjälä 		/* BXT/GLK have fixed PLL->port mapping */
4428351221ffSVille Syrjälä 		encoder->get_config = bxt_ddi_get_config;
442993e7e61eSLucas De Marchi 	} else if (DISPLAY_VER(dev_priv) == 9) {
443038e31f1aSVille Syrjälä 		encoder->enable_clock = skl_ddi_enable_clock;
443138e31f1aSVille Syrjälä 		encoder->disable_clock = skl_ddi_disable_clock;
44320fbd8694SVille Syrjälä 		encoder->is_clock_enabled = skl_ddi_is_clock_enabled;
4433351221ffSVille Syrjälä 		encoder->get_config = skl_ddi_get_config;
443438e31f1aSVille Syrjälä 	} else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
4435d135368dSVille Syrjälä 		encoder->enable_clock = hsw_ddi_enable_clock;
4436d135368dSVille Syrjälä 		encoder->disable_clock = hsw_ddi_disable_clock;
44370fbd8694SVille Syrjälä 		encoder->is_clock_enabled = hsw_ddi_is_clock_enabled;
4438351221ffSVille Syrjälä 		encoder->get_config = hsw_ddi_get_config;
4439d135368dSVille Syrjälä 	}
4440d135368dSVille Syrjälä 
4441193299adSVille Syrjälä 	if (IS_DG2(dev_priv)) {
4442193299adSVille Syrjälä 		encoder->set_signal_levels = intel_snps_phy_set_signal_levels;
4443193299adSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) >= 12) {
4444193299adSVille Syrjälä 		if (intel_phy_is_combo(dev_priv, phy))
4445193299adSVille Syrjälä 			encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
4446e722ab8bSVille Syrjälä 		else
4447193299adSVille Syrjälä 			encoder->set_signal_levels = tgl_dkl_phy_set_signal_levels;
4448193299adSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) >= 11) {
4449193299adSVille Syrjälä 		if (intel_phy_is_combo(dev_priv, phy))
4450193299adSVille Syrjälä 			encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
4451193299adSVille Syrjälä 		else
4452193299adSVille Syrjälä 			encoder->set_signal_levels = icl_mg_phy_set_signal_levels;
4453193299adSVille Syrjälä 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
44545f5ada0bSVille Syrjälä 		encoder->set_signal_levels = bxt_ddi_phy_set_signal_levels;
4455193299adSVille Syrjälä 	} else {
4456e722ab8bSVille Syrjälä 		encoder->set_signal_levels = hsw_set_signal_levels;
4457193299adSVille Syrjälä 	}
4458e722ab8bSVille Syrjälä 
4459c40a253bSVille Syrjälä 	intel_ddi_buf_trans_init(encoder);
4460c40a253bSVille Syrjälä 
4461ed2615a8SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 13)
4462ed2615a8SMatt Roper 		encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port);
4463ed2615a8SMatt Roper 	else if (IS_DG1(dev_priv))
4464229f31e2SLucas De Marchi 		encoder->hpd_pin = dg1_hpd_pin(dev_priv, port);
4465229f31e2SLucas De Marchi 	else if (IS_ROCKETLAKE(dev_priv))
4466da51e4baSVille Syrjälä 		encoder->hpd_pin = rkl_hpd_pin(dev_priv, port);
4467005e9537SMatt Roper 	else if (DISPLAY_VER(dev_priv) >= 12)
4468da51e4baSVille Syrjälä 		encoder->hpd_pin = tgl_hpd_pin(dev_priv, port);
446924ea098bSTejas Upadhyay 	else if (IS_JSL_EHL(dev_priv))
4470da51e4baSVille Syrjälä 		encoder->hpd_pin = ehl_hpd_pin(dev_priv, port);
447193e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 11)
4472da51e4baSVille Syrjälä 		encoder->hpd_pin = icl_hpd_pin(dev_priv, port);
447393e7e61eSLucas De Marchi 	else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
4474c8455098SLyude Paul 		encoder->hpd_pin = skl_hpd_pin(dev_priv, port);
4475da51e4baSVille Syrjälä 	else
447603c7e4f1SVille Syrjälä 		encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
4477379bc100SJani Nikula 
4478005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11)
44797801f3b7SLucas De Marchi 		dig_port->saved_port_bits =
44807801f3b7SLucas De Marchi 			intel_de_read(dev_priv, DDI_BUF_CTL(port))
44817801f3b7SLucas De Marchi 			& DDI_BUF_PORT_REVERSAL;
4482379bc100SJani Nikula 	else
44837801f3b7SLucas De Marchi 		dig_port->saved_port_bits =
44847801f3b7SLucas De Marchi 			intel_de_read(dev_priv, DDI_BUF_CTL(port))
44857801f3b7SLucas De Marchi 			& (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
448670dfbc29SLucas De Marchi 
44875f42196dSVille Syrjälä 	if (intel_bios_encoder_lane_reversal(devdata))
4488aaab24bbSUma Shankar 		dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
4489aaab24bbSUma Shankar 
44907801f3b7SLucas De Marchi 	dig_port->dp.output_reg = INVALID_MMIO_REG;
44917801f3b7SLucas De Marchi 	dig_port->max_lanes = intel_ddi_max_lanes(dig_port);
4492bb45217fSVille Syrjälä 	dig_port->aux_ch = intel_dp_aux_ch(encoder);
4493379bc100SJani Nikula 
4494d8fe2ab6SMatt Roper 	if (intel_phy_is_tc(dev_priv, phy)) {
4495c5faae5aSJani Nikula 		bool is_legacy =
4496f08fbe6aSJani Nikula 			!intel_bios_encoder_supports_typec_usb(devdata) &&
4497f08fbe6aSJani Nikula 			!intel_bios_encoder_supports_tbt(devdata);
4498379bc100SJani Nikula 
44997801f3b7SLucas De Marchi 		intel_tc_port_init(dig_port, is_legacy);
450024a7bfe0SImre Deak 
450170dfbc29SLucas De Marchi 		encoder->update_prepare = intel_ddi_update_prepare;
450270dfbc29SLucas De Marchi 		encoder->update_complete = intel_ddi_update_complete;
4503ab7bc4e1SImre Deak 	}
4504ab7bc4e1SImre Deak 
45051de143ccSPankaj Bharadiya 	drm_WARN_ON(&dev_priv->drm, port > PORT_I);
4506979e1b32SImre Deak 	dig_port->ddi_io_power_domain = intel_display_power_ddi_io_domain(dev_priv, port);
4507379bc100SJani Nikula 
4508005e9537SMatt Roper 	if (DISPLAY_VER(dev_priv) >= 11) {
4509edc0e09cSVille Syrjälä 		if (intel_phy_is_tc(dev_priv, phy))
45107801f3b7SLucas De Marchi 			dig_port->connected = intel_tc_port_connected;
4511edc0e09cSVille Syrjälä 		else
45127801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4513*dded35acSVille Syrjälä 	} else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
4514*dded35acSVille Syrjälä 		dig_port->connected = bdw_digital_port_connected;
4515*dded35acSVille Syrjälä 	} else if (DISPLAY_VER(dev_priv) == 9) {
4516*dded35acSVille Syrjälä 		dig_port->connected = lpt_digital_port_connected;
4517*dded35acSVille Syrjälä 	} else if (IS_BROADWELL(dev_priv)) {
4518*dded35acSVille Syrjälä 		if (port == PORT_A)
45197801f3b7SLucas De Marchi 			dig_port->connected = bdw_digital_port_connected;
4520edc0e09cSVille Syrjälä 		else
45217801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4522*dded35acSVille Syrjälä 	} else if (IS_HASWELL(dev_priv)) {
4523c7e8a3d6SVille Syrjälä 		if (port == PORT_A)
45247801f3b7SLucas De Marchi 			dig_port->connected = hsw_digital_port_connected;
4525edc0e09cSVille Syrjälä 		else
45267801f3b7SLucas De Marchi 			dig_port->connected = lpt_digital_port_connected;
4527edc0e09cSVille Syrjälä 	}
4528edc0e09cSVille Syrjälä 
45297801f3b7SLucas De Marchi 	intel_infoframe_init(dig_port);
4530379bc100SJani Nikula 
4531a98ffd6eSVille Syrjälä 	if (init_dp) {
4532a98ffd6eSVille Syrjälä 		if (!intel_ddi_init_dp_connector(dig_port))
4533a98ffd6eSVille Syrjälä 			goto err;
4534a98ffd6eSVille Syrjälä 
4535a98ffd6eSVille Syrjälä 		dig_port->hpd_pulse = intel_dp_hpd_pulse;
4536a98ffd6eSVille Syrjälä 
4537a98ffd6eSVille Syrjälä 		if (dig_port->dp.mso_link_count)
4538a98ffd6eSVille Syrjälä 			encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv);
4539a98ffd6eSVille Syrjälä 	}
4540a98ffd6eSVille Syrjälä 
4541a98ffd6eSVille Syrjälä 	/*
4542a98ffd6eSVille Syrjälä 	 * In theory we don't need the encoder->type check,
4543a98ffd6eSVille Syrjälä 	 * but leave it just in case we have some really bad VBTs...
4544a98ffd6eSVille Syrjälä 	 */
4545a98ffd6eSVille Syrjälä 	if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
4546a98ffd6eSVille Syrjälä 		if (!intel_ddi_init_hdmi_connector(dig_port))
4547a98ffd6eSVille Syrjälä 			goto err;
4548a98ffd6eSVille Syrjälä 	}
4549a98ffd6eSVille Syrjälä 
4550379bc100SJani Nikula 	return;
4551379bc100SJani Nikula 
4552379bc100SJani Nikula err:
455370dfbc29SLucas De Marchi 	drm_encoder_cleanup(&encoder->base);
45547801f3b7SLucas De Marchi 	kfree(dig_port);
4555379bc100SJani Nikula }
4556