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
286e916b35SImre Deak #include <linux/iopoll.h>
29707c3a7dSLucas De Marchi #include <linux/string_helpers.h>
30707c3a7dSLucas De Marchi
31644edf52SThomas Zimmermann #include <drm/display/drm_scdc_helper.h>
326306d8dbSHans de Goede #include <drm/drm_privacy_screen_consumer.h>
33379bc100SJani Nikula
34379bc100SJani Nikula #include "i915_drv.h"
35801543b2SJani Nikula #include "i915_reg.h"
36021a62a5SVille Syrjälä #include "icl_dsi.h"
37379bc100SJani Nikula #include "intel_audio.h"
38b43edc50SJani Nikula #include "intel_audio_regs.h"
396cc42fbeSJani Nikula #include "intel_backlight.h"
40379bc100SJani Nikula #include "intel_combo_phy.h"
41d0864ee4SMatt Roper #include "intel_combo_phy_regs.h"
42379bc100SJani Nikula #include "intel_connector.h"
437c53e628SJani Nikula #include "intel_crtc.h"
4451390cc0SRadhakrishna Sripada #include "intel_cx0_phy.h"
4523ef6194SJosé Roberto de Souza #include "intel_cx0_phy_regs.h"
46379bc100SJani Nikula #include "intel_ddi.h"
4799092a97SDave Airlie #include "intel_ddi_buf_trans.h"
487785ae0bSVille Syrjälä #include "intel_de.h"
49979e1b32SImre Deak #include "intel_display_power.h"
501d455f8dSJani Nikula #include "intel_display_types.h"
5189cb0ba4SImre Deak #include "intel_dkl_phy.h"
52d69813c7SImre Deak #include "intel_dkl_phy_regs.h"
53379bc100SJani Nikula #include "intel_dp.h"
54bb45217fSVille Syrjälä #include "intel_dp_aux.h"
55379bc100SJani Nikula #include "intel_dp_link_training.h"
56dcb38f79SDave Airlie #include "intel_dp_mst.h"
57e7e5048fSImre Deak #include "intel_dp_tunnel.h"
58379bc100SJani Nikula #include "intel_dpio_phy.h"
59379bc100SJani Nikula #include "intel_dsi.h"
603b3be899SImre Deak #include "intel_encoder.h"
61dcb38f79SDave Airlie #include "intel_fdi.h"
62379bc100SJani Nikula #include "intel_fifo_underrun.h"
63379bc100SJani Nikula #include "intel_gmbus.h"
64379bc100SJani Nikula #include "intel_hdcp.h"
65379bc100SJani Nikula #include "intel_hdmi.h"
66379bc100SJani Nikula #include "intel_hotplug.h"
6703120fefSJani Nikula #include "intel_hti.h"
68379bc100SJani Nikula #include "intel_lspcon.h"
69589ebefdSImre Deak #include "intel_mg_phy_regs.h"
7060ded7ccSImre Deak #include "intel_modeset_lock.h"
71abad6805SJani Nikula #include "intel_pps.h"
72379bc100SJani Nikula #include "intel_psr.h"
730c82118bSJani Nikula #include "intel_quirks.h"
74865b73eaSMatt Roper #include "intel_snps_phy.h"
75bc85328fSImre Deak #include "intel_tc.h"
76379bc100SJani Nikula #include "intel_vdsc.h"
77c3f05948SJani Nikula #include "intel_vdsc_regs.h"
78714b1cdbSDave Airlie #include "skl_scaler.h"
7946d12f91SDave Airlie #include "skl_universal_plane.h"
80379bc100SJani Nikula
81379bc100SJani Nikula static const u8 index_to_dp_signal_levels[] = {
82379bc100SJani Nikula [0] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0,
83379bc100SJani Nikula [1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1,
84379bc100SJani Nikula [2] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2,
85379bc100SJani Nikula [3] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3,
86379bc100SJani Nikula [4] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0,
87379bc100SJani Nikula [5] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1,
88379bc100SJani Nikula [6] = DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2,
89379bc100SJani Nikula [7] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0,
90379bc100SJani Nikula [8] = DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1,
91379bc100SJani Nikula [9] = DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0,
92379bc100SJani Nikula };
93379bc100SJani Nikula
intel_ddi_hdmi_level(struct intel_encoder * encoder,const struct intel_ddi_buf_trans * trans)94a621860aSVille Syrjälä static int intel_ddi_hdmi_level(struct intel_encoder *encoder,
953e022c1fSVille Syrjälä const struct intel_ddi_buf_trans *trans)
96379bc100SJani Nikula {
973e022c1fSVille Syrjälä int level;
98379bc100SJani Nikula
9902107ef1SVille Syrjälä level = intel_bios_hdmi_level_shift(encoder->devdata);
1000aed3bdeSJani Nikula if (level < 0)
1013e022c1fSVille Syrjälä level = trans->hdmi_default_entry;
102379bc100SJani Nikula
103379bc100SJani Nikula return level;
104379bc100SJani Nikula }
105379bc100SJani Nikula
has_buf_trans_select(struct drm_i915_private * i915)1065bafd85dSVille Syrjälä static bool has_buf_trans_select(struct drm_i915_private *i915)
1075bafd85dSVille Syrjälä {
1085bafd85dSVille Syrjälä return DISPLAY_VER(i915) < 10 && !IS_BROXTON(i915);
1095bafd85dSVille Syrjälä }
1105bafd85dSVille Syrjälä
has_iboost(struct drm_i915_private * i915)111f820693bSVille Syrjälä static bool has_iboost(struct drm_i915_private *i915)
112f820693bSVille Syrjälä {
113f820693bSVille Syrjälä return DISPLAY_VER(i915) == 9 && !IS_BROXTON(i915);
114f820693bSVille Syrjälä }
115f820693bSVille Syrjälä
116379bc100SJani Nikula /*
117379bc100SJani Nikula * Starting with Haswell, DDI port buffers must be programmed with correct
118379bc100SJani Nikula * values in advance. This function programs the correct values for
119379bc100SJani Nikula * DP/eDP/FDI use cases.
120379bc100SJani Nikula */
hsw_prepare_dp_ddi_buffers(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)121266152aeSVille Syrjälä void hsw_prepare_dp_ddi_buffers(struct intel_encoder *encoder,
122379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
123379bc100SJani Nikula {
124379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
125379bc100SJani Nikula u32 iboost_bit = 0;
126379bc100SJani Nikula int i, n_entries;
127379bc100SJani Nikula enum port port = encoder->port;
128e505d764SVille Syrjälä const struct intel_ddi_buf_trans *trans;
129379bc100SJani Nikula
130e505d764SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
131e505d764SVille Syrjälä if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
132d6b10b1aSVille Syrjälä return;
133379bc100SJani Nikula
134379bc100SJani Nikula /* If we're boosting the current, set bit 31 of trans1 */
135f820693bSVille Syrjälä if (has_iboost(dev_priv) &&
13602107ef1SVille Syrjälä intel_bios_dp_boost_level(encoder->devdata))
137379bc100SJani Nikula iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
138379bc100SJani Nikula
139379bc100SJani Nikula for (i = 0; i < n_entries; i++) {
140f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, i),
141e505d764SVille Syrjälä trans->entries[i].hsw.trans1 | iboost_bit);
142f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, i),
143e505d764SVille Syrjälä trans->entries[i].hsw.trans2);
144379bc100SJani Nikula }
145379bc100SJani Nikula }
146379bc100SJani Nikula
147379bc100SJani Nikula /*
148379bc100SJani Nikula * Starting with Haswell, DDI port buffers must be programmed with correct
149379bc100SJani Nikula * values in advance. This function programs the correct values for
150379bc100SJani Nikula * HDMI/DVI use cases.
151379bc100SJani Nikula */
hsw_prepare_hdmi_ddi_buffers(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)152266152aeSVille Syrjälä static void hsw_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder,
153e722ab8bSVille Syrjälä const struct intel_crtc_state *crtc_state)
154379bc100SJani Nikula {
155379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
156d0920a45SVille Syrjälä int level = intel_ddi_level(encoder, crtc_state, 0);
157379bc100SJani Nikula u32 iboost_bit = 0;
158379bc100SJani Nikula int n_entries;
159379bc100SJani Nikula enum port port = encoder->port;
160e505d764SVille Syrjälä const struct intel_ddi_buf_trans *trans;
161379bc100SJani Nikula
162e505d764SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
163e505d764SVille Syrjälä if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
164379bc100SJani Nikula return;
165379bc100SJani Nikula
166379bc100SJani Nikula /* If we're boosting the current, set bit 31 of trans1 */
167f820693bSVille Syrjälä if (has_iboost(dev_priv) &&
16802107ef1SVille Syrjälä intel_bios_hdmi_boost_level(encoder->devdata))
169379bc100SJani Nikula iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE;
170379bc100SJani Nikula
171379bc100SJani Nikula /* Entry 9 is for HDMI: */
172f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_TRANS_LO(port, 9),
173e505d764SVille Syrjälä trans->entries[level].hsw.trans1 | iboost_bit);
174f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_TRANS_HI(port, 9),
175e505d764SVille Syrjälä trans->entries[level].hsw.trans2);
176379bc100SJani Nikula }
177379bc100SJani Nikula
mtl_wait_ddi_buf_idle(struct drm_i915_private * i915,enum port port)17823ef6194SJosé Roberto de Souza static void mtl_wait_ddi_buf_idle(struct drm_i915_private *i915, enum port port)
17923ef6194SJosé Roberto de Souza {
18023ef6194SJosé Roberto de Souza int ret;
18123ef6194SJosé Roberto de Souza
18223ef6194SJosé Roberto de Souza /* FIXME: find out why Bspec's 100us timeout is too short */
183fe4c6ff5SLucas De Marchi ret = wait_for_us((intel_de_read(i915, XELPDP_PORT_BUF_CTL1(i915, port)) &
18423ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_PHY_IDLE), 10000);
18523ef6194SJosé Roberto de Souza if (ret)
18623ef6194SJosé Roberto de Souza drm_err(&i915->drm, "Timeout waiting for DDI BUF %c to get idle\n",
18723ef6194SJosé Roberto de Souza port_name(port));
18823ef6194SJosé Roberto de Souza }
18923ef6194SJosé Roberto de Souza
intel_wait_ddi_buf_idle(struct drm_i915_private * dev_priv,enum port port)190dcb38f79SDave Airlie void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,
191379bc100SJani Nikula enum port port)
192379bc100SJani Nikula {
1935a2ad99bSManasi Navare if (IS_BROXTON(dev_priv)) {
1945a2ad99bSManasi Navare udelay(16);
195379bc100SJani Nikula return;
196379bc100SJani Nikula }
1975a2ad99bSManasi Navare
1985a2ad99bSManasi Navare if (wait_for_us((intel_de_read(dev_priv, DDI_BUF_CTL(port)) &
1995a2ad99bSManasi Navare DDI_BUF_IS_IDLE), 8))
2005a2ad99bSManasi Navare drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get idle\n",
20147bdb1caSJani Nikula port_name(port));
202379bc100SJani Nikula }
203379bc100SJani Nikula
intel_wait_ddi_buf_active(struct intel_encoder * encoder)204684a37a6SJani Nikula static void intel_wait_ddi_buf_active(struct intel_encoder *encoder)
205e828da30SManasi Navare {
206684a37a6SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
207684a37a6SJani Nikula enum port port = encoder->port;
2085add4575SAnkit Nautiyal int timeout_us;
209f82f2563SMatt Roper int ret;
210f82f2563SMatt Roper
211e828da30SManasi Navare /* Wait > 518 usecs for DDI_BUF_CTL to be non idle */
212ad314fecSVille Syrjälä if (DISPLAY_VER(dev_priv) < 10) {
213e828da30SManasi Navare usleep_range(518, 1000);
214e828da30SManasi Navare return;
215e828da30SManasi Navare }
216e828da30SManasi Navare
21723ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14) {
21823ef6194SJosé Roberto de Souza timeout_us = 10000;
21923ef6194SJosé Roberto de Souza } else if (IS_DG2(dev_priv)) {
2205add4575SAnkit Nautiyal timeout_us = 1200;
2215add4575SAnkit Nautiyal } else if (DISPLAY_VER(dev_priv) >= 12) {
2227fcf7558SJani Nikula if (intel_encoder_is_tc(encoder))
2235add4575SAnkit Nautiyal timeout_us = 3000;
2245add4575SAnkit Nautiyal else
2255add4575SAnkit Nautiyal timeout_us = 1000;
2265add4575SAnkit Nautiyal } else {
2275add4575SAnkit Nautiyal timeout_us = 500;
2285add4575SAnkit Nautiyal }
2295add4575SAnkit Nautiyal
23023ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14)
231fe4c6ff5SLucas De Marchi ret = _wait_for(!(intel_de_read(dev_priv,
232fe4c6ff5SLucas De Marchi XELPDP_PORT_BUF_CTL1(dev_priv, port)) &
233fe4c6ff5SLucas De Marchi XELPDP_PORT_BUF_PHY_IDLE),
23423ef6194SJosé Roberto de Souza timeout_us, 10, 10);
23523ef6194SJosé Roberto de Souza else
23623ef6194SJosé Roberto de Souza ret = _wait_for(!(intel_de_read(dev_priv, DDI_BUF_CTL(port)) & DDI_BUF_IS_IDLE),
23723ef6194SJosé Roberto de Souza timeout_us, 10, 10);
238f82f2563SMatt Roper
239f82f2563SMatt Roper if (ret)
240e828da30SManasi Navare drm_err(&dev_priv->drm, "Timeout waiting for DDI BUF %c to get active\n",
241e828da30SManasi Navare port_name(port));
242e828da30SManasi Navare }
243e828da30SManasi Navare
hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll * pll)244ad952982SVille Syrjälä static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
245379bc100SJani Nikula {
246379bc100SJani Nikula switch (pll->info->id) {
247379bc100SJani Nikula case DPLL_ID_WRPLL1:
248379bc100SJani Nikula return PORT_CLK_SEL_WRPLL1;
249379bc100SJani Nikula case DPLL_ID_WRPLL2:
250379bc100SJani Nikula return PORT_CLK_SEL_WRPLL2;
251379bc100SJani Nikula case DPLL_ID_SPLL:
252379bc100SJani Nikula return PORT_CLK_SEL_SPLL;
253379bc100SJani Nikula case DPLL_ID_LCPLL_810:
254379bc100SJani Nikula return PORT_CLK_SEL_LCPLL_810;
255379bc100SJani Nikula case DPLL_ID_LCPLL_1350:
256379bc100SJani Nikula return PORT_CLK_SEL_LCPLL_1350;
257379bc100SJani Nikula case DPLL_ID_LCPLL_2700:
258379bc100SJani Nikula return PORT_CLK_SEL_LCPLL_2700;
259379bc100SJani Nikula default:
260379bc100SJani Nikula MISSING_CASE(pll->info->id);
261379bc100SJani Nikula return PORT_CLK_SEL_NONE;
262379bc100SJani Nikula }
263379bc100SJani Nikula }
264379bc100SJani Nikula
icl_pll_to_ddi_clk_sel(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)265379bc100SJani Nikula static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder,
266379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
267379bc100SJani Nikula {
268379bc100SJani Nikula const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
269379bc100SJani Nikula int clock = crtc_state->port_clock;
270379bc100SJani Nikula const enum intel_dpll_id id = pll->info->id;
271379bc100SJani Nikula
272379bc100SJani Nikula switch (id) {
273379bc100SJani Nikula default:
274379bc100SJani Nikula /*
275379bc100SJani Nikula * DPLL_ID_ICL_DPLL0 and DPLL_ID_ICL_DPLL1 should not be used
276379bc100SJani Nikula * here, so do warn if this get passed in
277379bc100SJani Nikula */
278379bc100SJani Nikula MISSING_CASE(id);
279379bc100SJani Nikula return DDI_CLK_SEL_NONE;
280379bc100SJani Nikula case DPLL_ID_ICL_TBTPLL:
281379bc100SJani Nikula switch (clock) {
282379bc100SJani Nikula case 162000:
283379bc100SJani Nikula return DDI_CLK_SEL_TBT_162;
284379bc100SJani Nikula case 270000:
285379bc100SJani Nikula return DDI_CLK_SEL_TBT_270;
286379bc100SJani Nikula case 540000:
287379bc100SJani Nikula return DDI_CLK_SEL_TBT_540;
288379bc100SJani Nikula case 810000:
289379bc100SJani Nikula return DDI_CLK_SEL_TBT_810;
290379bc100SJani Nikula default:
291379bc100SJani Nikula MISSING_CASE(clock);
292379bc100SJani Nikula return DDI_CLK_SEL_NONE;
293379bc100SJani Nikula }
294379bc100SJani Nikula case DPLL_ID_ICL_MGPLL1:
295379bc100SJani Nikula case DPLL_ID_ICL_MGPLL2:
296379bc100SJani Nikula case DPLL_ID_ICL_MGPLL3:
297379bc100SJani Nikula case DPLL_ID_ICL_MGPLL4:
2986677c3b1SJosé Roberto de Souza case DPLL_ID_TGL_MGPLL5:
2996677c3b1SJosé Roberto de Souza case DPLL_ID_TGL_MGPLL6:
300379bc100SJani Nikula return DDI_CLK_SEL_MG;
301379bc100SJani Nikula }
302379bc100SJani Nikula }
303379bc100SJani Nikula
ddi_buf_phy_link_rate(int port_clock)304414002f1SImre Deak static u32 ddi_buf_phy_link_rate(int port_clock)
305414002f1SImre Deak {
306414002f1SImre Deak switch (port_clock) {
307414002f1SImre Deak case 162000:
308414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(0);
309414002f1SImre Deak case 216000:
310414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(4);
311414002f1SImre Deak case 243000:
312414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(5);
313414002f1SImre Deak case 270000:
314414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(1);
315414002f1SImre Deak case 324000:
316414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(6);
317414002f1SImre Deak case 432000:
318414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(7);
319414002f1SImre Deak case 540000:
320414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(2);
321414002f1SImre Deak case 810000:
322414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(3);
323414002f1SImre Deak default:
324414002f1SImre Deak MISSING_CASE(port_clock);
325414002f1SImre Deak return DDI_BUF_PHY_LINK_RATE(0);
326414002f1SImre Deak }
327414002f1SImre Deak }
328414002f1SImre Deak
intel_ddi_init_dp_buf_reg(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)329a621860aSVille Syrjälä static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder,
330a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state)
331379bc100SJani Nikula {
33255ce306cSJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(encoder->base.dev);
333b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3347801f3b7SLucas De Marchi struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
335379bc100SJani Nikula
3369f620f1dSVille Syrjälä /* DDI_BUF_CTL_ENABLE will be set by intel_ddi_prepare_link_retrain() later */
3377801f3b7SLucas De Marchi intel_dp->DP = dig_port->saved_port_bits |
3389f620f1dSVille Syrjälä DDI_PORT_WIDTH(crtc_state->lane_count) |
3399f620f1dSVille Syrjälä DDI_BUF_TRANS_SELECT(0);
34055ce306cSJosé Roberto de Souza
34123ef6194SJosé Roberto de Souza if (DISPLAY_VER(i915) >= 14) {
34223ef6194SJosé Roberto de Souza if (intel_dp_is_uhbr(crtc_state))
34323ef6194SJosé Roberto de Souza intel_dp->DP |= DDI_BUF_PORT_DATA_40BIT;
34423ef6194SJosé Roberto de Souza else
34523ef6194SJosé Roberto de Souza intel_dp->DP |= DDI_BUF_PORT_DATA_10BIT;
34623ef6194SJosé Roberto de Souza }
34723ef6194SJosé Roberto de Souza
3487fcf7558SJani Nikula if (IS_ALDERLAKE_P(i915) && intel_encoder_is_tc(encoder)) {
349414002f1SImre Deak intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock);
35011a89708SImre Deak if (!intel_tc_port_in_tbt_alt_mode(dig_port))
35155ce306cSJosé Roberto de Souza intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
352379bc100SJani Nikula }
353414002f1SImre Deak }
354379bc100SJani Nikula
icl_calc_tbt_pll_link(struct drm_i915_private * dev_priv,enum port port)355379bc100SJani Nikula static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,
356379bc100SJani Nikula enum port port)
357379bc100SJani Nikula {
358f7960e7fSJani Nikula u32 val = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK;
359379bc100SJani Nikula
360379bc100SJani Nikula switch (val) {
361379bc100SJani Nikula case DDI_CLK_SEL_NONE:
362379bc100SJani Nikula return 0;
363379bc100SJani Nikula case DDI_CLK_SEL_TBT_162:
364379bc100SJani Nikula return 162000;
365379bc100SJani Nikula case DDI_CLK_SEL_TBT_270:
366379bc100SJani Nikula return 270000;
367379bc100SJani Nikula case DDI_CLK_SEL_TBT_540:
368379bc100SJani Nikula return 540000;
369379bc100SJani Nikula case DDI_CLK_SEL_TBT_810:
370379bc100SJani Nikula return 810000;
371379bc100SJani Nikula default:
372379bc100SJani Nikula MISSING_CASE(val);
373379bc100SJani Nikula return 0;
374379bc100SJani Nikula }
375379bc100SJani Nikula }
376379bc100SJani Nikula
ddi_dotclock_get(struct intel_crtc_state * pipe_config)377623411c2SVille Syrjälä static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
378623411c2SVille Syrjälä {
379623411c2SVille Syrjälä /* CRT dotclock is determined via other means */
380623411c2SVille Syrjälä if (pipe_config->has_pch_encoder)
381623411c2SVille Syrjälä return;
382623411c2SVille Syrjälä
383623411c2SVille Syrjälä pipe_config->hw.adjusted_mode.crtc_clock =
384623411c2SVille Syrjälä intel_crtc_dotclock(pipe_config);
385379bc100SJani Nikula }
386379bc100SJani Nikula
intel_ddi_set_dp_msa(const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3870c06fa15SGwan-gyeong Mun void intel_ddi_set_dp_msa(const struct intel_crtc_state *crtc_state,
3880c06fa15SGwan-gyeong Mun const struct drm_connector_state *conn_state)
389379bc100SJani Nikula {
3902225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
391379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
392379bc100SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
393379bc100SJani Nikula u32 temp;
394379bc100SJani Nikula
395379bc100SJani Nikula if (!intel_crtc_has_dp_encoder(crtc_state))
396379bc100SJani Nikula return;
397379bc100SJani Nikula
3981de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder));
399379bc100SJani Nikula
4003e706dffSVille Syrjälä temp = DP_MSA_MISC_SYNC_CLOCK;
401379bc100SJani Nikula
402379bc100SJani Nikula switch (crtc_state->pipe_bpp) {
403379bc100SJani Nikula case 18:
4043e706dffSVille Syrjälä temp |= DP_MSA_MISC_6_BPC;
405379bc100SJani Nikula break;
406379bc100SJani Nikula case 24:
4073e706dffSVille Syrjälä temp |= DP_MSA_MISC_8_BPC;
408379bc100SJani Nikula break;
409379bc100SJani Nikula case 30:
4103e706dffSVille Syrjälä temp |= DP_MSA_MISC_10_BPC;
411379bc100SJani Nikula break;
412379bc100SJani Nikula case 36:
4133e706dffSVille Syrjälä temp |= DP_MSA_MISC_12_BPC;
414379bc100SJani Nikula break;
415379bc100SJani Nikula default:
416379bc100SJani Nikula MISSING_CASE(crtc_state->pipe_bpp);
417379bc100SJani Nikula break;
418379bc100SJani Nikula }
419379bc100SJani Nikula
420cae154fcSVille Syrjälä /* nonsense combination */
4211de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, crtc_state->limited_color_range &&
422cae154fcSVille Syrjälä crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB);
423cae154fcSVille Syrjälä
424cae154fcSVille Syrjälä if (crtc_state->limited_color_range)
4253e706dffSVille Syrjälä temp |= DP_MSA_MISC_COLOR_CEA_RGB;
426cae154fcSVille Syrjälä
427379bc100SJani Nikula /*
428379bc100SJani Nikula * As per DP 1.2 spec section 2.3.4.3 while sending
429379bc100SJani Nikula * YCBCR 444 signals we should program MSA MISC1/0 fields with
430646d3dc8SVille Syrjälä * colorspace information.
431379bc100SJani Nikula */
432379bc100SJani Nikula if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
4333e706dffSVille Syrjälä temp |= DP_MSA_MISC_COLOR_YCBCR_444_BT709;
434646d3dc8SVille Syrjälä
435379bc100SJani Nikula /*
436379bc100SJani Nikula * As per DP 1.4a spec section 2.2.4.3 [MSA Field for Indication
437379bc100SJani Nikula * of Color Encoding Format and Content Color Gamut] while sending
4380c06fa15SGwan-gyeong Mun * YCBCR 420, HDR BT.2020 signals we should program MSA MISC1 fields
4390c06fa15SGwan-gyeong Mun * which indicate VSC SDP for the Pixel Encoding/Colorimetry Format.
440379bc100SJani Nikula */
441bd8c9ccaSGwan-gyeong Mun if (intel_dp_needs_vsc_sdp(crtc_state, conn_state))
4423e706dffSVille Syrjälä temp |= DP_MSA_MISC_COLOR_VSC_SDP;
4430c06fa15SGwan-gyeong Mun
4440623993cSJani Nikula intel_de_write(dev_priv, TRANS_MSA_MISC(dev_priv, cpu_transcoder),
4450623993cSJani Nikula temp);
446379bc100SJani Nikula }
447379bc100SJani Nikula
bdw_trans_port_sync_master_select(enum transcoder master_transcoder)448dc5b8ed5SVille Syrjälä static u32 bdw_trans_port_sync_master_select(enum transcoder master_transcoder)
449dc5b8ed5SVille Syrjälä {
450dc5b8ed5SVille Syrjälä if (master_transcoder == TRANSCODER_EDP)
451dc5b8ed5SVille Syrjälä return 0;
452dc5b8ed5SVille Syrjälä else
453dc5b8ed5SVille Syrjälä return master_transcoder + 1;
454dc5b8ed5SVille Syrjälä }
455dc5b8ed5SVille Syrjälä
45679ac2b1bSJani Nikula static void
intel_ddi_config_transcoder_dp2(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)45779ac2b1bSJani Nikula intel_ddi_config_transcoder_dp2(struct intel_encoder *encoder,
45879ac2b1bSJani Nikula const struct intel_crtc_state *crtc_state)
45979ac2b1bSJani Nikula {
46079ac2b1bSJani Nikula struct drm_i915_private *i915 = to_i915(encoder->base.dev);
46179ac2b1bSJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
46279ac2b1bSJani Nikula u32 val = 0;
46379ac2b1bSJani Nikula
46479ac2b1bSJani Nikula if (intel_dp_is_uhbr(crtc_state))
46579ac2b1bSJani Nikula val = TRANS_DP2_128B132B_CHANNEL_CODING;
46679ac2b1bSJani Nikula
46779ac2b1bSJani Nikula intel_de_write(i915, TRANS_DP2_CTL(cpu_transcoder), val);
46879ac2b1bSJani Nikula }
46979ac2b1bSJani Nikula
47099389390SJosé Roberto de Souza /*
47199389390SJosé Roberto de Souza * Returns the TRANS_DDI_FUNC_CTL value based on CRTC state.
47299389390SJosé Roberto de Souza *
47399389390SJosé Roberto de Souza * Only intended to be used by intel_ddi_enable_transcoder_func() and
47499389390SJosé Roberto de Souza * intel_ddi_config_transcoder_func().
47599389390SJosé Roberto de Souza */
47699389390SJosé Roberto de Souza static u32
intel_ddi_transcoder_func_reg_val_get(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)477eed22a46SVille Syrjälä intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder,
478eed22a46SVille Syrjälä const struct intel_crtc_state *crtc_state)
479379bc100SJani Nikula {
4802225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
481379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
482379bc100SJani Nikula enum pipe pipe = crtc->pipe;
483379bc100SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
484379bc100SJani Nikula enum port port = encoder->port;
485379bc100SJani Nikula u32 temp;
486379bc100SJani Nikula
487379bc100SJani Nikula /* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */
488379bc100SJani Nikula temp = TRANS_DDI_FUNC_ENABLE;
489005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12)
490df16b636SMahesh Kumar temp |= TGL_TRANS_DDI_SELECT_PORT(port);
491df16b636SMahesh Kumar else
492379bc100SJani Nikula temp |= TRANS_DDI_SELECT_PORT(port);
493379bc100SJani Nikula
494379bc100SJani Nikula switch (crtc_state->pipe_bpp) {
49504514c14SJani Nikula default:
49604514c14SJani Nikula MISSING_CASE(crtc_state->pipe_bpp);
49704514c14SJani Nikula fallthrough;
498379bc100SJani Nikula case 18:
499379bc100SJani Nikula temp |= TRANS_DDI_BPC_6;
500379bc100SJani Nikula break;
501379bc100SJani Nikula case 24:
502379bc100SJani Nikula temp |= TRANS_DDI_BPC_8;
503379bc100SJani Nikula break;
504379bc100SJani Nikula case 30:
505379bc100SJani Nikula temp |= TRANS_DDI_BPC_10;
506379bc100SJani Nikula break;
507379bc100SJani Nikula case 36:
508379bc100SJani Nikula temp |= TRANS_DDI_BPC_12;
509379bc100SJani Nikula break;
510379bc100SJani Nikula }
511379bc100SJani Nikula
5121326a92cSMaarten Lankhorst if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PVSYNC)
513379bc100SJani Nikula temp |= TRANS_DDI_PVSYNC;
5141326a92cSMaarten Lankhorst if (crtc_state->hw.adjusted_mode.flags & DRM_MODE_FLAG_PHSYNC)
515379bc100SJani Nikula temp |= TRANS_DDI_PHSYNC;
516379bc100SJani Nikula
517379bc100SJani Nikula if (cpu_transcoder == TRANSCODER_EDP) {
518379bc100SJani Nikula switch (pipe) {
51904514c14SJani Nikula default:
52004514c14SJani Nikula MISSING_CASE(pipe);
52104514c14SJani Nikula fallthrough;
522379bc100SJani Nikula case PIPE_A:
523379bc100SJani Nikula /* On Haswell, can only use the always-on power well for
524379bc100SJani Nikula * eDP when not using the panel fitter, and when not
525379bc100SJani Nikula * using motion blur mitigation (which we don't
526379bc100SJani Nikula * support). */
527379bc100SJani Nikula if (crtc_state->pch_pfit.force_thru)
528379bc100SJani Nikula temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
529379bc100SJani Nikula else
530379bc100SJani Nikula temp |= TRANS_DDI_EDP_INPUT_A_ON;
531379bc100SJani Nikula break;
532379bc100SJani Nikula case PIPE_B:
533379bc100SJani Nikula temp |= TRANS_DDI_EDP_INPUT_B_ONOFF;
534379bc100SJani Nikula break;
535379bc100SJani Nikula case PIPE_C:
536379bc100SJani Nikula temp |= TRANS_DDI_EDP_INPUT_C_ONOFF;
537379bc100SJani Nikula break;
538379bc100SJani Nikula }
539379bc100SJani Nikula }
540379bc100SJani Nikula
541379bc100SJani Nikula if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
542379bc100SJani Nikula if (crtc_state->has_hdmi_sink)
543379bc100SJani Nikula temp |= TRANS_DDI_MODE_SELECT_HDMI;
544379bc100SJani Nikula else
545379bc100SJani Nikula temp |= TRANS_DDI_MODE_SELECT_DVI;
546379bc100SJani Nikula
547379bc100SJani Nikula if (crtc_state->hdmi_scrambling)
548379bc100SJani Nikula temp |= TRANS_DDI_HDMI_SCRAMBLING;
549379bc100SJani Nikula if (crtc_state->hdmi_high_tmds_clock_ratio)
550379bc100SJani Nikula temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;
551b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14)
552b66a8abaSAnkit Nautiyal temp |= TRANS_DDI_PORT_WIDTH(crtc_state->lane_count);
553379bc100SJani Nikula } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
5547bb97db8SJani Nikula temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
555379bc100SJani Nikula temp |= (crtc_state->fdi_lanes - 1) << 1;
556379bc100SJani Nikula } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
55765213594SJani Nikula if (intel_dp_is_uhbr(crtc_state))
55865213594SJani Nikula temp |= TRANS_DDI_MODE_SELECT_FDI_OR_128B132B;
55965213594SJani Nikula else
560379bc100SJani Nikula temp |= TRANS_DDI_MODE_SELECT_DP_MST;
561379bc100SJani Nikula temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
562b3545e08SLucas De Marchi
563005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) {
5646671c367SJosé Roberto de Souza enum transcoder master;
5656671c367SJosé Roberto de Souza
5666671c367SJosé Roberto de Souza master = crtc_state->mst_master_transcoder;
5671de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm,
5681de143ccSPankaj Bharadiya master == INVALID_TRANSCODER);
5696671c367SJosé Roberto de Souza temp |= TRANS_DDI_MST_TRANSPORT_SELECT(master);
5706671c367SJosé Roberto de Souza }
571379bc100SJani Nikula } else {
572379bc100SJani Nikula temp |= TRANS_DDI_MODE_SELECT_DP_SST;
573379bc100SJani Nikula temp |= DDI_PORT_WIDTH(crtc_state->lane_count);
574379bc100SJani Nikula }
575379bc100SJani Nikula
57693e7e61eSLucas De Marchi if (IS_DISPLAY_VER(dev_priv, 8, 10) &&
577dc5b8ed5SVille Syrjälä crtc_state->master_transcoder != INVALID_TRANSCODER) {
578dc5b8ed5SVille Syrjälä u8 master_select =
579dc5b8ed5SVille Syrjälä bdw_trans_port_sync_master_select(crtc_state->master_transcoder);
580dc5b8ed5SVille Syrjälä
581dc5b8ed5SVille Syrjälä temp |= TRANS_DDI_PORT_SYNC_ENABLE |
582dc5b8ed5SVille Syrjälä TRANS_DDI_PORT_SYNC_MASTER_SELECT(master_select);
583dc5b8ed5SVille Syrjälä }
584dc5b8ed5SVille Syrjälä
58599389390SJosé Roberto de Souza return temp;
58699389390SJosé Roberto de Souza }
58799389390SJosé Roberto de Souza
intel_ddi_enable_transcoder_func(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)588eed22a46SVille Syrjälä void intel_ddi_enable_transcoder_func(struct intel_encoder *encoder,
589eed22a46SVille Syrjälä const struct intel_crtc_state *crtc_state)
59099389390SJosé Roberto de Souza {
5912225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
59299389390SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
59399389390SJosé Roberto de Souza enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
59499389390SJosé Roberto de Souza
595005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) {
596589a4cd6SVille Syrjälä enum transcoder master_transcoder = crtc_state->master_transcoder;
597589a4cd6SVille Syrjälä u32 ctl2 = 0;
598589a4cd6SVille Syrjälä
599589a4cd6SVille Syrjälä if (master_transcoder != INVALID_TRANSCODER) {
600dc5b8ed5SVille Syrjälä u8 master_select =
601dc5b8ed5SVille Syrjälä bdw_trans_port_sync_master_select(master_transcoder);
602589a4cd6SVille Syrjälä
603589a4cd6SVille Syrjälä ctl2 |= PORT_SYNC_MODE_ENABLE |
604d4d7d9caSVille Syrjälä PORT_SYNC_MODE_MASTER_SELECT(master_select);
605589a4cd6SVille Syrjälä }
606589a4cd6SVille Syrjälä
607589a4cd6SVille Syrjälä intel_de_write(dev_priv,
60876f1b2b1SJani Nikula TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder),
60976f1b2b1SJani Nikula ctl2);
610589a4cd6SVille Syrjälä }
611589a4cd6SVille Syrjälä
612b092d6adSJani Nikula intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
613580fbdc5SImre Deak intel_ddi_transcoder_func_reg_val_get(encoder,
614580fbdc5SImre Deak crtc_state));
61599389390SJosé Roberto de Souza }
61699389390SJosé Roberto de Souza
61799389390SJosé Roberto de Souza /*
61899389390SJosé Roberto de Souza * Same as intel_ddi_enable_transcoder_func(), but it does not set the enable
61999389390SJosé Roberto de Souza * bit.
62099389390SJosé Roberto de Souza */
62199389390SJosé Roberto de Souza static void
intel_ddi_config_transcoder_func(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)622eed22a46SVille Syrjälä intel_ddi_config_transcoder_func(struct intel_encoder *encoder,
623eed22a46SVille Syrjälä const struct intel_crtc_state *crtc_state)
62499389390SJosé Roberto de Souza {
6252225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
62699389390SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
62799389390SJosé Roberto de Souza enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
628589a4cd6SVille Syrjälä u32 ctl;
62999389390SJosé Roberto de Souza
630eed22a46SVille Syrjälä ctl = intel_ddi_transcoder_func_reg_val_get(encoder, crtc_state);
631589a4cd6SVille Syrjälä ctl &= ~TRANS_DDI_FUNC_ENABLE;
632b092d6adSJani Nikula intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
633b092d6adSJani Nikula ctl);
634379bc100SJani Nikula }
635379bc100SJani Nikula
intel_ddi_disable_transcoder_func(const struct intel_crtc_state * crtc_state)636379bc100SJani Nikula void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state)
637379bc100SJani Nikula {
638409c23aeSJani Nikula struct intel_display *display = to_intel_display(crtc_state);
6392225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
640379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
641379bc100SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
642589a4cd6SVille Syrjälä u32 ctl;
643c59053dcSJosé Roberto de Souza
644005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11)
645589a4cd6SVille Syrjälä intel_de_write(dev_priv,
64676f1b2b1SJani Nikula TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder),
64776f1b2b1SJani Nikula 0);
648589a4cd6SVille Syrjälä
649b092d6adSJani Nikula ctl = intel_de_read(dev_priv,
650b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
651dc5b8ed5SVille Syrjälä
6521cfcdbf3SSean Paul drm_WARN_ON(crtc->base.dev, ctl & TRANS_DDI_HDCP_SIGNALLING);
6531cfcdbf3SSean Paul
654589a4cd6SVille Syrjälä ctl &= ~TRANS_DDI_FUNC_ENABLE;
655379bc100SJani Nikula
65693e7e61eSLucas De Marchi if (IS_DISPLAY_VER(dev_priv, 8, 10))
657dc5b8ed5SVille Syrjälä ctl &= ~(TRANS_DDI_PORT_SYNC_ENABLE |
658dc5b8ed5SVille Syrjälä TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK);
659dc5b8ed5SVille Syrjälä
660005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) {
661919e4f07SJosé Roberto de Souza if (!intel_dp_mst_is_master_trans(crtc_state)) {
662589a4cd6SVille Syrjälä ctl &= ~(TGL_TRANS_DDI_PORT_MASK |
663919e4f07SJosé Roberto de Souza TRANS_DDI_MODE_SELECT_MASK);
664919e4f07SJosé Roberto de Souza }
665df16b636SMahesh Kumar } else {
666589a4cd6SVille Syrjälä ctl &= ~(TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK);
667df16b636SMahesh Kumar }
668dc5b8ed5SVille Syrjälä
669b092d6adSJani Nikula intel_de_write(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
670b092d6adSJani Nikula ctl);
671379bc100SJani Nikula
672409c23aeSJani Nikula if (intel_has_quirk(display, QUIRK_INCREASE_DDI_DISABLED_TIME) &&
673379bc100SJani Nikula intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
674409c23aeSJani Nikula drm_dbg_kms(display->drm, "Quirk Increase DDI disabled time\n");
675379bc100SJani Nikula /* Quirk time at 100ms for reliable operation */
676379bc100SJani Nikula msleep(100);
677379bc100SJani Nikula }
678379bc100SJani Nikula }
679379bc100SJani Nikula
intel_ddi_toggle_hdcp_bits(struct intel_encoder * intel_encoder,enum transcoder cpu_transcoder,bool enable,u32 hdcp_mask)6801a67a168SAnshuman Gupta int intel_ddi_toggle_hdcp_bits(struct intel_encoder *intel_encoder,
6810b9c9290SSean Paul enum transcoder cpu_transcoder,
6821a67a168SAnshuman Gupta bool enable, u32 hdcp_mask)
683379bc100SJani Nikula {
684379bc100SJani Nikula struct drm_device *dev = intel_encoder->base.dev;
685379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(dev);
686379bc100SJani Nikula intel_wakeref_t wakeref;
687379bc100SJani Nikula int ret = 0;
688379bc100SJani Nikula
689379bc100SJani Nikula wakeref = intel_display_power_get_if_enabled(dev_priv,
690379bc100SJani Nikula intel_encoder->power_domain);
6911de143ccSPankaj Bharadiya if (drm_WARN_ON(dev, !wakeref))
692379bc100SJani Nikula return -ENXIO;
693379bc100SJani Nikula
694b092d6adSJani Nikula intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
6958910d8b7SAndrzej Hajda hdcp_mask, enable ? hdcp_mask : 0);
696379bc100SJani Nikula intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);
697379bc100SJani Nikula return ret;
698379bc100SJani Nikula }
699379bc100SJani Nikula
intel_ddi_connector_get_hw_state(struct intel_connector * intel_connector)700379bc100SJani Nikula bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
701379bc100SJani Nikula {
702379bc100SJani Nikula struct drm_device *dev = intel_connector->base.dev;
703379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(dev);
704fa7edcd2SVille Syrjälä struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
705379bc100SJani Nikula int type = intel_connector->base.connector_type;
706379bc100SJani Nikula enum port port = encoder->port;
707379bc100SJani Nikula enum transcoder cpu_transcoder;
708379bc100SJani Nikula intel_wakeref_t wakeref;
709379bc100SJani Nikula enum pipe pipe = 0;
710379bc100SJani Nikula u32 tmp;
711379bc100SJani Nikula bool ret;
712379bc100SJani Nikula
713379bc100SJani Nikula wakeref = intel_display_power_get_if_enabled(dev_priv,
714379bc100SJani Nikula encoder->power_domain);
715379bc100SJani Nikula if (!wakeref)
716379bc100SJani Nikula return false;
717379bc100SJani Nikula
718379bc100SJani Nikula if (!encoder->get_hw_state(encoder, &pipe)) {
719379bc100SJani Nikula ret = false;
720379bc100SJani Nikula goto out;
721379bc100SJani Nikula }
722379bc100SJani Nikula
72310cf8e75SVille Syrjälä if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
724379bc100SJani Nikula cpu_transcoder = TRANSCODER_EDP;
725379bc100SJani Nikula else
726379bc100SJani Nikula cpu_transcoder = (enum transcoder) pipe;
727379bc100SJani Nikula
728b092d6adSJani Nikula tmp = intel_de_read(dev_priv,
729b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
730379bc100SJani Nikula
731379bc100SJani Nikula switch (tmp & TRANS_DDI_MODE_SELECT_MASK) {
732379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_HDMI:
733379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DVI:
734379bc100SJani Nikula ret = type == DRM_MODE_CONNECTOR_HDMIA;
735379bc100SJani Nikula break;
736379bc100SJani Nikula
737379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DP_SST:
738379bc100SJani Nikula ret = type == DRM_MODE_CONNECTOR_eDP ||
739379bc100SJani Nikula type == DRM_MODE_CONNECTOR_DisplayPort;
740379bc100SJani Nikula break;
741379bc100SJani Nikula
742379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DP_MST:
743379bc100SJani Nikula /* if the transcoder is in MST state then
744379bc100SJani Nikula * connector isn't connected */
745379bc100SJani Nikula ret = false;
746379bc100SJani Nikula break;
747379bc100SJani Nikula
7487bb97db8SJani Nikula case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
74965213594SJani Nikula if (HAS_DP20(dev_priv))
75065213594SJani Nikula /* 128b/132b */
75165213594SJani Nikula ret = false;
75265213594SJani Nikula else
75365213594SJani Nikula /* FDI */
754379bc100SJani Nikula ret = type == DRM_MODE_CONNECTOR_VGA;
755379bc100SJani Nikula break;
756379bc100SJani Nikula
757379bc100SJani Nikula default:
758379bc100SJani Nikula ret = false;
759379bc100SJani Nikula break;
760379bc100SJani Nikula }
761379bc100SJani Nikula
762379bc100SJani Nikula out:
763379bc100SJani Nikula intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
764379bc100SJani Nikula
765379bc100SJani Nikula return ret;
766379bc100SJani Nikula }
767379bc100SJani Nikula
intel_ddi_get_encoder_pipes(struct intel_encoder * encoder,u8 * pipe_mask,bool * is_dp_mst)768379bc100SJani Nikula static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,
769379bc100SJani Nikula u8 *pipe_mask, bool *is_dp_mst)
770379bc100SJani Nikula {
771379bc100SJani Nikula struct drm_device *dev = encoder->base.dev;
772379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(dev);
773379bc100SJani Nikula enum port port = encoder->port;
774379bc100SJani Nikula intel_wakeref_t wakeref;
775379bc100SJani Nikula enum pipe p;
776379bc100SJani Nikula u32 tmp;
777379bc100SJani Nikula u8 mst_pipe_mask;
778379bc100SJani Nikula
779379bc100SJani Nikula *pipe_mask = 0;
780379bc100SJani Nikula *is_dp_mst = false;
781379bc100SJani Nikula
782379bc100SJani Nikula wakeref = intel_display_power_get_if_enabled(dev_priv,
783379bc100SJani Nikula encoder->power_domain);
784379bc100SJani Nikula if (!wakeref)
785379bc100SJani Nikula return;
786379bc100SJani Nikula
787f7960e7fSJani Nikula tmp = intel_de_read(dev_priv, DDI_BUF_CTL(port));
788379bc100SJani Nikula if (!(tmp & DDI_BUF_CTL_ENABLE))
789379bc100SJani Nikula goto out;
790379bc100SJani Nikula
79110cf8e75SVille Syrjälä if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A) {
792f7960e7fSJani Nikula tmp = intel_de_read(dev_priv,
793b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, TRANSCODER_EDP));
794379bc100SJani Nikula
795379bc100SJani Nikula switch (tmp & TRANS_DDI_EDP_INPUT_MASK) {
796379bc100SJani Nikula default:
797379bc100SJani Nikula MISSING_CASE(tmp & TRANS_DDI_EDP_INPUT_MASK);
798df561f66SGustavo A. R. Silva fallthrough;
799379bc100SJani Nikula case TRANS_DDI_EDP_INPUT_A_ON:
800379bc100SJani Nikula case TRANS_DDI_EDP_INPUT_A_ONOFF:
801379bc100SJani Nikula *pipe_mask = BIT(PIPE_A);
802379bc100SJani Nikula break;
803379bc100SJani Nikula case TRANS_DDI_EDP_INPUT_B_ONOFF:
804379bc100SJani Nikula *pipe_mask = BIT(PIPE_B);
805379bc100SJani Nikula break;
806379bc100SJani Nikula case TRANS_DDI_EDP_INPUT_C_ONOFF:
807379bc100SJani Nikula *pipe_mask = BIT(PIPE_C);
808379bc100SJani Nikula break;
809379bc100SJani Nikula }
810379bc100SJani Nikula
811379bc100SJani Nikula goto out;
812379bc100SJani Nikula }
813379bc100SJani Nikula
814379bc100SJani Nikula mst_pipe_mask = 0;
815379bc100SJani Nikula for_each_pipe(dev_priv, p) {
816379bc100SJani Nikula enum transcoder cpu_transcoder = (enum transcoder)p;
817df16b636SMahesh Kumar unsigned int port_mask, ddi_select;
8186aa3bef1SJosé Roberto de Souza intel_wakeref_t trans_wakeref;
8196aa3bef1SJosé Roberto de Souza
8206aa3bef1SJosé Roberto de Souza trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
8216aa3bef1SJosé Roberto de Souza POWER_DOMAIN_TRANSCODER(cpu_transcoder));
8226aa3bef1SJosé Roberto de Souza if (!trans_wakeref)
8236aa3bef1SJosé Roberto de Souza continue;
824df16b636SMahesh Kumar
825005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) {
826df16b636SMahesh Kumar port_mask = TGL_TRANS_DDI_PORT_MASK;
827df16b636SMahesh Kumar ddi_select = TGL_TRANS_DDI_SELECT_PORT(port);
828df16b636SMahesh Kumar } else {
829df16b636SMahesh Kumar port_mask = TRANS_DDI_PORT_MASK;
830df16b636SMahesh Kumar ddi_select = TRANS_DDI_SELECT_PORT(port);
831df16b636SMahesh Kumar }
832379bc100SJani Nikula
833f7960e7fSJani Nikula tmp = intel_de_read(dev_priv,
834b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
8356aa3bef1SJosé Roberto de Souza intel_display_power_put(dev_priv, POWER_DOMAIN_TRANSCODER(cpu_transcoder),
8366aa3bef1SJosé Roberto de Souza trans_wakeref);
837379bc100SJani Nikula
838df16b636SMahesh Kumar if ((tmp & port_mask) != ddi_select)
839379bc100SJani Nikula continue;
840379bc100SJani Nikula
84165213594SJani Nikula if ((tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_DP_MST ||
84265213594SJani Nikula (HAS_DP20(dev_priv) &&
84365213594SJani Nikula (tmp & TRANS_DDI_MODE_SELECT_MASK) == TRANS_DDI_MODE_SELECT_FDI_OR_128B132B))
844379bc100SJani Nikula mst_pipe_mask |= BIT(p);
845379bc100SJani Nikula
846379bc100SJani Nikula *pipe_mask |= BIT(p);
847379bc100SJani Nikula }
848379bc100SJani Nikula
849379bc100SJani Nikula if (!*pipe_mask)
85047bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm,
85147bdb1caSJani Nikula "No pipe for [ENCODER:%d:%s] found\n",
85266a990ddSVille Syrjälä encoder->base.base.id, encoder->base.name);
853379bc100SJani Nikula
854379bc100SJani Nikula if (!mst_pipe_mask && hweight8(*pipe_mask) > 1) {
85547bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm,
85647bdb1caSJani Nikula "Multiple pipes for [ENCODER:%d:%s] (pipe_mask %02x)\n",
85766a990ddSVille Syrjälä encoder->base.base.id, encoder->base.name,
85866a990ddSVille Syrjälä *pipe_mask);
859379bc100SJani Nikula *pipe_mask = BIT(ffs(*pipe_mask) - 1);
860379bc100SJani Nikula }
861379bc100SJani Nikula
862379bc100SJani Nikula if (mst_pipe_mask && mst_pipe_mask != *pipe_mask)
86347bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm,
86447bdb1caSJani Nikula "Conflicting MST and non-MST state for [ENCODER:%d:%s] (pipe_mask %02x mst_pipe_mask %02x)\n",
86566a990ddSVille Syrjälä encoder->base.base.id, encoder->base.name,
86666a990ddSVille Syrjälä *pipe_mask, mst_pipe_mask);
867379bc100SJani Nikula else
868379bc100SJani Nikula *is_dp_mst = mst_pipe_mask;
869379bc100SJani Nikula
870379bc100SJani Nikula out:
8712446e1d6SMatt Roper if (*pipe_mask && (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))) {
872f7960e7fSJani Nikula tmp = intel_de_read(dev_priv, BXT_PHY_CTL(port));
873379bc100SJani Nikula if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
874379bc100SJani Nikula BXT_PHY_LANE_POWERDOWN_ACK |
875379bc100SJani Nikula BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED)
87647bdb1caSJani Nikula drm_err(&dev_priv->drm,
87747bdb1caSJani Nikula "[ENCODER:%d:%s] enabled but PHY powered down? (PHY_CTL %08x)\n",
87847bdb1caSJani Nikula encoder->base.base.id, encoder->base.name, tmp);
879379bc100SJani Nikula }
880379bc100SJani Nikula
881379bc100SJani Nikula intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
882379bc100SJani Nikula }
883379bc100SJani Nikula
intel_ddi_get_hw_state(struct intel_encoder * encoder,enum pipe * pipe)884379bc100SJani Nikula bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
885379bc100SJani Nikula enum pipe *pipe)
886379bc100SJani Nikula {
887379bc100SJani Nikula u8 pipe_mask;
888379bc100SJani Nikula bool is_mst;
889379bc100SJani Nikula
890379bc100SJani Nikula intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
891379bc100SJani Nikula
892379bc100SJani Nikula if (is_mst || !pipe_mask)
893379bc100SJani Nikula return false;
894379bc100SJani Nikula
895379bc100SJani Nikula *pipe = ffs(pipe_mask) - 1;
896379bc100SJani Nikula
897379bc100SJani Nikula return true;
898379bc100SJani Nikula }
899379bc100SJani Nikula
90081b55ef1SJani Nikula static enum intel_display_power_domain
intel_ddi_main_link_aux_domain(struct intel_digital_port * dig_port,const struct intel_crtc_state * crtc_state)901637c7aa2SImre Deak intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port,
902637c7aa2SImre Deak const struct intel_crtc_state *crtc_state)
903379bc100SJani Nikula {
904f645cbdaSImre Deak struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
905f645cbdaSImre Deak
906637c7aa2SImre Deak /*
907637c7aa2SImre Deak * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
908379bc100SJani Nikula * DC states enabled at the same time, while for driver initiated AUX
909379bc100SJani Nikula * transfers we need the same AUX IOs to be powered but with DC states
910637c7aa2SImre Deak * disabled. Accordingly use the AUX_IO_<port> power domain here which
911637c7aa2SImre Deak * leaves DC states enabled.
912637c7aa2SImre Deak *
913637c7aa2SImre Deak * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require
914637c7aa2SImre Deak * AUX IO to be enabled, but all these require DC_OFF to be enabled as
915637c7aa2SImre Deak * well, so we can acquire a wider AUX_<port> power domain reference
916637c7aa2SImre Deak * instead of a specific AUX_IO_<port> reference without powering up any
917637c7aa2SImre Deak * extra wells.
918379bc100SJani Nikula */
919*ec2231b8SImre Deak if (intel_psr_needs_aux_io_power(&dig_port->base, crtc_state))
920f645cbdaSImre Deak return intel_display_power_aux_io_domain(i915, dig_port->aux_ch);
9211acefacaSImre Deak else if (DISPLAY_VER(i915) < 14 &&
9221acefacaSImre Deak (intel_crtc_has_dp_encoder(crtc_state) ||
9237fcf7558SJani Nikula intel_encoder_is_tc(&dig_port->base)))
924b2e00dd3SImre Deak return intel_aux_power_domain(dig_port);
925637c7aa2SImre Deak else
926637c7aa2SImre Deak return POWER_DOMAIN_INVALID;
927637c7aa2SImre Deak }
928637c7aa2SImre Deak
929637c7aa2SImre Deak static void
main_link_aux_power_domain_get(struct intel_digital_port * dig_port,const struct intel_crtc_state * crtc_state)930637c7aa2SImre Deak main_link_aux_power_domain_get(struct intel_digital_port *dig_port,
931637c7aa2SImre Deak const struct intel_crtc_state *crtc_state)
932637c7aa2SImre Deak {
933637c7aa2SImre Deak struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
934637c7aa2SImre Deak enum intel_display_power_domain domain =
935637c7aa2SImre Deak intel_ddi_main_link_aux_domain(dig_port, crtc_state);
936637c7aa2SImre Deak
937637c7aa2SImre Deak drm_WARN_ON(&i915->drm, dig_port->aux_wakeref);
938637c7aa2SImre Deak
939637c7aa2SImre Deak if (domain == POWER_DOMAIN_INVALID)
940637c7aa2SImre Deak return;
941637c7aa2SImre Deak
942637c7aa2SImre Deak dig_port->aux_wakeref = intel_display_power_get(i915, domain);
943637c7aa2SImre Deak }
944637c7aa2SImre Deak
945637c7aa2SImre Deak static void
main_link_aux_power_domain_put(struct intel_digital_port * dig_port,const struct intel_crtc_state * crtc_state)946637c7aa2SImre Deak main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
947637c7aa2SImre Deak const struct intel_crtc_state *crtc_state)
948637c7aa2SImre Deak {
949637c7aa2SImre Deak struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
950637c7aa2SImre Deak enum intel_display_power_domain domain =
951637c7aa2SImre Deak intel_ddi_main_link_aux_domain(dig_port, crtc_state);
952637c7aa2SImre Deak intel_wakeref_t wf;
953637c7aa2SImre Deak
954637c7aa2SImre Deak wf = fetch_and_zero(&dig_port->aux_wakeref);
955637c7aa2SImre Deak if (!wf)
956637c7aa2SImre Deak return;
957637c7aa2SImre Deak
958637c7aa2SImre Deak intel_display_power_put(i915, domain, wf);
959379bc100SJani Nikula }
960379bc100SJani Nikula
intel_ddi_get_power_domains(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)961379bc100SJani Nikula static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
962379bc100SJani Nikula struct intel_crtc_state *crtc_state)
963379bc100SJani Nikula {
964379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
965379bc100SJani Nikula struct intel_digital_port *dig_port;
966379bc100SJani Nikula
967379bc100SJani Nikula /*
968379bc100SJani Nikula * TODO: Add support for MST encoders. Atm, the following should never
969379bc100SJani Nikula * happen since fake-MST encoders don't set their get_power_domains()
970379bc100SJani Nikula * hook.
971379bc100SJani Nikula */
9721de143ccSPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm,
9731de143ccSPankaj Bharadiya intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)))
974379bc100SJani Nikula return;
975379bc100SJani Nikula
976b7d02c3aSVille Syrjälä dig_port = enc_to_dig_port(encoder);
977f77a2db2SImre Deak
97811a89708SImre Deak if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
979a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
980a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
981f77a2db2SImre Deak dig_port->ddi_io_power_domain);
982a4550977SImre Deak }
983379bc100SJani Nikula
984637c7aa2SImre Deak main_link_aux_power_domain_get(dig_port, crtc_state);
985162e68e1SImre Deak }
986379bc100SJani Nikula
intel_ddi_enable_transcoder_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)98755a4679eSVille Syrjälä void intel_ddi_enable_transcoder_clock(struct intel_encoder *encoder,
98802a715c3SVille Syrjälä const struct intel_crtc_state *crtc_state)
989379bc100SJani Nikula {
9902225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
991379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
992379bc100SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
9937fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
994ed2615a8SMatt Roper u32 val;
995379bc100SJani Nikula
99648630a31SVille Syrjälä if (cpu_transcoder == TRANSCODER_EDP)
99748630a31SVille Syrjälä return;
99848630a31SVille Syrjälä
999ed2615a8SMatt Roper if (DISPLAY_VER(dev_priv) >= 13)
1000ed2615a8SMatt Roper val = TGL_TRANS_CLK_SEL_PORT(phy);
1001ed2615a8SMatt Roper else if (DISPLAY_VER(dev_priv) >= 12)
1002ed2615a8SMatt Roper val = TGL_TRANS_CLK_SEL_PORT(encoder->port);
1003df16b636SMahesh Kumar else
1004ed2615a8SMatt Roper val = TRANS_CLK_SEL_PORT(encoder->port);
1005ed2615a8SMatt Roper
1006ed2615a8SMatt Roper intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
1007379bc100SJani Nikula }
1008379bc100SJani Nikula
intel_ddi_disable_transcoder_clock(const struct intel_crtc_state * crtc_state)100955a4679eSVille Syrjälä void intel_ddi_disable_transcoder_clock(const struct intel_crtc_state *crtc_state)
1010379bc100SJani Nikula {
10112225f3c6SMaarten Lankhorst struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
1012379bc100SJani Nikula enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
101348630a31SVille Syrjälä u32 val;
1014379bc100SJani Nikula
101548630a31SVille Syrjälä if (cpu_transcoder == TRANSCODER_EDP)
101648630a31SVille Syrjälä return;
101748630a31SVille Syrjälä
1018005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12)
101948630a31SVille Syrjälä val = TGL_TRANS_CLK_SEL_DISABLED;
1020df16b636SMahesh Kumar else
102148630a31SVille Syrjälä val = TRANS_CLK_SEL_DISABLED;
102248630a31SVille Syrjälä
102348630a31SVille Syrjälä intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val);
1024df16b636SMahesh Kumar }
1025379bc100SJani Nikula
_skl_ddi_set_iboost(struct drm_i915_private * dev_priv,enum port port,u8 iboost)1026379bc100SJani Nikula static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv,
1027379bc100SJani Nikula enum port port, u8 iboost)
1028379bc100SJani Nikula {
1029379bc100SJani Nikula u32 tmp;
1030379bc100SJani Nikula
1031f7960e7fSJani Nikula tmp = intel_de_read(dev_priv, DISPIO_CR_TX_BMU_CR0);
1032379bc100SJani Nikula tmp &= ~(BALANCE_LEG_MASK(port) | BALANCE_LEG_DISABLE(port));
1033379bc100SJani Nikula if (iboost)
1034379bc100SJani Nikula tmp |= iboost << BALANCE_LEG_SHIFT(port);
1035379bc100SJani Nikula else
1036379bc100SJani Nikula tmp |= BALANCE_LEG_DISABLE(port);
1037f7960e7fSJani Nikula intel_de_write(dev_priv, DISPIO_CR_TX_BMU_CR0, tmp);
1038379bc100SJani Nikula }
1039379bc100SJani Nikula
skl_ddi_set_iboost(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,int level)1040379bc100SJani Nikula static void skl_ddi_set_iboost(struct intel_encoder *encoder,
1041a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state,
1042a621860aSVille Syrjälä int level)
1043379bc100SJani Nikula {
10447801f3b7SLucas De Marchi struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
1045379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1046379bc100SJani Nikula u8 iboost;
1047379bc100SJani Nikula
1048a621860aSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
104902107ef1SVille Syrjälä iboost = intel_bios_hdmi_boost_level(encoder->devdata);
1050379bc100SJani Nikula else
105102107ef1SVille Syrjälä iboost = intel_bios_dp_boost_level(encoder->devdata);
1052379bc100SJani Nikula
1053379bc100SJani Nikula if (iboost == 0) {
1054e505d764SVille Syrjälä const struct intel_ddi_buf_trans *trans;
1055379bc100SJani Nikula int n_entries;
1056379bc100SJani Nikula
1057e505d764SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1058e505d764SVille Syrjälä if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
1059379bc100SJani Nikula return;
1060379bc100SJani Nikula
1061e505d764SVille Syrjälä iboost = trans->entries[level].hsw.i_boost;
1062379bc100SJani Nikula }
1063379bc100SJani Nikula
1064379bc100SJani Nikula /* Make sure that the requested I_boost is valid */
1065379bc100SJani Nikula if (iboost && iboost != 0x1 && iboost != 0x3 && iboost != 0x7) {
106647bdb1caSJani Nikula drm_err(&dev_priv->drm, "Invalid I_boost value %u\n", iboost);
1067379bc100SJani Nikula return;
1068379bc100SJani Nikula }
1069379bc100SJani Nikula
1070f0e86e05SJosé Roberto de Souza _skl_ddi_set_iboost(dev_priv, encoder->port, iboost);
1071379bc100SJani Nikula
1072f0e86e05SJosé Roberto de Souza if (encoder->port == PORT_A && dig_port->max_lanes == 4)
1073379bc100SJani Nikula _skl_ddi_set_iboost(dev_priv, PORT_E, iboost);
1074379bc100SJani Nikula }
1075379bc100SJani Nikula
intel_ddi_dp_voltage_max(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state)1076a621860aSVille Syrjälä static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp,
1077a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state)
1078379bc100SJani Nikula {
107953de0a20SVille Syrjälä struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
1080379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1081379bc100SJani Nikula int n_entries;
1082379bc100SJani Nikula
1083c40a253bSVille Syrjälä encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1084379bc100SJani Nikula
10851de143ccSPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, n_entries < 1))
1086379bc100SJani Nikula n_entries = 1;
10871de143ccSPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm,
10881de143ccSPankaj Bharadiya n_entries > ARRAY_SIZE(index_to_dp_signal_levels)))
1089379bc100SJani Nikula n_entries = ARRAY_SIZE(index_to_dp_signal_levels);
1090379bc100SJani Nikula
1091379bc100SJani Nikula return index_to_dp_signal_levels[n_entries - 1] &
1092379bc100SJani Nikula DP_TRAIN_VOLTAGE_SWING_MASK;
1093379bc100SJani Nikula }
1094379bc100SJani Nikula
1095379bc100SJani Nikula /*
1096379bc100SJani Nikula * We assume that the full set of pre-emphasis values can be
1097379bc100SJani Nikula * used on all DDI platforms. Should that change we need to
1098379bc100SJani Nikula * rethink this code.
1099379bc100SJani Nikula */
intel_ddi_dp_preemph_max(struct intel_dp * intel_dp)110053de0a20SVille Syrjälä static u8 intel_ddi_dp_preemph_max(struct intel_dp *intel_dp)
1101379bc100SJani Nikula {
1102379bc100SJani Nikula return DP_TRAIN_PRE_EMPH_LEVEL_3;
1103379bc100SJani Nikula }
1104379bc100SJani Nikula
icl_combo_phy_loadgen_select(const struct intel_crtc_state * crtc_state,int lane)11055e7fe4d9SVille Syrjälä static u32 icl_combo_phy_loadgen_select(const struct intel_crtc_state *crtc_state,
11065e7fe4d9SVille Syrjälä int lane)
11075e7fe4d9SVille Syrjälä {
11085e7fe4d9SVille Syrjälä if (crtc_state->port_clock > 600000)
11095e7fe4d9SVille Syrjälä return 0;
11105e7fe4d9SVille Syrjälä
11115e7fe4d9SVille Syrjälä if (crtc_state->lane_count == 4)
11125e7fe4d9SVille Syrjälä return lane >= 1 ? LOADGEN_SELECT : 0;
11135e7fe4d9SVille Syrjälä else
11145e7fe4d9SVille Syrjälä return lane == 1 || lane == 2 ? LOADGEN_SELECT : 0;
11155e7fe4d9SVille Syrjälä }
11165e7fe4d9SVille Syrjälä
icl_ddi_combo_vswing_program(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1117a8143150SJosé Roberto de Souza static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder,
1118193299adSVille Syrjälä const struct intel_crtc_state *crtc_state)
1119379bc100SJani Nikula {
1120a8143150SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1121e505d764SVille Syrjälä const struct intel_ddi_buf_trans *trans;
11227fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1123a621860aSVille Syrjälä int n_entries, ln;
1124a621860aSVille Syrjälä u32 val;
1125379bc100SJani Nikula
1126e505d764SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1127e505d764SVille Syrjälä if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
112885da0292SVille Syrjälä return;
1129379bc100SJani Nikula
1130a621860aSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) {
113181619f4aSJosé Roberto de Souza struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
113281619f4aSJosé Roberto de Souza
113381619f4aSJosé Roberto de Souza val = EDP4K2K_MODE_OVRD_EN | EDP4K2K_MODE_OVRD_OPTIMIZED;
1134e505d764SVille Syrjälä intel_dp->hobl_active = is_hobl_buf_trans(trans);
113581619f4aSJosé Roberto de Souza intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy), val,
113681619f4aSJosé Roberto de Souza intel_dp->hobl_active ? val : 0);
113781619f4aSJosé Roberto de Souza }
113881619f4aSJosé Roberto de Souza
1139379bc100SJani Nikula /* Set PORT_TX_DW5 */
1140e6908588SVille Syrjälä val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1141379bc100SJani Nikula val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
1142379bc100SJani Nikula TAP2_DISABLE | TAP3_DISABLE);
1143379bc100SJani Nikula val |= SCALING_MODE_SEL(0x2);
1144379bc100SJani Nikula val |= RTERM_SELECT(0x6);
1145379bc100SJani Nikula val |= TAP3_DISABLE;
1146f7960e7fSJani Nikula intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1147379bc100SJani Nikula
1148379bc100SJani Nikula /* Program PORT_TX_DW2 */
1149f20ca899SVille Syrjälä for (ln = 0; ln < 4; ln++) {
115031e914a2SVille Syrjälä int level = intel_ddi_level(encoder, crtc_state, ln);
115131e914a2SVille Syrjälä
1152c1d53cbdSVille Syrjälä intel_de_rmw(dev_priv, ICL_PORT_TX_DW2_LN(ln, phy),
1153c1d53cbdSVille Syrjälä SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK | RCOMP_SCALAR_MASK,
1154c1d53cbdSVille Syrjälä SWING_SEL_UPPER(trans->entries[level].icl.dw2_swing_sel) |
1155c1d53cbdSVille Syrjälä SWING_SEL_LOWER(trans->entries[level].icl.dw2_swing_sel) |
1156c1d53cbdSVille Syrjälä RCOMP_SCALAR(0x98));
1157f20ca899SVille Syrjälä }
1158379bc100SJani Nikula
1159379bc100SJani Nikula /* Program PORT_TX_DW4 */
1160379bc100SJani Nikula /* We cannot write to GRP. It would overwrite individual loadgen. */
1161a1f01768SVille Syrjälä for (ln = 0; ln < 4; ln++) {
116231e914a2SVille Syrjälä int level = intel_ddi_level(encoder, crtc_state, ln);
116331e914a2SVille Syrjälä
1164c1d53cbdSVille Syrjälä intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1165c1d53cbdSVille Syrjälä POST_CURSOR_1_MASK | POST_CURSOR_2_MASK | CURSOR_COEFF_MASK,
1166c1d53cbdSVille Syrjälä POST_CURSOR_1(trans->entries[level].icl.dw4_post_cursor_1) |
1167c1d53cbdSVille Syrjälä POST_CURSOR_2(trans->entries[level].icl.dw4_post_cursor_2) |
1168c1d53cbdSVille Syrjälä CURSOR_COEFF(trans->entries[level].icl.dw4_cursor_coeff));
1169379bc100SJani Nikula }
1170379bc100SJani Nikula
1171379bc100SJani Nikula /* Program PORT_TX_DW7 */
1172f20ca899SVille Syrjälä for (ln = 0; ln < 4; ln++) {
117331e914a2SVille Syrjälä int level = intel_ddi_level(encoder, crtc_state, ln);
117431e914a2SVille Syrjälä
1175c1d53cbdSVille Syrjälä intel_de_rmw(dev_priv, ICL_PORT_TX_DW7_LN(ln, phy),
1176c1d53cbdSVille Syrjälä N_SCALAR_MASK,
1177c1d53cbdSVille Syrjälä N_SCALAR(trans->entries[level].icl.dw7_n_scalar));
1178f20ca899SVille Syrjälä }
1179379bc100SJani Nikula }
1180379bc100SJani Nikula
icl_combo_phy_set_signal_levels(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1181193299adSVille Syrjälä static void icl_combo_phy_set_signal_levels(struct intel_encoder *encoder,
1182193299adSVille Syrjälä const struct intel_crtc_state *crtc_state)
1183379bc100SJani Nikula {
1184379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
11857fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1186379bc100SJani Nikula u32 val;
11875e7fe4d9SVille Syrjälä int ln;
1188379bc100SJani Nikula
1189379bc100SJani Nikula /*
1190379bc100SJani Nikula * 1. If port type is eDP or DP,
1191379bc100SJani Nikula * set PORT_PCS_DW1 cmnkeeper_enable to 1b,
1192379bc100SJani Nikula * else clear to 0b.
1193379bc100SJani Nikula */
1194e6908588SVille Syrjälä val = intel_de_read(dev_priv, ICL_PORT_PCS_DW1_LN(0, phy));
1195a621860aSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1196379bc100SJani Nikula val &= ~COMMON_KEEPER_EN;
1197379bc100SJani Nikula else
1198379bc100SJani Nikula val |= COMMON_KEEPER_EN;
1199f7960e7fSJani Nikula intel_de_write(dev_priv, ICL_PORT_PCS_DW1_GRP(phy), val);
1200379bc100SJani Nikula
1201379bc100SJani Nikula /* 2. Program loadgen select */
1202379bc100SJani Nikula /*
1203e6908588SVille Syrjälä * Program PORT_TX_DW4 depending on Bit rate and used lanes
1204379bc100SJani Nikula * <= 6 GHz and 4 lanes (LN0=0, LN1=1, LN2=1, LN3=1)
1205379bc100SJani Nikula * <= 6 GHz and 1,2 lanes (LN0=0, LN1=1, LN2=1, LN3=0)
1206379bc100SJani Nikula * > 6 GHz (LN0=0, LN1=0, LN2=0, LN3=0)
1207379bc100SJani Nikula */
1208a1f01768SVille Syrjälä for (ln = 0; ln < 4; ln++) {
1209c1d53cbdSVille Syrjälä intel_de_rmw(dev_priv, ICL_PORT_TX_DW4_LN(ln, phy),
1210c1d53cbdSVille Syrjälä LOADGEN_SELECT,
1211c1d53cbdSVille Syrjälä icl_combo_phy_loadgen_select(crtc_state, ln));
1212379bc100SJani Nikula }
1213379bc100SJani Nikula
1214379bc100SJani Nikula /* 3. Set PORT_CL_DW5 SUS Clock Config to 11b */
1215c1d53cbdSVille Syrjälä intel_de_rmw(dev_priv, ICL_PORT_CL_DW5(phy),
1216c1d53cbdSVille Syrjälä 0, SUS_CLOCK_CONFIG);
1217379bc100SJani Nikula
1218379bc100SJani Nikula /* 4. Clear training enable to change swing values */
1219e6908588SVille Syrjälä val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1220379bc100SJani Nikula val &= ~TX_TRAINING_EN;
1221f7960e7fSJani Nikula intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1222379bc100SJani Nikula
1223379bc100SJani Nikula /* 5. Program swing and de-emphasis */
1224193299adSVille Syrjälä icl_ddi_combo_vswing_program(encoder, crtc_state);
1225379bc100SJani Nikula
1226379bc100SJani Nikula /* 6. Set training enable to trigger update */
1227e6908588SVille Syrjälä val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN(0, phy));
1228379bc100SJani Nikula val |= TX_TRAINING_EN;
1229f7960e7fSJani Nikula intel_de_write(dev_priv, ICL_PORT_TX_DW5_GRP(phy), val);
1230379bc100SJani Nikula }
1231379bc100SJani Nikula
icl_mg_phy_set_signal_levels(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1232193299adSVille Syrjälä static void icl_mg_phy_set_signal_levels(struct intel_encoder *encoder,
1233193299adSVille Syrjälä const struct intel_crtc_state *crtc_state)
1234379bc100SJani Nikula {
1235379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
12367fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
1237e505d764SVille Syrjälä const struct intel_ddi_buf_trans *trans;
1238a621860aSVille Syrjälä int n_entries, ln;
1239379bc100SJani Nikula
124011a89708SImre Deak if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1241f8c6b615SVille Syrjälä return;
1242f8c6b615SVille Syrjälä
1243e505d764SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1244e505d764SVille Syrjälä if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
124585da0292SVille Syrjälä return;
1246379bc100SJani Nikula
1247379bc100SJani Nikula for (ln = 0; ln < 2; ln++) {
1248d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX1_LINK_PARAMS(ln, tc_port),
1249d4e0f163SVille Syrjälä CRI_USE_FS32, 0);
1250d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX2_LINK_PARAMS(ln, tc_port),
1251d4e0f163SVille Syrjälä CRI_USE_FS32, 0);
1252379bc100SJani Nikula }
1253379bc100SJani Nikula
1254379bc100SJani Nikula /* Program MG_TX_SWINGCTRL with values from vswing table */
1255379bc100SJani Nikula for (ln = 0; ln < 2; ln++) {
1256305448e5SVille Syrjälä int level;
1257305448e5SVille Syrjälä
1258305448e5SVille Syrjälä level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1259305448e5SVille Syrjälä
1260d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX1_SWINGCTRL(ln, tc_port),
1261d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1262d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1263379bc100SJani Nikula
1264305448e5SVille Syrjälä level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1265305448e5SVille Syrjälä
1266d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX2_SWINGCTRL(ln, tc_port),
1267d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_17_12_MASK,
1268d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_17_12(trans->entries[level].mg.cri_txdeemph_override_17_12));
1269379bc100SJani Nikula }
1270379bc100SJani Nikula
1271379bc100SJani Nikula /* Program MG_TX_DRVCTRL with values from vswing table */
1272379bc100SJani Nikula for (ln = 0; ln < 2; ln++) {
1273305448e5SVille Syrjälä int level;
1274305448e5SVille Syrjälä
1275305448e5SVille Syrjälä level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1276305448e5SVille Syrjälä
1277d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX1_DRVCTRL(ln, tc_port),
1278d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1279d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1280d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1281d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1282d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_EN);
1283379bc100SJani Nikula
1284305448e5SVille Syrjälä level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1285305448e5SVille Syrjälä
1286d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX2_DRVCTRL(ln, tc_port),
1287d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_11_6_MASK |
1288d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_5_0_MASK,
1289d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_11_6(trans->entries[level].mg.cri_txdeemph_override_11_6) |
1290d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_5_0(trans->entries[level].mg.cri_txdeemph_override_5_0) |
1291d4e0f163SVille Syrjälä CRI_TXDEEMPH_OVERRIDE_EN);
1292379bc100SJani Nikula
1293379bc100SJani Nikula /* FIXME: Program CRI_LOADGEN_SEL after the spec is updated */
1294379bc100SJani Nikula }
1295379bc100SJani Nikula
1296379bc100SJani Nikula /*
1297379bc100SJani Nikula * Program MG_CLKHUB<LN, port being used> with value from frequency table
1298379bc100SJani Nikula * In case of Legacy mode on MG PHY, both TX1 and TX2 enabled so use the
1299379bc100SJani Nikula * values from table for which TX1 and TX2 enabled.
1300379bc100SJani Nikula */
1301379bc100SJani Nikula for (ln = 0; ln < 2; ln++) {
1302d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_CLKHUB(ln, tc_port),
1303d4e0f163SVille Syrjälä CFG_LOW_RATE_LKREN_EN,
1304d4e0f163SVille Syrjälä crtc_state->port_clock < 300000 ? CFG_LOW_RATE_LKREN_EN : 0);
1305379bc100SJani Nikula }
1306379bc100SJani Nikula
1307379bc100SJani Nikula /* Program the MG_TX_DCC<LN, port being used> based on the link frequency */
1308379bc100SJani Nikula for (ln = 0; ln < 2; ln++) {
1309d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX1_DCC(ln, tc_port),
1310d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1311d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_EN,
1312d4e0f163SVille Syrjälä crtc_state->port_clock > 500000 ?
1313d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1314d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1315379bc100SJani Nikula
1316d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX2_DCC(ln, tc_port),
1317d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_VAL_MASK |
1318d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_EN,
1319d4e0f163SVille Syrjälä crtc_state->port_clock > 500000 ?
1320d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_VAL(1) |
1321d4e0f163SVille Syrjälä CFG_AMI_CK_DIV_OVERRIDE_EN : 0);
1322379bc100SJani Nikula }
1323379bc100SJani Nikula
1324379bc100SJani Nikula /* Program MG_TX_PISO_READLOAD with values from vswing table */
1325379bc100SJani Nikula for (ln = 0; ln < 2; ln++) {
1326d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX1_PISO_READLOAD(ln, tc_port),
1327d4e0f163SVille Syrjälä 0, CRI_CALCINIT);
1328d4e0f163SVille Syrjälä intel_de_rmw(dev_priv, MG_TX2_PISO_READLOAD(ln, tc_port),
1329d4e0f163SVille Syrjälä 0, CRI_CALCINIT);
1330379bc100SJani Nikula }
1331379bc100SJani Nikula }
1332379bc100SJani Nikula
tgl_dkl_phy_set_signal_levels(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1333193299adSVille Syrjälä static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
1334193299adSVille Syrjälä const struct intel_crtc_state *crtc_state)
1335978c3e53SClinton A Taylor {
1336978c3e53SClinton A Taylor struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
13377fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
1338e505d764SVille Syrjälä const struct intel_ddi_buf_trans *trans;
1339a621860aSVille Syrjälä int n_entries, ln;
1340978c3e53SClinton A Taylor
134111a89708SImre Deak if (intel_tc_port_in_tbt_alt_mode(enc_to_dig_port(encoder)))
1342f8c6b615SVille Syrjälä return;
1343f8c6b615SVille Syrjälä
1344e505d764SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
1345e505d764SVille Syrjälä if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans))
134685da0292SVille Syrjälä return;
1347978c3e53SClinton A Taylor
1348978c3e53SClinton A Taylor for (ln = 0; ln < 2; ln++) {
1349a905ced6SVille Syrjälä int level;
1350a905ced6SVille Syrjälä
1351b8ed5533SImre Deak intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0);
13522d69c42eSJosé Roberto de Souza
1353a905ced6SVille Syrjälä level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
1354a905ced6SVille Syrjälä
1355b8ed5533SImre Deak intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln),
1356c86e1873SVille Syrjälä DKL_TX_PRESHOOT_COEFF_MASK |
1357a905ced6SVille Syrjälä DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1358c86e1873SVille Syrjälä DKL_TX_VSWING_CONTROL_MASK,
1359c86e1873SVille Syrjälä DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1360a905ced6SVille Syrjälä DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1361c86e1873SVille Syrjälä DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1362978c3e53SClinton A Taylor
1363a905ced6SVille Syrjälä level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
1364a905ced6SVille Syrjälä
1365b8ed5533SImre Deak intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln),
1366c86e1873SVille Syrjälä DKL_TX_PRESHOOT_COEFF_MASK |
1367a905ced6SVille Syrjälä DKL_TX_DE_EMPAHSIS_COEFF_MASK |
1368c86e1873SVille Syrjälä DKL_TX_VSWING_CONTROL_MASK,
1369c86e1873SVille Syrjälä DKL_TX_PRESHOOT_COEFF(trans->entries[level].dkl.preshoot) |
1370a905ced6SVille Syrjälä DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
1371c86e1873SVille Syrjälä DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
1372978c3e53SClinton A Taylor
1373b8ed5533SImre Deak intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
1374c86e1873SVille Syrjälä DKL_TX_DP20BITMODE, 0);
13755ff59dddSJosé Roberto de Souza
13765ff59dddSJosé Roberto de Souza if (IS_ALDERLAKE_P(dev_priv)) {
13775ff59dddSJosé Roberto de Souza u32 val;
13785ff59dddSJosé Roberto de Souza
13795ff59dddSJosé Roberto de Souza if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
13805ff59dddSJosé Roberto de Souza if (ln == 0) {
13815ff59dddSJosé Roberto de Souza val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13825ff59dddSJosé Roberto de Souza val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(2);
13835ff59dddSJosé Roberto de Souza } else {
13845ff59dddSJosé Roberto de Souza val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(3);
13855ff59dddSJosé Roberto de Souza val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(3);
13865ff59dddSJosé Roberto de Souza }
13875ff59dddSJosé Roberto de Souza } else {
13885ff59dddSJosé Roberto de Souza val = DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(0);
13895ff59dddSJosé Roberto de Souza val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0);
13905ff59dddSJosé Roberto de Souza }
13915ff59dddSJosé Roberto de Souza
1392b8ed5533SImre Deak intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
13935ff59dddSJosé Roberto de Souza DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
13945ff59dddSJosé Roberto de Souza DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
13955ff59dddSJosé Roberto de Souza val);
13965ff59dddSJosé Roberto de Souza }
1397978c3e53SClinton A Taylor }
1398978c3e53SClinton A Taylor }
1399978c3e53SClinton A Taylor
translate_signal_level(struct intel_dp * intel_dp,u8 signal_levels)1400a621860aSVille Syrjälä static int translate_signal_level(struct intel_dp *intel_dp,
1401a621860aSVille Syrjälä u8 signal_levels)
1402379bc100SJani Nikula {
14037134cc23SJani Nikula struct intel_display *display = to_intel_display(intel_dp);
1404379bc100SJani Nikula int i;
1405379bc100SJani Nikula
1406379bc100SJani Nikula for (i = 0; i < ARRAY_SIZE(index_to_dp_signal_levels); i++) {
1407379bc100SJani Nikula if (index_to_dp_signal_levels[i] == signal_levels)
1408379bc100SJani Nikula return i;
1409379bc100SJani Nikula }
1410379bc100SJani Nikula
14117134cc23SJani Nikula drm_WARN(display->drm, 1,
14128b4f2137SPankaj Bharadiya "Unsupported voltage swing/pre-emphasis level: 0x%x\n",
1413379bc100SJani Nikula signal_levels);
1414379bc100SJani Nikula
1415379bc100SJani Nikula return 0;
1416379bc100SJani Nikula }
1417379bc100SJani Nikula
intel_ddi_dp_level(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state,int lane)14185c31e9d0SJani Nikula static int intel_ddi_dp_level(struct intel_dp *intel_dp,
14195c31e9d0SJani Nikula const struct intel_crtc_state *crtc_state,
14205c31e9d0SJani Nikula int lane)
1421379bc100SJani Nikula {
1422d0920a45SVille Syrjälä u8 train_set = intel_dp->train_set[lane];
14235c31e9d0SJani Nikula
14245c31e9d0SJani Nikula if (intel_dp_is_uhbr(crtc_state)) {
14255c31e9d0SJani Nikula return train_set & DP_TX_FFE_PRESET_VALUE_MASK;
14265c31e9d0SJani Nikula } else {
1427a621860aSVille Syrjälä u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
1428379bc100SJani Nikula DP_TRAIN_PRE_EMPHASIS_MASK);
1429379bc100SJani Nikula
14308b4f2137SPankaj Bharadiya return translate_signal_level(intel_dp, signal_levels);
1431379bc100SJani Nikula }
14325c31e9d0SJani Nikula }
1433379bc100SJani Nikula
intel_ddi_level(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,int lane)1434193299adSVille Syrjälä int intel_ddi_level(struct intel_encoder *encoder,
1435d0920a45SVille Syrjälä const struct intel_crtc_state *crtc_state,
1436d0920a45SVille Syrjälä int lane)
1437a046a0daSMatt Roper {
14382c63e0f9SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
14392c63e0f9SVille Syrjälä const struct intel_ddi_buf_trans *trans;
14402c63e0f9SVille Syrjälä int level, n_entries;
14412c63e0f9SVille Syrjälä
14422c63e0f9SVille Syrjälä trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries);
14432c63e0f9SVille Syrjälä if (drm_WARN_ON_ONCE(&i915->drm, !trans))
14442c63e0f9SVille Syrjälä return 0;
14452c63e0f9SVille Syrjälä
1446e722ab8bSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
14473e022c1fSVille Syrjälä level = intel_ddi_hdmi_level(encoder, trans);
1448e722ab8bSVille Syrjälä else
14495c31e9d0SJani Nikula level = intel_ddi_dp_level(enc_to_intel_dp(encoder), crtc_state,
14505c31e9d0SJani Nikula lane);
14512c63e0f9SVille Syrjälä
14522c63e0f9SVille Syrjälä if (drm_WARN_ON_ONCE(&i915->drm, level >= n_entries))
14532c63e0f9SVille Syrjälä level = n_entries - 1;
14542c63e0f9SVille Syrjälä
14552c63e0f9SVille Syrjälä return level;
1456e722ab8bSVille Syrjälä }
1457e722ab8bSVille Syrjälä
1458e722ab8bSVille Syrjälä static void
hsw_set_signal_levels(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1459e722ab8bSVille Syrjälä hsw_set_signal_levels(struct intel_encoder *encoder,
1460a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state)
1461fb83f72cSVille Syrjälä {
1462fb83f72cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
1463e722ab8bSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
1464d0920a45SVille Syrjälä int level = intel_ddi_level(encoder, crtc_state, 0);
1465fb83f72cSVille Syrjälä enum port port = encoder->port;
1466fb83f72cSVille Syrjälä u32 signal_levels;
1467fb83f72cSVille Syrjälä
1468e722ab8bSVille Syrjälä if (has_iboost(dev_priv))
1469e722ab8bSVille Syrjälä skl_ddi_set_iboost(encoder, crtc_state, level);
1470e722ab8bSVille Syrjälä
1471e722ab8bSVille Syrjälä /* HDMI ignores the rest */
1472e722ab8bSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
1473e722ab8bSVille Syrjälä return;
1474e722ab8bSVille Syrjälä
1475fb83f72cSVille Syrjälä signal_levels = DDI_BUF_TRANS_SELECT(level);
1476fb83f72cSVille Syrjälä
1477fb83f72cSVille Syrjälä drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
1478fb83f72cSVille Syrjälä signal_levels);
1479fb83f72cSVille Syrjälä
1480fb83f72cSVille Syrjälä intel_dp->DP &= ~DDI_BUF_EMP_MASK;
1481fb83f72cSVille Syrjälä intel_dp->DP |= signal_levels;
1482fb83f72cSVille Syrjälä
1483fb83f72cSVille Syrjälä intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
1484fb83f72cSVille Syrjälä intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
1485379bc100SJani Nikula }
1486379bc100SJani Nikula
_icl_ddi_enable_clock(struct drm_i915_private * i915,i915_reg_t reg,u32 clk_sel_mask,u32 clk_sel,u32 clk_off)14874da27d5dSLucas De Marchi static void _icl_ddi_enable_clock(struct drm_i915_private *i915, i915_reg_t reg,
14889c6a5c35SVille Syrjälä u32 clk_sel_mask, u32 clk_sel, u32 clk_off)
14899c6a5c35SVille Syrjälä {
149036d225f3SJani Nikula mutex_lock(&i915->display.dpll.lock);
14919c6a5c35SVille Syrjälä
14929c6a5c35SVille Syrjälä intel_de_rmw(i915, reg, clk_sel_mask, clk_sel);
14939c6a5c35SVille Syrjälä
14949c6a5c35SVille Syrjälä /*
14959c6a5c35SVille Syrjälä * "This step and the step before must be
14969c6a5c35SVille Syrjälä * done with separate register writes."
14979c6a5c35SVille Syrjälä */
14989c6a5c35SVille Syrjälä intel_de_rmw(i915, reg, clk_off, 0);
14999c6a5c35SVille Syrjälä
150036d225f3SJani Nikula mutex_unlock(&i915->display.dpll.lock);
15019c6a5c35SVille Syrjälä }
15029c6a5c35SVille Syrjälä
_icl_ddi_disable_clock(struct drm_i915_private * i915,i915_reg_t reg,u32 clk_off)15034da27d5dSLucas De Marchi static void _icl_ddi_disable_clock(struct drm_i915_private *i915, i915_reg_t reg,
15049c6a5c35SVille Syrjälä u32 clk_off)
15059c6a5c35SVille Syrjälä {
150636d225f3SJani Nikula mutex_lock(&i915->display.dpll.lock);
15079c6a5c35SVille Syrjälä
15089c6a5c35SVille Syrjälä intel_de_rmw(i915, reg, 0, clk_off);
15099c6a5c35SVille Syrjälä
151036d225f3SJani Nikula mutex_unlock(&i915->display.dpll.lock);
15119c6a5c35SVille Syrjälä }
15129c6a5c35SVille Syrjälä
_icl_ddi_is_clock_enabled(struct drm_i915_private * i915,i915_reg_t reg,u32 clk_off)15134da27d5dSLucas De Marchi static bool _icl_ddi_is_clock_enabled(struct drm_i915_private *i915, i915_reg_t reg,
15140fbd8694SVille Syrjälä u32 clk_off)
15150fbd8694SVille Syrjälä {
15160fbd8694SVille Syrjälä return !(intel_de_read(i915, reg) & clk_off);
15170fbd8694SVille Syrjälä }
15180fbd8694SVille Syrjälä
1519351221ffSVille Syrjälä static struct intel_shared_dpll *
_icl_ddi_get_pll(struct drm_i915_private * i915,i915_reg_t reg,u32 clk_sel_mask,u32 clk_sel_shift)15204da27d5dSLucas De Marchi _icl_ddi_get_pll(struct drm_i915_private *i915, i915_reg_t reg,
1521351221ffSVille Syrjälä u32 clk_sel_mask, u32 clk_sel_shift)
1522351221ffSVille Syrjälä {
1523351221ffSVille Syrjälä enum intel_dpll_id id;
1524351221ffSVille Syrjälä
1525351221ffSVille Syrjälä id = (intel_de_read(i915, reg) & clk_sel_mask) >> clk_sel_shift;
1526351221ffSVille Syrjälä
1527351221ffSVille Syrjälä return intel_get_shared_dpll_by_id(i915, id);
1528351221ffSVille Syrjälä }
1529351221ffSVille Syrjälä
adls_ddi_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)153040b316d4SVille Syrjälä static void adls_ddi_enable_clock(struct intel_encoder *encoder,
153140b316d4SVille Syrjälä const struct intel_crtc_state *crtc_state)
153240b316d4SVille Syrjälä {
153340b316d4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
153440b316d4SVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
15357fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
153640b316d4SVille Syrjälä
153740b316d4SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
153840b316d4SVille Syrjälä return;
153940b316d4SVille Syrjälä
15404da27d5dSLucas De Marchi _icl_ddi_enable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
154140b316d4SVille Syrjälä ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
154240b316d4SVille Syrjälä pll->info->id << ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy),
154340b316d4SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
154440b316d4SVille Syrjälä }
154540b316d4SVille Syrjälä
adls_ddi_disable_clock(struct intel_encoder * encoder)154640b316d4SVille Syrjälä static void adls_ddi_disable_clock(struct intel_encoder *encoder)
154740b316d4SVille Syrjälä {
154840b316d4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15497fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
155040b316d4SVille Syrjälä
15514da27d5dSLucas De Marchi _icl_ddi_disable_clock(i915, ADLS_DPCLKA_CFGCR(phy),
155240b316d4SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
155340b316d4SVille Syrjälä }
155440b316d4SVille Syrjälä
adls_ddi_is_clock_enabled(struct intel_encoder * encoder)15550fbd8694SVille Syrjälä static bool adls_ddi_is_clock_enabled(struct intel_encoder *encoder)
15560fbd8694SVille Syrjälä {
15570fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15587fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
15590fbd8694SVille Syrjälä
15604da27d5dSLucas De Marchi return _icl_ddi_is_clock_enabled(i915, ADLS_DPCLKA_CFGCR(phy),
15610fbd8694SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
15620fbd8694SVille Syrjälä }
15630fbd8694SVille Syrjälä
adls_ddi_get_pll(struct intel_encoder * encoder)1564351221ffSVille Syrjälä static struct intel_shared_dpll *adls_ddi_get_pll(struct intel_encoder *encoder)
1565351221ffSVille Syrjälä {
1566351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15677fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1568351221ffSVille Syrjälä
15694da27d5dSLucas De Marchi return _icl_ddi_get_pll(i915, ADLS_DPCLKA_CFGCR(phy),
1570351221ffSVille Syrjälä ADLS_DPCLKA_CFGCR_DDI_CLK_SEL_MASK(phy),
1571351221ffSVille Syrjälä ADLS_DPCLKA_CFGCR_DDI_SHIFT(phy));
1572351221ffSVille Syrjälä }
1573351221ffSVille Syrjälä
rkl_ddi_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)157440b316d4SVille Syrjälä static void rkl_ddi_enable_clock(struct intel_encoder *encoder,
157540b316d4SVille Syrjälä const struct intel_crtc_state *crtc_state)
157640b316d4SVille Syrjälä {
157740b316d4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
157840b316d4SVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
15797fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
158040b316d4SVille Syrjälä
158140b316d4SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
158240b316d4SVille Syrjälä return;
158340b316d4SVille Syrjälä
15844da27d5dSLucas De Marchi _icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
158540b316d4SVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
158640b316d4SVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
158740b316d4SVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
158840b316d4SVille Syrjälä }
158940b316d4SVille Syrjälä
rkl_ddi_disable_clock(struct intel_encoder * encoder)159040b316d4SVille Syrjälä static void rkl_ddi_disable_clock(struct intel_encoder *encoder)
159140b316d4SVille Syrjälä {
159240b316d4SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
15937fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
159440b316d4SVille Syrjälä
15954da27d5dSLucas De Marchi _icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
159640b316d4SVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
159740b316d4SVille Syrjälä }
159840b316d4SVille Syrjälä
rkl_ddi_is_clock_enabled(struct intel_encoder * encoder)15990fbd8694SVille Syrjälä static bool rkl_ddi_is_clock_enabled(struct intel_encoder *encoder)
16000fbd8694SVille Syrjälä {
16010fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16027fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
16030fbd8694SVille Syrjälä
16044da27d5dSLucas De Marchi return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
16050fbd8694SVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
16060fbd8694SVille Syrjälä }
16070fbd8694SVille Syrjälä
rkl_ddi_get_pll(struct intel_encoder * encoder)1608351221ffSVille Syrjälä static struct intel_shared_dpll *rkl_ddi_get_pll(struct intel_encoder *encoder)
1609351221ffSVille Syrjälä {
1610351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16117fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1612351221ffSVille Syrjälä
16134da27d5dSLucas De Marchi return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1614351221ffSVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1615351221ffSVille Syrjälä RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1616351221ffSVille Syrjälä }
1617351221ffSVille Syrjälä
dg1_ddi_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)161835bb6b1aSVille Syrjälä static void dg1_ddi_enable_clock(struct intel_encoder *encoder,
161911ffe972SLucas De Marchi const struct intel_crtc_state *crtc_state)
162011ffe972SLucas De Marchi {
162197a24a70SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16229c6a5c35SVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
16237fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
162411ffe972SLucas De Marchi
162597a24a70SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
1626f67a008eSVille Syrjälä return;
1627f67a008eSVille Syrjälä
162811ffe972SLucas De Marchi /*
162911ffe972SLucas De Marchi * If we fail this, something went very wrong: first 2 PLLs should be
163011ffe972SLucas De Marchi * used by first 2 phys and last 2 PLLs by last phys
163111ffe972SLucas De Marchi */
163297a24a70SVille Syrjälä if (drm_WARN_ON(&i915->drm,
163311ffe972SLucas De Marchi (pll->info->id < DPLL_ID_DG1_DPLL2 && phy >= PHY_C) ||
163411ffe972SLucas De Marchi (pll->info->id >= DPLL_ID_DG1_DPLL2 && phy < PHY_C)))
163511ffe972SLucas De Marchi return;
163611ffe972SLucas De Marchi
16374da27d5dSLucas De Marchi _icl_ddi_enable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16387815ed88SVille Syrjälä DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
16399c6a5c35SVille Syrjälä DG1_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
16409c6a5c35SVille Syrjälä DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
164111ffe972SLucas De Marchi }
164211ffe972SLucas De Marchi
dg1_ddi_disable_clock(struct intel_encoder * encoder)164335bb6b1aSVille Syrjälä static void dg1_ddi_disable_clock(struct intel_encoder *encoder)
164435bb6b1aSVille Syrjälä {
164597a24a70SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16467fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
164735bb6b1aSVille Syrjälä
16484da27d5dSLucas De Marchi _icl_ddi_disable_clock(i915, DG1_DPCLKA_CFGCR0(phy),
16499c6a5c35SVille Syrjälä DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
165035bb6b1aSVille Syrjälä }
165135bb6b1aSVille Syrjälä
dg1_ddi_is_clock_enabled(struct intel_encoder * encoder)16520fbd8694SVille Syrjälä static bool dg1_ddi_is_clock_enabled(struct intel_encoder *encoder)
16530fbd8694SVille Syrjälä {
16540fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16557fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
16560fbd8694SVille Syrjälä
16574da27d5dSLucas De Marchi return _icl_ddi_is_clock_enabled(i915, DG1_DPCLKA_CFGCR0(phy),
16580fbd8694SVille Syrjälä DG1_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
16590fbd8694SVille Syrjälä }
16600fbd8694SVille Syrjälä
dg1_ddi_get_pll(struct intel_encoder * encoder)1661351221ffSVille Syrjälä static struct intel_shared_dpll *dg1_ddi_get_pll(struct intel_encoder *encoder)
1662351221ffSVille Syrjälä {
1663351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16647fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
16653352d86dSJosé Roberto de Souza enum intel_dpll_id id;
16663352d86dSJosé Roberto de Souza u32 val;
1667351221ffSVille Syrjälä
16683352d86dSJosé Roberto de Souza val = intel_de_read(i915, DG1_DPCLKA_CFGCR0(phy));
16693352d86dSJosé Roberto de Souza val &= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy);
16703352d86dSJosé Roberto de Souza val >>= DG1_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy);
16713352d86dSJosé Roberto de Souza id = val;
16723352d86dSJosé Roberto de Souza
16733352d86dSJosé Roberto de Souza /*
16743352d86dSJosé Roberto de Souza * _DG1_DPCLKA0_CFGCR0 maps between DPLL 0 and 1 with one bit for phy A
16753352d86dSJosé Roberto de Souza * and B while _DG1_DPCLKA1_CFGCR0 maps between DPLL 2 and 3 with one
16763352d86dSJosé Roberto de Souza * bit for phy C and D.
16773352d86dSJosé Roberto de Souza */
16783352d86dSJosé Roberto de Souza if (phy >= PHY_C)
16793352d86dSJosé Roberto de Souza id += DPLL_ID_DG1_DPLL2;
16803352d86dSJosé Roberto de Souza
16813352d86dSJosé Roberto de Souza return intel_get_shared_dpll_by_id(i915, id);
1682351221ffSVille Syrjälä }
1683351221ffSVille Syrjälä
icl_ddi_combo_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)168436ecb0ecSVille Syrjälä static void icl_ddi_combo_enable_clock(struct intel_encoder *encoder,
1685379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
1686379bc100SJani Nikula {
168797a24a70SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
16889c6a5c35SVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
16897fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1690cd803bb4SMatt Roper
169197a24a70SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
1692f67a008eSVille Syrjälä return;
1693f67a008eSVille Syrjälä
16944da27d5dSLucas De Marchi _icl_ddi_enable_clock(i915, ICL_DPCLKA_CFGCR0,
169540b316d4SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
169640b316d4SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy),
169740b316d4SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1698379bc100SJani Nikula }
1699379bc100SJani Nikula
icl_ddi_combo_disable_clock(struct intel_encoder * encoder)170036ecb0ecSVille Syrjälä static void icl_ddi_combo_disable_clock(struct intel_encoder *encoder)
1701379bc100SJani Nikula {
170297a24a70SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17037fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1704379bc100SJani Nikula
17054da27d5dSLucas De Marchi _icl_ddi_disable_clock(i915, ICL_DPCLKA_CFGCR0,
170640b316d4SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
1707379bc100SJani Nikula }
1708379bc100SJani Nikula
icl_ddi_combo_is_clock_enabled(struct intel_encoder * encoder)17090fbd8694SVille Syrjälä static bool icl_ddi_combo_is_clock_enabled(struct intel_encoder *encoder)
17100fbd8694SVille Syrjälä {
17110fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17127fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
17130fbd8694SVille Syrjälä
17144da27d5dSLucas De Marchi return _icl_ddi_is_clock_enabled(i915, ICL_DPCLKA_CFGCR0,
17150fbd8694SVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy));
17160fbd8694SVille Syrjälä }
17170fbd8694SVille Syrjälä
icl_ddi_combo_get_pll(struct intel_encoder * encoder)1718351221ffSVille Syrjälä struct intel_shared_dpll *icl_ddi_combo_get_pll(struct intel_encoder *encoder)
1719351221ffSVille Syrjälä {
1720351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17217fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
1722351221ffSVille Syrjälä
17234da27d5dSLucas De Marchi return _icl_ddi_get_pll(i915, ICL_DPCLKA_CFGCR0,
1724351221ffSVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy),
1725351221ffSVille Syrjälä ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy));
1726351221ffSVille Syrjälä }
1727351221ffSVille Syrjälä
jsl_ddi_tc_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)172836ecb0ecSVille Syrjälä static void jsl_ddi_tc_enable_clock(struct intel_encoder *encoder,
1729379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
1730379bc100SJani Nikula {
173136ecb0ecSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1732379bc100SJani Nikula const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
173336ecb0ecSVille Syrjälä enum port port = encoder->port;
1734379bc100SJani Nikula
173536ecb0ecSVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
1736379bc100SJani Nikula return;
1737379bc100SJani Nikula
1738c2052d6eSJosé Roberto de Souza /*
173936ecb0ecSVille Syrjälä * "For DDIC and DDID, program DDI_CLK_SEL to map the MG clock to the port.
174036ecb0ecSVille Syrjälä * MG does not exist, but the programming is required to ungate DDIC and DDID."
1741c2052d6eSJosé Roberto de Souza */
174236ecb0ecSVille Syrjälä intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_MG);
174336ecb0ecSVille Syrjälä
174436ecb0ecSVille Syrjälä icl_ddi_combo_enable_clock(encoder, crtc_state);
1745379bc100SJani Nikula }
1746379bc100SJani Nikula
jsl_ddi_tc_disable_clock(struct intel_encoder * encoder)174736ecb0ecSVille Syrjälä static void jsl_ddi_tc_disable_clock(struct intel_encoder *encoder)
1748379bc100SJani Nikula {
174936ecb0ecSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1750379bc100SJani Nikula enum port port = encoder->port;
1751379bc100SJani Nikula
175236ecb0ecSVille Syrjälä icl_ddi_combo_disable_clock(encoder);
175336ecb0ecSVille Syrjälä
175436ecb0ecSVille Syrjälä intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1755379bc100SJani Nikula }
175636ecb0ecSVille Syrjälä
jsl_ddi_tc_is_clock_enabled(struct intel_encoder * encoder)17570fbd8694SVille Syrjälä static bool jsl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
17580fbd8694SVille Syrjälä {
17590fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17600fbd8694SVille Syrjälä enum port port = encoder->port;
17610fbd8694SVille Syrjälä u32 tmp;
17620fbd8694SVille Syrjälä
17630fbd8694SVille Syrjälä tmp = intel_de_read(i915, DDI_CLK_SEL(port));
17640fbd8694SVille Syrjälä
17650fbd8694SVille Syrjälä if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
17660fbd8694SVille Syrjälä return false;
17670fbd8694SVille Syrjälä
17680fbd8694SVille Syrjälä return icl_ddi_combo_is_clock_enabled(encoder);
17690fbd8694SVille Syrjälä }
17700fbd8694SVille Syrjälä
icl_ddi_tc_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)177136ecb0ecSVille Syrjälä static void icl_ddi_tc_enable_clock(struct intel_encoder *encoder,
177236ecb0ecSVille Syrjälä const struct intel_crtc_state *crtc_state)
177336ecb0ecSVille Syrjälä {
177436ecb0ecSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
177536ecb0ecSVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
17767fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
177736ecb0ecSVille Syrjälä enum port port = encoder->port;
177836ecb0ecSVille Syrjälä
177936ecb0ecSVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
178036ecb0ecSVille Syrjälä return;
178136ecb0ecSVille Syrjälä
178236ecb0ecSVille Syrjälä intel_de_write(i915, DDI_CLK_SEL(port),
178336ecb0ecSVille Syrjälä icl_pll_to_ddi_clk_sel(encoder, crtc_state));
178436ecb0ecSVille Syrjälä
178536d225f3SJani Nikula mutex_lock(&i915->display.dpll.lock);
178636ecb0ecSVille Syrjälä
178736ecb0ecSVille Syrjälä intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
178836ecb0ecSVille Syrjälä ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port), 0);
178936ecb0ecSVille Syrjälä
179036d225f3SJani Nikula mutex_unlock(&i915->display.dpll.lock);
179136ecb0ecSVille Syrjälä }
179236ecb0ecSVille Syrjälä
icl_ddi_tc_disable_clock(struct intel_encoder * encoder)179336ecb0ecSVille Syrjälä static void icl_ddi_tc_disable_clock(struct intel_encoder *encoder)
179436ecb0ecSVille Syrjälä {
179536ecb0ecSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
17967fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
179736ecb0ecSVille Syrjälä enum port port = encoder->port;
179836ecb0ecSVille Syrjälä
179936d225f3SJani Nikula mutex_lock(&i915->display.dpll.lock);
180036ecb0ecSVille Syrjälä
180136ecb0ecSVille Syrjälä intel_de_rmw(i915, ICL_DPCLKA_CFGCR0,
180236ecb0ecSVille Syrjälä 0, ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
180336ecb0ecSVille Syrjälä
180436d225f3SJani Nikula mutex_unlock(&i915->display.dpll.lock);
180536ecb0ecSVille Syrjälä
180636ecb0ecSVille Syrjälä intel_de_write(i915, DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
1807379bc100SJani Nikula }
1808379bc100SJani Nikula
icl_ddi_tc_is_clock_enabled(struct intel_encoder * encoder)18090fbd8694SVille Syrjälä static bool icl_ddi_tc_is_clock_enabled(struct intel_encoder *encoder)
18100fbd8694SVille Syrjälä {
18110fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
18127fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
18130fbd8694SVille Syrjälä enum port port = encoder->port;
18140fbd8694SVille Syrjälä u32 tmp;
18150fbd8694SVille Syrjälä
18160fbd8694SVille Syrjälä tmp = intel_de_read(i915, DDI_CLK_SEL(port));
18170fbd8694SVille Syrjälä
18180fbd8694SVille Syrjälä if ((tmp & DDI_CLK_SEL_MASK) == DDI_CLK_SEL_NONE)
18190fbd8694SVille Syrjälä return false;
18200fbd8694SVille Syrjälä
18210fbd8694SVille Syrjälä tmp = intel_de_read(i915, ICL_DPCLKA_CFGCR0);
18220fbd8694SVille Syrjälä
18230fbd8694SVille Syrjälä return !(tmp & ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port));
18240fbd8694SVille Syrjälä }
18250fbd8694SVille Syrjälä
icl_ddi_tc_get_pll(struct intel_encoder * encoder)1826351221ffSVille Syrjälä static struct intel_shared_dpll *icl_ddi_tc_get_pll(struct intel_encoder *encoder)
1827351221ffSVille Syrjälä {
1828351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
18297fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
1830351221ffSVille Syrjälä enum port port = encoder->port;
1831351221ffSVille Syrjälä enum intel_dpll_id id;
1832351221ffSVille Syrjälä u32 tmp;
1833351221ffSVille Syrjälä
1834351221ffSVille Syrjälä tmp = intel_de_read(i915, DDI_CLK_SEL(port));
1835351221ffSVille Syrjälä
1836351221ffSVille Syrjälä switch (tmp & DDI_CLK_SEL_MASK) {
1837351221ffSVille Syrjälä case DDI_CLK_SEL_TBT_162:
1838351221ffSVille Syrjälä case DDI_CLK_SEL_TBT_270:
1839351221ffSVille Syrjälä case DDI_CLK_SEL_TBT_540:
1840351221ffSVille Syrjälä case DDI_CLK_SEL_TBT_810:
1841351221ffSVille Syrjälä id = DPLL_ID_ICL_TBTPLL;
1842351221ffSVille Syrjälä break;
1843351221ffSVille Syrjälä case DDI_CLK_SEL_MG:
1844351221ffSVille Syrjälä id = icl_tc_port_to_pll_id(tc_port);
1845351221ffSVille Syrjälä break;
1846351221ffSVille Syrjälä default:
1847351221ffSVille Syrjälä MISSING_CASE(tmp);
1848351221ffSVille Syrjälä fallthrough;
1849351221ffSVille Syrjälä case DDI_CLK_SEL_NONE:
1850351221ffSVille Syrjälä return NULL;
1851351221ffSVille Syrjälä }
1852351221ffSVille Syrjälä
1853351221ffSVille Syrjälä return intel_get_shared_dpll_by_id(i915, id);
1854351221ffSVille Syrjälä }
1855351221ffSVille Syrjälä
bxt_ddi_get_pll(struct intel_encoder * encoder)1856351221ffSVille Syrjälä static struct intel_shared_dpll *bxt_ddi_get_pll(struct intel_encoder *encoder)
1857351221ffSVille Syrjälä {
1858351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1859351221ffSVille Syrjälä enum intel_dpll_id id;
1860351221ffSVille Syrjälä
1861351221ffSVille Syrjälä switch (encoder->port) {
1862351221ffSVille Syrjälä case PORT_A:
1863351221ffSVille Syrjälä id = DPLL_ID_SKL_DPLL0;
1864351221ffSVille Syrjälä break;
1865351221ffSVille Syrjälä case PORT_B:
1866351221ffSVille Syrjälä id = DPLL_ID_SKL_DPLL1;
1867351221ffSVille Syrjälä break;
1868351221ffSVille Syrjälä case PORT_C:
1869351221ffSVille Syrjälä id = DPLL_ID_SKL_DPLL2;
1870351221ffSVille Syrjälä break;
1871351221ffSVille Syrjälä default:
1872351221ffSVille Syrjälä MISSING_CASE(encoder->port);
1873351221ffSVille Syrjälä return NULL;
1874351221ffSVille Syrjälä }
1875351221ffSVille Syrjälä
1876351221ffSVille Syrjälä return intel_get_shared_dpll_by_id(i915, id);
1877351221ffSVille Syrjälä }
1878351221ffSVille Syrjälä
skl_ddi_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)187938e31f1aSVille Syrjälä static void skl_ddi_enable_clock(struct intel_encoder *encoder,
188038e31f1aSVille Syrjälä const struct intel_crtc_state *crtc_state)
188138e31f1aSVille Syrjälä {
188238e31f1aSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
188338e31f1aSVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
188438e31f1aSVille Syrjälä enum port port = encoder->port;
188538e31f1aSVille Syrjälä
188638e31f1aSVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
188738e31f1aSVille Syrjälä return;
188838e31f1aSVille Syrjälä
188936d225f3SJani Nikula mutex_lock(&i915->display.dpll.lock);
189038e31f1aSVille Syrjälä
18917815ed88SVille Syrjälä intel_de_rmw(i915, DPLL_CTRL2,
18927815ed88SVille Syrjälä DPLL_CTRL2_DDI_CLK_OFF(port) |
18937815ed88SVille Syrjälä DPLL_CTRL2_DDI_CLK_SEL_MASK(port),
18947815ed88SVille Syrjälä DPLL_CTRL2_DDI_CLK_SEL(pll->info->id, port) |
189538e31f1aSVille Syrjälä DPLL_CTRL2_DDI_SEL_OVERRIDE(port));
189638e31f1aSVille Syrjälä
189736d225f3SJani Nikula mutex_unlock(&i915->display.dpll.lock);
189838e31f1aSVille Syrjälä }
189938e31f1aSVille Syrjälä
skl_ddi_disable_clock(struct intel_encoder * encoder)190038e31f1aSVille Syrjälä static void skl_ddi_disable_clock(struct intel_encoder *encoder)
190138e31f1aSVille Syrjälä {
190238e31f1aSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
190338e31f1aSVille Syrjälä enum port port = encoder->port;
190438e31f1aSVille Syrjälä
190536d225f3SJani Nikula mutex_lock(&i915->display.dpll.lock);
1906be317ca0SVille Syrjälä
19077815ed88SVille Syrjälä intel_de_rmw(i915, DPLL_CTRL2,
19087815ed88SVille Syrjälä 0, DPLL_CTRL2_DDI_CLK_OFF(port));
1909be317ca0SVille Syrjälä
191036d225f3SJani Nikula mutex_unlock(&i915->display.dpll.lock);
191138e31f1aSVille Syrjälä }
191238e31f1aSVille Syrjälä
skl_ddi_is_clock_enabled(struct intel_encoder * encoder)19130fbd8694SVille Syrjälä static bool skl_ddi_is_clock_enabled(struct intel_encoder *encoder)
19140fbd8694SVille Syrjälä {
19150fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19160fbd8694SVille Syrjälä enum port port = encoder->port;
19170fbd8694SVille Syrjälä
19180fbd8694SVille Syrjälä /*
19190fbd8694SVille Syrjälä * FIXME Not sure if the override affects both
19200fbd8694SVille Syrjälä * the PLL selection and the CLK_OFF bit.
19210fbd8694SVille Syrjälä */
19220fbd8694SVille Syrjälä return !(intel_de_read(i915, DPLL_CTRL2) & DPLL_CTRL2_DDI_CLK_OFF(port));
19230fbd8694SVille Syrjälä }
19240fbd8694SVille Syrjälä
skl_ddi_get_pll(struct intel_encoder * encoder)1925351221ffSVille Syrjälä static struct intel_shared_dpll *skl_ddi_get_pll(struct intel_encoder *encoder)
1926351221ffSVille Syrjälä {
1927351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1928351221ffSVille Syrjälä enum port port = encoder->port;
1929351221ffSVille Syrjälä enum intel_dpll_id id;
1930351221ffSVille Syrjälä u32 tmp;
1931351221ffSVille Syrjälä
1932351221ffSVille Syrjälä tmp = intel_de_read(i915, DPLL_CTRL2);
1933351221ffSVille Syrjälä
1934351221ffSVille Syrjälä /*
1935351221ffSVille Syrjälä * FIXME Not sure if the override affects both
1936351221ffSVille Syrjälä * the PLL selection and the CLK_OFF bit.
1937351221ffSVille Syrjälä */
1938351221ffSVille Syrjälä if ((tmp & DPLL_CTRL2_DDI_SEL_OVERRIDE(port)) == 0)
1939351221ffSVille Syrjälä return NULL;
1940351221ffSVille Syrjälä
1941351221ffSVille Syrjälä id = (tmp & DPLL_CTRL2_DDI_CLK_SEL_MASK(port)) >>
1942351221ffSVille Syrjälä DPLL_CTRL2_DDI_CLK_SEL_SHIFT(port);
1943351221ffSVille Syrjälä
1944351221ffSVille Syrjälä return intel_get_shared_dpll_by_id(i915, id);
1945351221ffSVille Syrjälä }
1946351221ffSVille Syrjälä
hsw_ddi_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)1947d135368dSVille Syrjälä void hsw_ddi_enable_clock(struct intel_encoder *encoder,
1948d135368dSVille Syrjälä const struct intel_crtc_state *crtc_state)
1949d135368dSVille Syrjälä {
1950d135368dSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1951d135368dSVille Syrjälä const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
1952d135368dSVille Syrjälä enum port port = encoder->port;
1953d135368dSVille Syrjälä
1954d135368dSVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
1955d135368dSVille Syrjälä return;
1956d135368dSVille Syrjälä
1957d135368dSVille Syrjälä intel_de_write(i915, PORT_CLK_SEL(port), hsw_pll_to_ddi_pll_sel(pll));
1958d135368dSVille Syrjälä }
1959d135368dSVille Syrjälä
hsw_ddi_disable_clock(struct intel_encoder * encoder)1960d135368dSVille Syrjälä void hsw_ddi_disable_clock(struct intel_encoder *encoder)
1961d135368dSVille Syrjälä {
1962d135368dSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1963d135368dSVille Syrjälä enum port port = encoder->port;
1964d135368dSVille Syrjälä
1965d135368dSVille Syrjälä intel_de_write(i915, PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
1966d135368dSVille Syrjälä }
1967d135368dSVille Syrjälä
hsw_ddi_is_clock_enabled(struct intel_encoder * encoder)19680fbd8694SVille Syrjälä bool hsw_ddi_is_clock_enabled(struct intel_encoder *encoder)
19690fbd8694SVille Syrjälä {
19700fbd8694SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
19710fbd8694SVille Syrjälä enum port port = encoder->port;
19720fbd8694SVille Syrjälä
19730fbd8694SVille Syrjälä return intel_de_read(i915, PORT_CLK_SEL(port)) != PORT_CLK_SEL_NONE;
19740fbd8694SVille Syrjälä }
19750fbd8694SVille Syrjälä
hsw_ddi_get_pll(struct intel_encoder * encoder)1976351221ffSVille Syrjälä static struct intel_shared_dpll *hsw_ddi_get_pll(struct intel_encoder *encoder)
1977351221ffSVille Syrjälä {
1978351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
1979351221ffSVille Syrjälä enum port port = encoder->port;
1980351221ffSVille Syrjälä enum intel_dpll_id id;
1981351221ffSVille Syrjälä u32 tmp;
1982351221ffSVille Syrjälä
1983351221ffSVille Syrjälä tmp = intel_de_read(i915, PORT_CLK_SEL(port));
1984351221ffSVille Syrjälä
1985351221ffSVille Syrjälä switch (tmp & PORT_CLK_SEL_MASK) {
1986351221ffSVille Syrjälä case PORT_CLK_SEL_WRPLL1:
1987351221ffSVille Syrjälä id = DPLL_ID_WRPLL1;
1988351221ffSVille Syrjälä break;
1989351221ffSVille Syrjälä case PORT_CLK_SEL_WRPLL2:
1990351221ffSVille Syrjälä id = DPLL_ID_WRPLL2;
1991351221ffSVille Syrjälä break;
1992351221ffSVille Syrjälä case PORT_CLK_SEL_SPLL:
1993351221ffSVille Syrjälä id = DPLL_ID_SPLL;
1994351221ffSVille Syrjälä break;
1995351221ffSVille Syrjälä case PORT_CLK_SEL_LCPLL_810:
1996351221ffSVille Syrjälä id = DPLL_ID_LCPLL_810;
1997351221ffSVille Syrjälä break;
1998351221ffSVille Syrjälä case PORT_CLK_SEL_LCPLL_1350:
1999351221ffSVille Syrjälä id = DPLL_ID_LCPLL_1350;
2000351221ffSVille Syrjälä break;
2001351221ffSVille Syrjälä case PORT_CLK_SEL_LCPLL_2700:
2002351221ffSVille Syrjälä id = DPLL_ID_LCPLL_2700;
2003351221ffSVille Syrjälä break;
2004351221ffSVille Syrjälä default:
2005351221ffSVille Syrjälä MISSING_CASE(tmp);
2006351221ffSVille Syrjälä fallthrough;
2007351221ffSVille Syrjälä case PORT_CLK_SEL_NONE:
2008351221ffSVille Syrjälä return NULL;
2009351221ffSVille Syrjälä }
2010351221ffSVille Syrjälä
2011351221ffSVille Syrjälä return intel_get_shared_dpll_by_id(i915, id);
2012351221ffSVille Syrjälä }
2013351221ffSVille Syrjälä
intel_ddi_enable_clock(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)2014c133df69SVille Syrjälä void intel_ddi_enable_clock(struct intel_encoder *encoder,
2015c133df69SVille Syrjälä const struct intel_crtc_state *crtc_state)
2016c133df69SVille Syrjälä {
2017c133df69SVille Syrjälä if (encoder->enable_clock)
2018c133df69SVille Syrjälä encoder->enable_clock(encoder, crtc_state);
2019c133df69SVille Syrjälä }
2020c133df69SVille Syrjälä
intel_ddi_disable_clock(struct intel_encoder * encoder)2021d39ef5d5SVille Syrjälä void intel_ddi_disable_clock(struct intel_encoder *encoder)
2022c133df69SVille Syrjälä {
2023c133df69SVille Syrjälä if (encoder->disable_clock)
2024c133df69SVille Syrjälä encoder->disable_clock(encoder);
2025c133df69SVille Syrjälä }
2026c133df69SVille Syrjälä
intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder * encoder)2027aaca50efSVille Syrjälä void intel_ddi_sanitize_encoder_pll_mapping(struct intel_encoder *encoder)
2028dc1ddac6SVille Syrjälä {
202997a24a70SVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
2030dc1ddac6SVille Syrjälä u32 port_mask;
2031dc1ddac6SVille Syrjälä bool ddi_clk_needed;
2032dc1ddac6SVille Syrjälä
2033dc1ddac6SVille Syrjälä /*
2034dc1ddac6SVille Syrjälä * In case of DP MST, we sanitize the primary encoder only, not the
2035dc1ddac6SVille Syrjälä * virtual ones.
2036dc1ddac6SVille Syrjälä */
2037dc1ddac6SVille Syrjälä if (encoder->type == INTEL_OUTPUT_DP_MST)
2038dc1ddac6SVille Syrjälä return;
2039dc1ddac6SVille Syrjälä
2040dc1ddac6SVille Syrjälä if (!encoder->base.crtc && intel_encoder_is_dp(encoder)) {
2041dc1ddac6SVille Syrjälä u8 pipe_mask;
2042dc1ddac6SVille Syrjälä bool is_mst;
2043dc1ddac6SVille Syrjälä
2044dc1ddac6SVille Syrjälä intel_ddi_get_encoder_pipes(encoder, &pipe_mask, &is_mst);
2045dc1ddac6SVille Syrjälä /*
2046dc1ddac6SVille Syrjälä * In the unlikely case that BIOS enables DP in MST mode, just
2047dc1ddac6SVille Syrjälä * warn since our MST HW readout is incomplete.
2048dc1ddac6SVille Syrjälä */
204997a24a70SVille Syrjälä if (drm_WARN_ON(&i915->drm, is_mst))
2050dc1ddac6SVille Syrjälä return;
2051dc1ddac6SVille Syrjälä }
2052dc1ddac6SVille Syrjälä
2053dc1ddac6SVille Syrjälä port_mask = BIT(encoder->port);
2054dc1ddac6SVille Syrjälä ddi_clk_needed = encoder->base.crtc;
2055dc1ddac6SVille Syrjälä
2056dc1ddac6SVille Syrjälä if (encoder->type == INTEL_OUTPUT_DSI) {
2057dc1ddac6SVille Syrjälä struct intel_encoder *other_encoder;
2058dc1ddac6SVille Syrjälä
2059dc1ddac6SVille Syrjälä port_mask = intel_dsi_encoder_ports(encoder);
2060dc1ddac6SVille Syrjälä /*
2061dc1ddac6SVille Syrjälä * Sanity check that we haven't incorrectly registered another
2062dc1ddac6SVille Syrjälä * encoder using any of the ports of this DSI encoder.
2063dc1ddac6SVille Syrjälä */
206497a24a70SVille Syrjälä for_each_intel_encoder(&i915->drm, other_encoder) {
2065dc1ddac6SVille Syrjälä if (other_encoder == encoder)
2066dc1ddac6SVille Syrjälä continue;
2067dc1ddac6SVille Syrjälä
206897a24a70SVille Syrjälä if (drm_WARN_ON(&i915->drm,
2069dc1ddac6SVille Syrjälä port_mask & BIT(other_encoder->port)))
2070dc1ddac6SVille Syrjälä return;
2071dc1ddac6SVille Syrjälä }
2072dc1ddac6SVille Syrjälä /*
2073dc1ddac6SVille Syrjälä * For DSI we keep the ddi clocks gated
2074dc1ddac6SVille Syrjälä * except during enable/disable sequence.
2075dc1ddac6SVille Syrjälä */
2076dc1ddac6SVille Syrjälä ddi_clk_needed = false;
2077dc1ddac6SVille Syrjälä }
2078dc1ddac6SVille Syrjälä
2079f82f2563SMatt Roper if (ddi_clk_needed || !encoder->is_clock_enabled ||
20800fbd8694SVille Syrjälä !encoder->is_clock_enabled(encoder))
20810fbd8694SVille Syrjälä return;
20820fbd8694SVille Syrjälä
208392959898SVille Syrjälä drm_dbg_kms(&i915->drm,
20840fbd8694SVille Syrjälä "[ENCODER:%d:%s] is disabled/in DSI mode with an ungated DDI clock, gate it\n",
20850fbd8694SVille Syrjälä encoder->base.base.id, encoder->base.name);
20860fbd8694SVille Syrjälä
2087dc1ddac6SVille Syrjälä encoder->disable_clock(encoder);
2088dc1ddac6SVille Syrjälä }
2089dc1ddac6SVille Syrjälä
20908aaf5cbdSJosé Roberto de Souza static void
icl_program_mg_dp_mode(struct intel_digital_port * dig_port,const struct intel_crtc_state * crtc_state)20917801f3b7SLucas De Marchi icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
20923b51be4eSClinton A Taylor const struct intel_crtc_state *crtc_state)
2093379bc100SJani Nikula {
20947801f3b7SLucas De Marchi struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
20957fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(&dig_port->base);
20963b51be4eSClinton A Taylor u32 ln0, ln1, pin_assignment;
20973b51be4eSClinton A Taylor u8 width;
2098379bc100SJani Nikula
2099aaf9dc86SImre Deak if (DISPLAY_VER(dev_priv) >= 14)
2100aaf9dc86SImre Deak return;
2101aaf9dc86SImre Deak
21027fcf7558SJani Nikula if (!intel_encoder_is_tc(&dig_port->base) ||
210311a89708SImre Deak intel_tc_port_in_tbt_alt_mode(dig_port))
2104379bc100SJani Nikula return;
2105379bc100SJani Nikula
2106005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) {
2107b8ed5533SImre Deak ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0));
2108b8ed5533SImre Deak ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1));
2109978c3e53SClinton A Taylor } else {
2110f7960e7fSJani Nikula ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port));
2111f7960e7fSJani Nikula ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
2112978c3e53SClinton A Taylor }
2113379bc100SJani Nikula
21144f72a8eeSKhaled Almahallawy ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2115379bc100SJani Nikula ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE);
2116379bc100SJani Nikula
21173b51be4eSClinton A Taylor /* DPPATC */
21187801f3b7SLucas De Marchi pin_assignment = intel_tc_port_get_pin_assignment_mask(dig_port);
21193b51be4eSClinton A Taylor width = crtc_state->lane_count;
2120379bc100SJani Nikula
21213b51be4eSClinton A Taylor switch (pin_assignment) {
21223b51be4eSClinton A Taylor case 0x0:
21231de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm,
212411a89708SImre Deak !intel_tc_port_in_legacy_mode(dig_port));
21253b51be4eSClinton A Taylor if (width == 1) {
2126379bc100SJani Nikula ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21273b51be4eSClinton A Taylor } else {
21283b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21293b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
2130379bc100SJani Nikula }
2131379bc100SJani Nikula break;
21323b51be4eSClinton A Taylor case 0x1:
21333b51be4eSClinton A Taylor if (width == 4) {
21343b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21353b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21363b51be4eSClinton A Taylor }
2137379bc100SJani Nikula break;
21383b51be4eSClinton A Taylor case 0x2:
21393b51be4eSClinton A Taylor if (width == 2) {
21403b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21413b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21423b51be4eSClinton A Taylor }
21433b51be4eSClinton A Taylor break;
21443b51be4eSClinton A Taylor case 0x3:
21453b51be4eSClinton A Taylor case 0x5:
21463b51be4eSClinton A Taylor if (width == 1) {
21473b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21483b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21493b51be4eSClinton A Taylor } else {
21503b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21513b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21523b51be4eSClinton A Taylor }
21533b51be4eSClinton A Taylor break;
21543b51be4eSClinton A Taylor case 0x4:
21553b51be4eSClinton A Taylor case 0x6:
21563b51be4eSClinton A Taylor if (width == 1) {
21573b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X1_MODE;
21583b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X1_MODE;
21593b51be4eSClinton A Taylor } else {
21603b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE;
21613b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE;
21623b51be4eSClinton A Taylor }
21633b51be4eSClinton A Taylor break;
2164379bc100SJani Nikula default:
21653b51be4eSClinton A Taylor MISSING_CASE(pin_assignment);
2166379bc100SJani Nikula }
2167379bc100SJani Nikula
2168005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) {
2169b8ed5533SImre Deak intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0);
2170b8ed5533SImre Deak intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1);
2171978c3e53SClinton A Taylor } else {
2172f7960e7fSJani Nikula intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0);
2173f7960e7fSJani Nikula intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1);
2174379bc100SJani Nikula }
2175978c3e53SClinton A Taylor }
2176379bc100SJani Nikula
2177ef79fafeSVille Syrjälä static enum transcoder
tgl_dp_tp_transcoder(const struct intel_crtc_state * crtc_state)2178ef79fafeSVille Syrjälä tgl_dp_tp_transcoder(const struct intel_crtc_state *crtc_state)
2179ef79fafeSVille Syrjälä {
2180ef79fafeSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
2181ef79fafeSVille Syrjälä return crtc_state->mst_master_transcoder;
2182ef79fafeSVille Syrjälä else
2183ef79fafeSVille Syrjälä return crtc_state->cpu_transcoder;
2184ef79fafeSVille Syrjälä }
2185ef79fafeSVille Syrjälä
dp_tp_ctl_reg(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)2186ef79fafeSVille Syrjälä i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder,
2187ef79fafeSVille Syrjälä const struct intel_crtc_state *crtc_state)
2188ef79fafeSVille Syrjälä {
2189ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2190ef79fafeSVille Syrjälä
2191005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12)
21923cd5a36dSJani Nikula return TGL_DP_TP_CTL(dev_priv,
21933cd5a36dSJani Nikula tgl_dp_tp_transcoder(crtc_state));
2194ef79fafeSVille Syrjälä else
2195ef79fafeSVille Syrjälä return DP_TP_CTL(encoder->port);
2196ef79fafeSVille Syrjälä }
2197ef79fafeSVille Syrjälä
dp_tp_status_reg(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)2198ef79fafeSVille Syrjälä i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder,
2199ef79fafeSVille Syrjälä const struct intel_crtc_state *crtc_state)
2200ef79fafeSVille Syrjälä {
2201ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2202ef79fafeSVille Syrjälä
2203005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12)
2204b11bf614SJani Nikula return TGL_DP_TP_STATUS(dev_priv,
2205b11bf614SJani Nikula tgl_dp_tp_transcoder(crtc_state));
2206ef79fafeSVille Syrjälä else
2207ef79fafeSVille Syrjälä return DP_TP_STATUS(encoder->port);
2208ef79fafeSVille Syrjälä }
2209ef79fafeSVille Syrjälä
intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state,bool enable)22101639406aSManasi Navare static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp,
22111639406aSManasi Navare const struct intel_crtc_state *crtc_state,
22121639406aSManasi Navare bool enable)
22131639406aSManasi Navare {
22147134cc23SJani Nikula struct intel_display *display = to_intel_display(intel_dp);
22151639406aSManasi Navare
22161639406aSManasi Navare if (!crtc_state->vrr.enable)
22171639406aSManasi Navare return;
22181639406aSManasi Navare
22191639406aSManasi Navare if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL,
22201639406aSManasi Navare enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0)
22217134cc23SJani Nikula drm_dbg_kms(display->drm,
22220868b1ceSVille Syrjälä "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n",
2223707c3a7dSLucas De Marchi str_enable_disable(enable));
22241639406aSManasi Navare }
22251639406aSManasi Navare
intel_dp_sink_set_fec_ready(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state,bool enable)2226379bc100SJani Nikula static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp,
22278ab5a036SImre Deak const struct intel_crtc_state *crtc_state,
22288ab5a036SImre Deak bool enable)
2229379bc100SJani Nikula {
22307134cc23SJani Nikula struct intel_display *display = to_intel_display(intel_dp);
223147bdb1caSJani Nikula
2232379bc100SJani Nikula if (!crtc_state->fec_enable)
2233379bc100SJani Nikula return;
2234379bc100SJani Nikula
22358ab5a036SImre Deak if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION,
22368ab5a036SImre Deak enable ? DP_FEC_READY : 0) <= 0)
22377134cc23SJani Nikula drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink\n",
22388ab5a036SImre Deak enable ? "enabled" : "disabled");
22396e916b35SImre Deak
22408ab5a036SImre Deak if (enable &&
22418ab5a036SImre Deak drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_STATUS,
22426e916b35SImre Deak DP_FEC_DECODE_EN_DETECTED | DP_FEC_DECODE_DIS_DETECTED) <= 0)
22437134cc23SJani Nikula drm_dbg_kms(display->drm, "Failed to clear FEC detected flags\n");
22446e916b35SImre Deak }
22456e916b35SImre Deak
read_fec_detected_status(struct drm_dp_aux * aux)22466e916b35SImre Deak static int read_fec_detected_status(struct drm_dp_aux *aux)
22476e916b35SImre Deak {
22486e916b35SImre Deak int ret;
22496e916b35SImre Deak u8 status;
22506e916b35SImre Deak
22516e916b35SImre Deak ret = drm_dp_dpcd_readb(aux, DP_FEC_STATUS, &status);
22526e916b35SImre Deak if (ret < 0)
22536e916b35SImre Deak return ret;
22546e916b35SImre Deak
22556e916b35SImre Deak return status;
22566e916b35SImre Deak }
22576e916b35SImre Deak
wait_for_fec_detected(struct drm_dp_aux * aux,bool enabled)22586e916b35SImre Deak static void wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled)
22596e916b35SImre Deak {
22606e916b35SImre Deak struct drm_i915_private *i915 = to_i915(aux->drm_dev);
22616e916b35SImre Deak int mask = enabled ? DP_FEC_DECODE_EN_DETECTED : DP_FEC_DECODE_DIS_DETECTED;
22626e916b35SImre Deak int status;
22636e916b35SImre Deak int err;
22646e916b35SImre Deak
22656e916b35SImre Deak err = readx_poll_timeout(read_fec_detected_status, aux, status,
22666e916b35SImre Deak status & mask || status < 0,
22676e916b35SImre Deak 10000, 200000);
22686e916b35SImre Deak
22696e916b35SImre Deak if (!err && status >= 0)
22706e916b35SImre Deak return;
22716e916b35SImre Deak
22726e916b35SImre Deak if (err == -ETIMEDOUT)
2273dd99d5b1SImre Deak drm_dbg_kms(&i915->drm, "Timeout waiting for FEC %s to get detected\n",
22746e916b35SImre Deak str_enabled_disabled(enabled));
22756e916b35SImre Deak else
22766e916b35SImre Deak drm_dbg_kms(&i915->drm, "FEC detected status read error: %d\n", status);
22776e916b35SImre Deak }
22786e916b35SImre Deak
intel_ddi_wait_for_fec_status(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,bool enabled)22796e916b35SImre Deak void intel_ddi_wait_for_fec_status(struct intel_encoder *encoder,
22806e916b35SImre Deak const struct intel_crtc_state *crtc_state,
22816e916b35SImre Deak bool enabled)
22826e916b35SImre Deak {
22836e916b35SImre Deak struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
22846e916b35SImre Deak struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
22856e916b35SImre Deak int ret;
22866e916b35SImre Deak
22876e916b35SImre Deak if (!crtc_state->fec_enable)
22886e916b35SImre Deak return;
22896e916b35SImre Deak
22906e916b35SImre Deak if (enabled)
22916e916b35SImre Deak ret = intel_de_wait_for_set(i915, dp_tp_status_reg(encoder, crtc_state),
22926e916b35SImre Deak DP_TP_STATUS_FEC_ENABLE_LIVE, 1);
22936e916b35SImre Deak else
22946e916b35SImre Deak ret = intel_de_wait_for_clear(i915, dp_tp_status_reg(encoder, crtc_state),
22956e916b35SImre Deak DP_TP_STATUS_FEC_ENABLE_LIVE, 1);
22966e916b35SImre Deak
22976e916b35SImre Deak if (ret)
22986e916b35SImre Deak drm_err(&i915->drm,
22996e916b35SImre Deak "Timeout waiting for FEC live state to get %s\n",
23006e916b35SImre Deak str_enabled_disabled(enabled));
23016e916b35SImre Deak
23026e916b35SImre Deak /*
23036e916b35SImre Deak * At least the Synoptics MST hub doesn't set the detected flag for
23046e916b35SImre Deak * FEC decoding disabling so skip waiting for that.
23056e916b35SImre Deak */
23066e916b35SImre Deak if (enabled)
23076e916b35SImre Deak wait_for_fec_detected(&intel_dp->aux, enabled);
2308379bc100SJani Nikula }
2309379bc100SJani Nikula
intel_ddi_enable_fec(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)2310379bc100SJani Nikula static void intel_ddi_enable_fec(struct intel_encoder *encoder,
2311379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
2312379bc100SJani Nikula {
2313379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2314379bc100SJani Nikula
2315379bc100SJani Nikula if (!crtc_state->fec_enable)
2316379bc100SJani Nikula return;
2317379bc100SJani Nikula
23188910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
23198910d8b7SAndrzej Hajda 0, DP_TP_CTL_FEC_ENABLE);
2320379bc100SJani Nikula }
2321379bc100SJani Nikula
intel_ddi_disable_fec(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)23220cfdf662SImre Deak static void intel_ddi_disable_fec(struct intel_encoder *encoder,
2323379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
2324379bc100SJani Nikula {
2325379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2326379bc100SJani Nikula
2327379bc100SJani Nikula if (!crtc_state->fec_enable)
2328379bc100SJani Nikula return;
2329379bc100SJani Nikula
23308910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
23318910d8b7SAndrzej Hajda DP_TP_CTL_FEC_ENABLE, 0);
2332ef79fafeSVille Syrjälä intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
2333379bc100SJani Nikula }
2334379bc100SJani Nikula
intel_ddi_power_up_lanes(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)23355cdf706fSVille Syrjälä static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
23365cdf706fSVille Syrjälä const struct intel_crtc_state *crtc_state)
23375cdf706fSVille Syrjälä {
23385cdf706fSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
23395cdf706fSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
23405cdf706fSVille Syrjälä
23417fcf7558SJani Nikula if (intel_encoder_is_combo(encoder)) {
23427fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder);
23435cdf706fSVille Syrjälä bool lane_reversal =
23445cdf706fSVille Syrjälä dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
23455cdf706fSVille Syrjälä
23465cdf706fSVille Syrjälä intel_combo_phy_power_up_lanes(i915, phy, false,
23475cdf706fSVille Syrjälä crtc_state->lane_count,
23485cdf706fSVille Syrjälä lane_reversal);
23495cdf706fSVille Syrjälä }
23505cdf706fSVille Syrjälä }
23515cdf706fSVille Syrjälä
2352a3f610ddSLuca Coelho /*
2353a3f610ddSLuca Coelho * Splitter enable for eDP MSO is limited to certain pipes, on certain
2354a3f610ddSLuca Coelho * platforms.
2355a3f610ddSLuca Coelho */
intel_ddi_splitter_pipe_mask(struct drm_i915_private * i915)2356f6864b27SJani Nikula static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915)
2357f6864b27SJani Nikula {
2358a3f610ddSLuca Coelho if (DISPLAY_VER(i915) > 20)
2359a3f610ddSLuca Coelho return ~0;
2360a3f610ddSLuca Coelho else if (IS_ALDERLAKE_P(i915))
2361f6864b27SJani Nikula return BIT(PIPE_A) | BIT(PIPE_B);
2362f6864b27SJani Nikula else
2363f6864b27SJani Nikula return BIT(PIPE_A);
2364f6864b27SJani Nikula }
2365f6864b27SJani Nikula
intel_ddi_mso_get_config(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config)23665b616a29SJani Nikula static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
23675b616a29SJani Nikula struct intel_crtc_state *pipe_config)
23685b616a29SJani Nikula {
23695b616a29SJani Nikula struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
23705b616a29SJani Nikula struct drm_i915_private *i915 = to_i915(crtc->base.dev);
23715b616a29SJani Nikula enum pipe pipe = crtc->pipe;
23725b616a29SJani Nikula u32 dss1;
23735b616a29SJani Nikula
23745b616a29SJani Nikula if (!HAS_MSO(i915))
23755b616a29SJani Nikula return;
23765b616a29SJani Nikula
23775b616a29SJani Nikula dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe));
23785b616a29SJani Nikula
23795b616a29SJani Nikula pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE;
23805b616a29SJani Nikula if (!pipe_config->splitter.enable)
23815b616a29SJani Nikula return;
23825b616a29SJani Nikula
2383f6864b27SJani Nikula if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) {
23845b616a29SJani Nikula pipe_config->splitter.enable = false;
23855b616a29SJani Nikula return;
23865b616a29SJani Nikula }
23875b616a29SJani Nikula
23885b616a29SJani Nikula switch (dss1 & SPLITTER_CONFIGURATION_MASK) {
23895b616a29SJani Nikula default:
23905b616a29SJani Nikula drm_WARN(&i915->drm, true,
23915b616a29SJani Nikula "Invalid splitter configuration, dss1=0x%08x\n", dss1);
23925b616a29SJani Nikula fallthrough;
23935b616a29SJani Nikula case SPLITTER_CONFIGURATION_2_SEGMENT:
23945b616a29SJani Nikula pipe_config->splitter.link_count = 2;
23955b616a29SJani Nikula break;
23965b616a29SJani Nikula case SPLITTER_CONFIGURATION_4_SEGMENT:
23975b616a29SJani Nikula pipe_config->splitter.link_count = 4;
23985b616a29SJani Nikula break;
23995b616a29SJani Nikula }
24005b616a29SJani Nikula
24015b616a29SJani Nikula pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1);
24025b616a29SJani Nikula }
24035b616a29SJani Nikula
intel_ddi_mso_configure(const struct intel_crtc_state * crtc_state)2404bc71194eSJani Nikula static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
2405bc71194eSJani Nikula {
2406bc71194eSJani Nikula struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2407bc71194eSJani Nikula struct drm_i915_private *i915 = to_i915(crtc->base.dev);
2408bc71194eSJani Nikula enum pipe pipe = crtc->pipe;
2409bc71194eSJani Nikula u32 dss1 = 0;
2410bc71194eSJani Nikula
2411bc71194eSJani Nikula if (!HAS_MSO(i915))
2412bc71194eSJani Nikula return;
2413bc71194eSJani Nikula
2414bc71194eSJani Nikula if (crtc_state->splitter.enable) {
2415bc71194eSJani Nikula dss1 |= SPLITTER_ENABLE;
2416bc71194eSJani Nikula dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
2417bc71194eSJani Nikula if (crtc_state->splitter.link_count == 2)
2418bc71194eSJani Nikula dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT;
2419bc71194eSJani Nikula else
2420bc71194eSJani Nikula dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT;
2421bc71194eSJani Nikula }
2422bc71194eSJani Nikula
2423bc71194eSJani Nikula intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe),
2424bc71194eSJani Nikula SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK |
2425bc71194eSJani Nikula OVERLAP_PIXELS_MASK, dss1);
2426bc71194eSJani Nikula }
2427bc71194eSJani Nikula
mtl_get_port_width(u8 lane_count)242823ef6194SJosé Roberto de Souza static u8 mtl_get_port_width(u8 lane_count)
242923ef6194SJosé Roberto de Souza {
243023ef6194SJosé Roberto de Souza switch (lane_count) {
243123ef6194SJosé Roberto de Souza case 1:
243223ef6194SJosé Roberto de Souza return 0;
243323ef6194SJosé Roberto de Souza case 2:
243423ef6194SJosé Roberto de Souza return 1;
243523ef6194SJosé Roberto de Souza case 3:
243623ef6194SJosé Roberto de Souza return 4;
243723ef6194SJosé Roberto de Souza case 4:
243823ef6194SJosé Roberto de Souza return 3;
243923ef6194SJosé Roberto de Souza default:
244023ef6194SJosé Roberto de Souza MISSING_CASE(lane_count);
244123ef6194SJosé Roberto de Souza return 4;
244223ef6194SJosé Roberto de Souza }
244323ef6194SJosé Roberto de Souza }
244423ef6194SJosé Roberto de Souza
244523ef6194SJosé Roberto de Souza static void
mtl_ddi_enable_d2d(struct intel_encoder * encoder)244623ef6194SJosé Roberto de Souza mtl_ddi_enable_d2d(struct intel_encoder *encoder)
244723ef6194SJosé Roberto de Souza {
244823ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
244923ef6194SJosé Roberto de Souza enum port port = encoder->port;
2450d5c7854bSLucas De Marchi i915_reg_t reg;
2451d5c7854bSLucas De Marchi u32 set_bits, wait_bits;
245223ef6194SJosé Roberto de Souza
2453d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20) {
2454d5c7854bSLucas De Marchi reg = DDI_BUF_CTL(port);
2455d5c7854bSLucas De Marchi set_bits = XE2LPD_DDI_BUF_D2D_LINK_ENABLE;
2456d5c7854bSLucas De Marchi wait_bits = XE2LPD_DDI_BUF_D2D_LINK_STATE;
2457d5c7854bSLucas De Marchi } else {
2458fe4c6ff5SLucas De Marchi reg = XELPDP_PORT_BUF_CTL1(dev_priv, port);
2459d5c7854bSLucas De Marchi set_bits = XELPDP_PORT_BUF_D2D_LINK_ENABLE;
2460d5c7854bSLucas De Marchi wait_bits = XELPDP_PORT_BUF_D2D_LINK_STATE;
2461d5c7854bSLucas De Marchi }
246223ef6194SJosé Roberto de Souza
2463d5c7854bSLucas De Marchi intel_de_rmw(dev_priv, reg, 0, set_bits);
2464d5c7854bSLucas De Marchi if (wait_for_us(intel_de_read(dev_priv, reg) & wait_bits, 100)) {
2465d5c7854bSLucas De Marchi drm_err(&dev_priv->drm, "Timeout waiting for D2D Link enable for DDI/PORT_BUF_CTL %c\n",
246623ef6194SJosé Roberto de Souza port_name(port));
246723ef6194SJosé Roberto de Souza }
246823ef6194SJosé Roberto de Souza }
246923ef6194SJosé Roberto de Souza
mtl_port_buf_ctl_program(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)247023ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_program(struct intel_encoder *encoder,
247123ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state)
247223ef6194SJosé Roberto de Souza {
247323ef6194SJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(encoder->base.dev);
247423ef6194SJosé Roberto de Souza struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
247523ef6194SJosé Roberto de Souza enum port port = encoder->port;
247623ef6194SJosé Roberto de Souza u32 val;
247723ef6194SJosé Roberto de Souza
2478fe4c6ff5SLucas De Marchi val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(i915, port));
247923ef6194SJosé Roberto de Souza val &= ~XELPDP_PORT_WIDTH_MASK;
248023ef6194SJosé Roberto de Souza val |= XELPDP_PORT_WIDTH(mtl_get_port_width(crtc_state->lane_count));
248123ef6194SJosé Roberto de Souza
248223ef6194SJosé Roberto de Souza val &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK;
248323ef6194SJosé Roberto de Souza if (intel_dp_is_uhbr(crtc_state))
248423ef6194SJosé Roberto de Souza val |= XELPDP_PORT_BUF_PORT_DATA_40BIT;
248523ef6194SJosé Roberto de Souza else
248623ef6194SJosé Roberto de Souza val |= XELPDP_PORT_BUF_PORT_DATA_10BIT;
248723ef6194SJosé Roberto de Souza
248823ef6194SJosé Roberto de Souza if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
248923ef6194SJosé Roberto de Souza val |= XELPDP_PORT_REVERSAL;
249023ef6194SJosé Roberto de Souza
2491fe4c6ff5SLucas De Marchi intel_de_write(i915, XELPDP_PORT_BUF_CTL1(i915, port), val);
249223ef6194SJosé Roberto de Souza }
249323ef6194SJosé Roberto de Souza
mtl_port_buf_ctl_io_selection(struct intel_encoder * encoder)249423ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_io_selection(struct intel_encoder *encoder)
249523ef6194SJosé Roberto de Souza {
249623ef6194SJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(encoder->base.dev);
249723ef6194SJosé Roberto de Souza struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
249823ef6194SJosé Roberto de Souza u32 val;
249923ef6194SJosé Roberto de Souza
250023ef6194SJosé Roberto de Souza val = intel_tc_port_in_tbt_alt_mode(dig_port) ?
250123ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_IO_SELECT_TBT : 0;
2502fe4c6ff5SLucas De Marchi intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(i915, encoder->port),
250323ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_IO_SELECT_TBT, val);
250423ef6194SJosé Roberto de Souza }
250523ef6194SJosé Roberto de Souza
mtl_ddi_pre_enable_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)250623ef6194SJosé Roberto de Souza static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state,
250723ef6194SJosé Roberto de Souza struct intel_encoder *encoder,
250823ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state,
250923ef6194SJosé Roberto de Souza const struct drm_connector_state *conn_state)
251023ef6194SJosé Roberto de Souza {
251123ef6194SJosé Roberto de Souza struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
251223ef6194SJosé Roberto de Souza bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
251323ef6194SJosé Roberto de Souza
251423ef6194SJosé Roberto de Souza intel_dp_set_link_params(intel_dp,
251523ef6194SJosé Roberto de Souza crtc_state->port_clock,
251623ef6194SJosé Roberto de Souza crtc_state->lane_count);
251723ef6194SJosé Roberto de Souza
251823ef6194SJosé Roberto de Souza /*
251923ef6194SJosé Roberto de Souza * We only configure what the register value will be here. Actual
252023ef6194SJosé Roberto de Souza * enabling happens during link training farther down.
252123ef6194SJosé Roberto de Souza */
252223ef6194SJosé Roberto de Souza intel_ddi_init_dp_buf_reg(encoder, crtc_state);
252323ef6194SJosé Roberto de Souza
252423ef6194SJosé Roberto de Souza /*
252523ef6194SJosé Roberto de Souza * 1. Enable Power Wells
252623ef6194SJosé Roberto de Souza *
252723ef6194SJosé Roberto de Souza * This was handled at the beginning of intel_atomic_commit_tail(),
252823ef6194SJosé Roberto de Souza * before we called down into this function.
252923ef6194SJosé Roberto de Souza */
253023ef6194SJosé Roberto de Souza
253123ef6194SJosé Roberto de Souza /* 2. PMdemand was already set */
253223ef6194SJosé Roberto de Souza
253323ef6194SJosé Roberto de Souza /* 3. Select Thunderbolt */
253423ef6194SJosé Roberto de Souza mtl_port_buf_ctl_io_selection(encoder);
253523ef6194SJosé Roberto de Souza
253623ef6194SJosé Roberto de Souza /* 4. Enable Panel Power if PPS is required */
253723ef6194SJosé Roberto de Souza intel_pps_on(intel_dp);
253823ef6194SJosé Roberto de Souza
253923ef6194SJosé Roberto de Souza /* 5. Enable the port PLL */
254023ef6194SJosé Roberto de Souza intel_ddi_enable_clock(encoder, crtc_state);
254123ef6194SJosé Roberto de Souza
254223ef6194SJosé Roberto de Souza /*
254323ef6194SJosé Roberto de Souza * 6.a Configure Transcoder Clock Select to direct the Port clock to the
254423ef6194SJosé Roberto de Souza * Transcoder.
254523ef6194SJosé Roberto de Souza */
254623ef6194SJosé Roberto de Souza intel_ddi_enable_transcoder_clock(encoder, crtc_state);
254723ef6194SJosé Roberto de Souza
254823ef6194SJosé Roberto de Souza /*
254923ef6194SJosé Roberto de Souza * 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings.
255023ef6194SJosé Roberto de Souza */
255123ef6194SJosé Roberto de Souza intel_ddi_config_transcoder_dp2(encoder, crtc_state);
255223ef6194SJosé Roberto de Souza
255323ef6194SJosé Roberto de Souza /*
255423ef6194SJosé Roberto de Souza * 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
255523ef6194SJosé Roberto de Souza * Transport Select
255623ef6194SJosé Roberto de Souza */
255723ef6194SJosé Roberto de Souza intel_ddi_config_transcoder_func(encoder, crtc_state);
255823ef6194SJosé Roberto de Souza
255923ef6194SJosé Roberto de Souza /*
256023ef6194SJosé Roberto de Souza * 6.e Program CoG/MSO configuration bits in DSS_CTL1 if selected.
256123ef6194SJosé Roberto de Souza */
256223ef6194SJosé Roberto de Souza intel_ddi_mso_configure(crtc_state);
256323ef6194SJosé Roberto de Souza
256423ef6194SJosé Roberto de Souza if (!is_mst)
256523ef6194SJosé Roberto de Souza intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
256623ef6194SJosé Roberto de Souza
256723ef6194SJosé Roberto de Souza intel_dp_configure_protocol_converter(intel_dp, crtc_state);
2568503611c8SImre Deak if (!is_mst)
25697c4631ffSImre Deak intel_dp_sink_enable_decompression(state,
25707c4631ffSImre Deak to_intel_connector(conn_state->connector),
25717c4631ffSImre Deak crtc_state);
2572503611c8SImre Deak
257323ef6194SJosé Roberto de Souza /*
257423ef6194SJosé Roberto de Souza * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
257523ef6194SJosé Roberto de Souza * in the FEC_CONFIGURATION register to 1 before initiating link
257623ef6194SJosé Roberto de Souza * training
257723ef6194SJosé Roberto de Souza */
25788ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true);
257923ef6194SJosé Roberto de Souza
258023ef6194SJosé Roberto de Souza intel_dp_check_frl_training(intel_dp);
258123ef6194SJosé Roberto de Souza intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
258223ef6194SJosé Roberto de Souza
258323ef6194SJosé Roberto de Souza /*
258423ef6194SJosé Roberto de Souza * 6. The rest of the below are substeps under the bspec's "Enable and
258523ef6194SJosé Roberto de Souza * Train Display Port" step. Note that steps that are specific to
258623ef6194SJosé Roberto de Souza * MST will be handled by intel_mst_pre_enable_dp() before/after it
258723ef6194SJosé Roberto de Souza * calls into this function. Also intel_mst_pre_enable_dp() only calls
258823ef6194SJosé Roberto de Souza * us when active_mst_links==0, so any steps designated for "single
258923ef6194SJosé Roberto de Souza * stream or multi-stream master transcoder" can just be performed
259023ef6194SJosé Roberto de Souza * unconditionally here.
259123ef6194SJosé Roberto de Souza *
259223ef6194SJosé Roberto de Souza * mtl_ddi_prepare_link_retrain() that is called by
259323ef6194SJosé Roberto de Souza * intel_dp_start_link_train() will execute steps: 6.d, 6.f, 6.g, 6.h,
259423ef6194SJosé Roberto de Souza * 6.i and 6.j
259523ef6194SJosé Roberto de Souza *
259623ef6194SJosé Roberto de Souza * 6.k Follow DisplayPort specification training sequence (see notes for
259723ef6194SJosé Roberto de Souza * failure handling)
259823ef6194SJosé Roberto de Souza * 6.m If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
259923ef6194SJosé Roberto de Souza * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
260023ef6194SJosé Roberto de Souza * (timeout after 800 us)
260123ef6194SJosé Roberto de Souza */
2602182c6be0SImre Deak intel_dp_start_link_train(state, intel_dp, crtc_state);
260323ef6194SJosé Roberto de Souza
260423ef6194SJosé Roberto de Souza /* 6.n Set DP_TP_CTL link training to Normal */
260523ef6194SJosé Roberto de Souza if (!is_trans_port_sync_mode(crtc_state))
260623ef6194SJosé Roberto de Souza intel_dp_stop_link_train(intel_dp, crtc_state);
260723ef6194SJosé Roberto de Souza
260823ef6194SJosé Roberto de Souza /* 6.o Configure and enable FEC if needed */
260923ef6194SJosé Roberto de Souza intel_ddi_enable_fec(encoder, crtc_state);
261023ef6194SJosé Roberto de Souza
261153f468aaSImre Deak if (!is_mst)
261223ef6194SJosé Roberto de Souza intel_dsc_dp_pps_write(encoder, crtc_state);
261323ef6194SJosé Roberto de Souza }
261423ef6194SJosé Roberto de Souza
tgl_ddi_pre_enable_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)2615ede9771dSVille Syrjälä static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
2616ede9771dSVille Syrjälä struct intel_encoder *encoder,
261799389390SJosé Roberto de Souza const struct intel_crtc_state *crtc_state,
261899389390SJosé Roberto de Souza const struct drm_connector_state *conn_state)
261999389390SJosé Roberto de Souza {
2620b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
262199389390SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2622b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
262399389390SJosé Roberto de Souza bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
262499389390SJosé Roberto de Souza
2625a621860aSVille Syrjälä intel_dp_set_link_params(intel_dp,
2626a621860aSVille Syrjälä crtc_state->port_clock,
2627a621860aSVille Syrjälä crtc_state->lane_count);
262899389390SJosé Roberto de Souza
26295e19c0b0SMatt Roper /*
26309f620f1dSVille Syrjälä * We only configure what the register value will be here. Actual
26319f620f1dSVille Syrjälä * enabling happens during link training farther down.
26329f620f1dSVille Syrjälä */
26339f620f1dSVille Syrjälä intel_ddi_init_dp_buf_reg(encoder, crtc_state);
26349f620f1dSVille Syrjälä
26359f620f1dSVille Syrjälä /*
26365e19c0b0SMatt Roper * 1. Enable Power Wells
26375e19c0b0SMatt Roper *
26385e19c0b0SMatt Roper * This was handled at the beginning of intel_atomic_commit_tail(),
26395e19c0b0SMatt Roper * before we called down into this function.
26405e19c0b0SMatt Roper */
264199389390SJosé Roberto de Souza
26425e19c0b0SMatt Roper /* 2. Enable Panel Power if PPS is required */
2643eb46f498SJani Nikula intel_pps_on(intel_dp);
264499389390SJosé Roberto de Souza
264599389390SJosé Roberto de Souza /*
26465e19c0b0SMatt Roper * 3. For non-TBT Type-C ports, set FIA lane count
26475e19c0b0SMatt Roper * (DFLEXDPSP.DPX4TXLATC)
26485e19c0b0SMatt Roper *
26495e19c0b0SMatt Roper * This was done before tgl_ddi_pre_enable_dp by
26501e98f88cSLucas De Marchi * hsw_crtc_enable()->intel_encoders_pre_pll_enable().
265199389390SJosé Roberto de Souza */
265299389390SJosé Roberto de Souza
26535e19c0b0SMatt Roper /*
26545e19c0b0SMatt Roper * 4. Enable the port PLL.
26555e19c0b0SMatt Roper *
26565e19c0b0SMatt Roper * The PLL enabling itself was already done before this function by
26571e98f88cSLucas De Marchi * hsw_crtc_enable()->intel_enable_shared_dpll(). We need only
26585e19c0b0SMatt Roper * configure the PLL to port mapping here.
26595e19c0b0SMatt Roper */
2660c133df69SVille Syrjälä intel_ddi_enable_clock(encoder, crtc_state);
26616171e58bSClinton A Taylor
26625e19c0b0SMatt Roper /* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */
266311a89708SImre Deak if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2664a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2665a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
266699389390SJosé Roberto de Souza dig_port->ddi_io_power_domain);
2667a4550977SImre Deak }
266899389390SJosé Roberto de Souza
26695e19c0b0SMatt Roper /* 6. Program DP_MODE */
26703b51be4eSClinton A Taylor icl_program_mg_dp_mode(dig_port, crtc_state);
267199389390SJosé Roberto de Souza
267299389390SJosé Roberto de Souza /*
26735e19c0b0SMatt Roper * 7. The rest of the below are substeps under the bspec's "Enable and
26745e19c0b0SMatt Roper * Train Display Port" step. Note that steps that are specific to
26755e19c0b0SMatt Roper * MST will be handled by intel_mst_pre_enable_dp() before/after it
26765e19c0b0SMatt Roper * calls into this function. Also intel_mst_pre_enable_dp() only calls
26775e19c0b0SMatt Roper * us when active_mst_links==0, so any steps designated for "single
26785e19c0b0SMatt Roper * stream or multi-stream master transcoder" can just be performed
26795e19c0b0SMatt Roper * unconditionally here.
26805e19c0b0SMatt Roper */
26815e19c0b0SMatt Roper
26825e19c0b0SMatt Roper /*
26835e19c0b0SMatt Roper * 7.a Configure Transcoder Clock Select to direct the Port clock to the
26845e19c0b0SMatt Roper * Transcoder.
268599389390SJosé Roberto de Souza */
268655a4679eSVille Syrjälä intel_ddi_enable_transcoder_clock(encoder, crtc_state);
268799389390SJosé Roberto de Souza
2688fe6959a6SVille Syrjälä if (HAS_DP20(dev_priv))
2689fe6959a6SVille Syrjälä intel_ddi_config_transcoder_dp2(encoder, crtc_state);
2690fe6959a6SVille Syrjälä
26915e19c0b0SMatt Roper /*
26925e19c0b0SMatt Roper * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST
26935e19c0b0SMatt Roper * Transport Select
26945e19c0b0SMatt Roper */
2695eed22a46SVille Syrjälä intel_ddi_config_transcoder_func(encoder, crtc_state);
269699389390SJosé Roberto de Souza
26975e19c0b0SMatt Roper /*
26985e19c0b0SMatt Roper * 7.c Configure & enable DP_TP_CTL with link training pattern 1
26995e19c0b0SMatt Roper * selected
27005e19c0b0SMatt Roper *
27015e19c0b0SMatt Roper * This will be handled by the intel_dp_start_link_train() farther
27025e19c0b0SMatt Roper * down this function.
27035e19c0b0SMatt Roper */
27045e19c0b0SMatt Roper
27055e19c0b0SMatt Roper /* 7.e Configure voltage swing and related IO settings */
2706e722ab8bSVille Syrjälä encoder->set_signal_levels(encoder, crtc_state);
270799389390SJosé Roberto de Souza
27085e19c0b0SMatt Roper /*
27095e19c0b0SMatt Roper * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up
27105e19c0b0SMatt Roper * the used lanes of the DDI.
27115e19c0b0SMatt Roper */
27125cdf706fSVille Syrjälä intel_ddi_power_up_lanes(encoder, crtc_state);
271399389390SJosé Roberto de Souza
27145e19c0b0SMatt Roper /*
2715bc71194eSJani Nikula * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected.
2716bc71194eSJani Nikula */
2717bc71194eSJani Nikula intel_ddi_mso_configure(crtc_state);
2718bc71194eSJani Nikula
271999389390SJosé Roberto de Souza if (!is_mst)
27200e634efdSVille Syrjälä intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
272199389390SJosé Roberto de Souza
2722522508b6SAnkit Nautiyal intel_dp_configure_protocol_converter(intel_dp, crtc_state);
2723503611c8SImre Deak if (!is_mst)
27247c4631ffSImre Deak intel_dp_sink_enable_decompression(state,
27257c4631ffSImre Deak to_intel_connector(conn_state->connector),
27267c4631ffSImre Deak crtc_state);
272799389390SJosé Roberto de Souza /*
272899389390SJosé Roberto de Souza * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit
272999389390SJosé Roberto de Souza * in the FEC_CONFIGURATION register to 1 before initiating link
273099389390SJosé Roberto de Souza * training
273199389390SJosé Roberto de Souza */
27328ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true);
27335e19c0b0SMatt Roper
27344f3dd47aSAnkit Nautiyal intel_dp_check_frl_training(intel_dp);
273510fec80bSAnkit Nautiyal intel_dp_pcon_dsc_configure(intel_dp, crtc_state);
27364f3dd47aSAnkit Nautiyal
27375e19c0b0SMatt Roper /*
27385e19c0b0SMatt Roper * 7.i Follow DisplayPort specification training sequence (see notes for
27395e19c0b0SMatt Roper * failure handling)
27405e19c0b0SMatt Roper * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle
27415e19c0b0SMatt Roper * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent)
27425e19c0b0SMatt Roper * (timeout after 800 us)
27435e19c0b0SMatt Roper */
2744182c6be0SImre Deak intel_dp_start_link_train(state, intel_dp, crtc_state);
274599389390SJosé Roberto de Souza
27465e19c0b0SMatt Roper /* 7.k Set DP_TP_CTL link training to Normal */
2747eadf6f91SManasi Navare if (!is_trans_port_sync_mode(crtc_state))
2748a621860aSVille Syrjälä intel_dp_stop_link_train(intel_dp, crtc_state);
274999389390SJosé Roberto de Souza
27505e19c0b0SMatt Roper /* 7.l Configure and enable FEC if needed */
275199389390SJosé Roberto de Souza intel_ddi_enable_fec(encoder, crtc_state);
27523126977dSVille Syrjälä
275353f468aaSImre Deak if (!is_mst)
27543126977dSVille Syrjälä intel_dsc_dp_pps_write(encoder, crtc_state);
275599389390SJosé Roberto de Souza }
275699389390SJosé Roberto de Souza
hsw_ddi_pre_enable_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)2757ede9771dSVille Syrjälä static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
2758ede9771dSVille Syrjälä struct intel_encoder *encoder,
2759379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
2760379bc100SJani Nikula const struct drm_connector_state *conn_state)
2761379bc100SJani Nikula {
2762b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2763379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2764379bc100SJani Nikula enum port port = encoder->port;
2765b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2766379bc100SJani Nikula bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST);
2767379bc100SJani Nikula
2768005e9537SMatt Roper if (DISPLAY_VER(dev_priv) < 11)
27691de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm,
27701de143ccSPankaj Bharadiya is_mst && (port == PORT_A || port == PORT_E));
2771542dfab5SJosé Roberto de Souza else
27721de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, is_mst && port == PORT_A);
2773379bc100SJani Nikula
2774a621860aSVille Syrjälä intel_dp_set_link_params(intel_dp,
2775a621860aSVille Syrjälä crtc_state->port_clock,
2776a621860aSVille Syrjälä crtc_state->lane_count);
2777379bc100SJani Nikula
27789f620f1dSVille Syrjälä /*
27799f620f1dSVille Syrjälä * We only configure what the register value will be here. Actual
27809f620f1dSVille Syrjälä * enabling happens during link training farther down.
27819f620f1dSVille Syrjälä */
27829f620f1dSVille Syrjälä intel_ddi_init_dp_buf_reg(encoder, crtc_state);
27839f620f1dSVille Syrjälä
2784eb46f498SJani Nikula intel_pps_on(intel_dp);
2785379bc100SJani Nikula
2786c133df69SVille Syrjälä intel_ddi_enable_clock(encoder, crtc_state);
2787379bc100SJani Nikula
278811a89708SImre Deak if (!intel_tc_port_in_tbt_alt_mode(dig_port)) {
2789a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2790a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
27913b2ed431SImre Deak dig_port->ddi_io_power_domain);
2792a4550977SImre Deak }
2793379bc100SJani Nikula
27943b51be4eSClinton A Taylor icl_program_mg_dp_mode(dig_port, crtc_state);
2795379bc100SJani Nikula
27965bafd85dSVille Syrjälä if (has_buf_trans_select(dev_priv))
2797266152aeSVille Syrjälä hsw_prepare_dp_ddi_buffers(encoder, crtc_state);
2798379bc100SJani Nikula
2799e722ab8bSVille Syrjälä encoder->set_signal_levels(encoder, crtc_state);
2800e722ab8bSVille Syrjälä
28015cdf706fSVille Syrjälä intel_ddi_power_up_lanes(encoder, crtc_state);
2802379bc100SJani Nikula
2803379bc100SJani Nikula if (!is_mst)
28040e634efdSVille Syrjälä intel_dp_set_power(intel_dp, DP_SET_POWER_D0);
2805522508b6SAnkit Nautiyal intel_dp_configure_protocol_converter(intel_dp, crtc_state);
2806503611c8SImre Deak if (!is_mst)
28077c4631ffSImre Deak intel_dp_sink_enable_decompression(state,
28087c4631ffSImre Deak to_intel_connector(conn_state->connector),
28097c4631ffSImre Deak crtc_state);
28108ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true);
2811182c6be0SImre Deak intel_dp_start_link_train(state, intel_dp, crtc_state);
2812005e9537SMatt Roper if ((port != PORT_A || DISPLAY_VER(dev_priv) >= 9) &&
2813eadf6f91SManasi Navare !is_trans_port_sync_mode(crtc_state))
2814a621860aSVille Syrjälä intel_dp_stop_link_train(intel_dp, crtc_state);
2815379bc100SJani Nikula
2816379bc100SJani Nikula intel_ddi_enable_fec(encoder, crtc_state);
2817379bc100SJani Nikula
281853f468aaSImre Deak if (!is_mst) {
281955a4679eSVille Syrjälä intel_ddi_enable_transcoder_clock(encoder, crtc_state);
28203126977dSVille Syrjälä intel_dsc_dp_pps_write(encoder, crtc_state);
2821379bc100SJani Nikula }
282253f468aaSImre Deak }
2823379bc100SJani Nikula
intel_ddi_pre_enable_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)2824ede9771dSVille Syrjälä static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state,
2825ede9771dSVille Syrjälä struct intel_encoder *encoder,
282699389390SJosé Roberto de Souza const struct intel_crtc_state *crtc_state,
282799389390SJosé Roberto de Souza const struct drm_connector_state *conn_state)
282899389390SJosé Roberto de Souza {
282999389390SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
283099389390SJosé Roberto de Souza
283188ae6c65SJouni Högander if (HAS_DP20(dev_priv))
28321a324a40SArun R Murthy intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder),
28331a324a40SArun R Murthy crtc_state);
283488ae6c65SJouni Högander
283588ae6c65SJouni Högander /* Panel replay has to be enabled in sink dpcd before link training. */
28363257e55dSAnimesh Manna if (crtc_state->has_panel_replay)
283788ae6c65SJouni Högander intel_psr_enable_sink(enc_to_intel_dp(encoder), crtc_state);
28381a324a40SArun R Murthy
283923ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14)
284023ef6194SJosé Roberto de Souza mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
284123ef6194SJosé Roberto de Souza else if (DISPLAY_VER(dev_priv) >= 12)
2842ede9771dSVille Syrjälä tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
284399389390SJosé Roberto de Souza else
2844ede9771dSVille Syrjälä hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state);
28450c06fa15SGwan-gyeong Mun
2846bd8c9ccaSGwan-gyeong Mun /* MST will call a setting of MSA after an allocating of Virtual Channel
2847bd8c9ccaSGwan-gyeong Mun * from MST encoder pre_enable callback.
2848bd8c9ccaSGwan-gyeong Mun */
28498de5df3bSVille Syrjälä if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
28500c06fa15SGwan-gyeong Mun intel_ddi_set_dp_msa(crtc_state, conn_state);
28511fc1e8d4SJosé Roberto de Souza }
285299389390SJosé Roberto de Souza
intel_ddi_pre_enable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)2853ede9771dSVille Syrjälä static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state,
2854ede9771dSVille Syrjälä struct intel_encoder *encoder,
2855379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
2856379bc100SJani Nikula const struct drm_connector_state *conn_state)
2857379bc100SJani Nikula {
28580ba7ffeaSLucas De Marchi struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
28590ba7ffeaSLucas De Marchi struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
2860379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2861379bc100SJani Nikula
2862379bc100SJani Nikula intel_dp_dual_mode_set_tmds_output(intel_hdmi, true);
2863c133df69SVille Syrjälä intel_ddi_enable_clock(encoder, crtc_state);
2864379bc100SJani Nikula
2865a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref);
2866a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv,
2867a4550977SImre Deak dig_port->ddi_io_power_domain);
2868379bc100SJani Nikula
28693b51be4eSClinton A Taylor icl_program_mg_dp_mode(dig_port, crtc_state);
2870379bc100SJani Nikula
287155a4679eSVille Syrjälä intel_ddi_enable_transcoder_clock(encoder, crtc_state);
2872379bc100SJani Nikula
28730ba7ffeaSLucas De Marchi dig_port->set_infoframes(encoder,
2874379bc100SJani Nikula crtc_state->has_infoframe,
2875379bc100SJani Nikula crtc_state, conn_state);
2876379bc100SJani Nikula }
2877379bc100SJani Nikula
intel_ddi_pre_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)2878ede9771dSVille Syrjälä static void intel_ddi_pre_enable(struct intel_atomic_state *state,
2879ede9771dSVille Syrjälä struct intel_encoder *encoder,
2880379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
2881379bc100SJani Nikula const struct drm_connector_state *conn_state)
2882379bc100SJani Nikula {
28832225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2884379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2885379bc100SJani Nikula enum pipe pipe = crtc->pipe;
2886379bc100SJani Nikula
2887379bc100SJani Nikula /*
2888379bc100SJani Nikula * When called from DP MST code:
2889379bc100SJani Nikula * - conn_state will be NULL
2890379bc100SJani Nikula * - encoder will be the main encoder (ie. mst->primary)
2891379bc100SJani Nikula * - the main connector associated with this port
2892379bc100SJani Nikula * won't be active or linked to a crtc
2893379bc100SJani Nikula * - crtc_state will be the state of the first stream to
2894379bc100SJani Nikula * be activated on this port, and it may not be the same
2895379bc100SJani Nikula * stream that will be deactivated last, but each stream
2896379bc100SJani Nikula * should have a state that is identical when it comes to
2897379bc100SJani Nikula * the DP link parameteres
2898379bc100SJani Nikula */
2899379bc100SJani Nikula
29001de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder);
2901379bc100SJani Nikula
2902379bc100SJani Nikula intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
2903379bc100SJani Nikula
2904379bc100SJani Nikula if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
2905ede9771dSVille Syrjälä intel_ddi_pre_enable_hdmi(state, encoder, crtc_state,
2906ede9771dSVille Syrjälä conn_state);
2907379bc100SJani Nikula } else {
2908f7af425dSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
2909379bc100SJani Nikula
2910ede9771dSVille Syrjälä intel_ddi_pre_enable_dp(state, encoder, crtc_state,
2911ede9771dSVille Syrjälä conn_state);
2912379bc100SJani Nikula
2913f7af425dSVille Syrjälä /* FIXME precompute everything properly */
29140ea02bb8SJosé Roberto de Souza /* FIXME how do we turn infoframes off again? */
29157ffa2f27SJani Nikula if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
2916379bc100SJani Nikula dig_port->set_infoframes(encoder,
2917379bc100SJani Nikula crtc_state->has_infoframe,
2918379bc100SJani Nikula crtc_state, conn_state);
2919379bc100SJani Nikula }
2920379bc100SJani Nikula }
2921379bc100SJani Nikula
292223ef6194SJosé Roberto de Souza static void
mtl_ddi_disable_d2d_link(struct intel_encoder * encoder)292323ef6194SJosé Roberto de Souza mtl_ddi_disable_d2d_link(struct intel_encoder *encoder)
292423ef6194SJosé Roberto de Souza {
292523ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
292623ef6194SJosé Roberto de Souza enum port port = encoder->port;
2927d5c7854bSLucas De Marchi i915_reg_t reg;
2928d5c7854bSLucas De Marchi u32 clr_bits, wait_bits;
292923ef6194SJosé Roberto de Souza
2930d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20) {
2931d5c7854bSLucas De Marchi reg = DDI_BUF_CTL(port);
2932d5c7854bSLucas De Marchi clr_bits = XE2LPD_DDI_BUF_D2D_LINK_ENABLE;
2933d5c7854bSLucas De Marchi wait_bits = XE2LPD_DDI_BUF_D2D_LINK_STATE;
2934d5c7854bSLucas De Marchi } else {
2935fe4c6ff5SLucas De Marchi reg = XELPDP_PORT_BUF_CTL1(dev_priv, port);
2936d5c7854bSLucas De Marchi clr_bits = XELPDP_PORT_BUF_D2D_LINK_ENABLE;
2937d5c7854bSLucas De Marchi wait_bits = XELPDP_PORT_BUF_D2D_LINK_STATE;
2938d5c7854bSLucas De Marchi }
293923ef6194SJosé Roberto de Souza
2940d5c7854bSLucas De Marchi intel_de_rmw(dev_priv, reg, clr_bits, 0);
2941d5c7854bSLucas De Marchi if (wait_for_us(!(intel_de_read(dev_priv, reg) & wait_bits), 100))
2942d5c7854bSLucas De Marchi drm_err(&dev_priv->drm, "Timeout waiting for D2D Link disable for DDI/PORT_BUF_CTL %c\n",
294323ef6194SJosé Roberto de Souza port_name(port));
294423ef6194SJosé Roberto de Souza }
294523ef6194SJosé Roberto de Souza
mtl_disable_ddi_buf(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)294623ef6194SJosé Roberto de Souza static void mtl_disable_ddi_buf(struct intel_encoder *encoder,
294723ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state)
294823ef6194SJosé Roberto de Souza {
294923ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
295023ef6194SJosé Roberto de Souza enum port port = encoder->port;
295123ef6194SJosé Roberto de Souza u32 val;
295223ef6194SJosé Roberto de Souza
295323ef6194SJosé Roberto de Souza /* 3.b Clear DDI_CTL_DE Enable to 0. */
295423ef6194SJosé Roberto de Souza val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
295523ef6194SJosé Roberto de Souza if (val & DDI_BUF_CTL_ENABLE) {
295623ef6194SJosé Roberto de Souza val &= ~DDI_BUF_CTL_ENABLE;
295723ef6194SJosé Roberto de Souza intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
295823ef6194SJosé Roberto de Souza
295923ef6194SJosé Roberto de Souza /* 3.c Poll for PORT_BUF_CTL Idle Status == 1, timeout after 100us */
296023ef6194SJosé Roberto de Souza mtl_wait_ddi_buf_idle(dev_priv, port);
296123ef6194SJosé Roberto de Souza }
296223ef6194SJosé Roberto de Souza
296323ef6194SJosé Roberto de Souza /* 3.d Disable D2D Link */
296423ef6194SJosé Roberto de Souza mtl_ddi_disable_d2d_link(encoder);
296523ef6194SJosé Roberto de Souza
296623ef6194SJosé Roberto de Souza /* 3.e Disable DP_TP_CTL */
296723ef6194SJosé Roberto de Souza if (intel_crtc_has_dp_encoder(crtc_state)) {
296823ef6194SJosé Roberto de Souza intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
296923ef6194SJosé Roberto de Souza DP_TP_CTL_ENABLE, 0);
297023ef6194SJosé Roberto de Souza }
297123ef6194SJosé Roberto de Souza }
297223ef6194SJosé Roberto de Souza
disable_ddi_buf(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)297323ef6194SJosé Roberto de Souza static void disable_ddi_buf(struct intel_encoder *encoder,
2974379bc100SJani Nikula const struct intel_crtc_state *crtc_state)
2975379bc100SJani Nikula {
2976379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2977379bc100SJani Nikula enum port port = encoder->port;
2978379bc100SJani Nikula bool wait = false;
2979379bc100SJani Nikula u32 val;
2980379bc100SJani Nikula
2981f7960e7fSJani Nikula val = intel_de_read(dev_priv, DDI_BUF_CTL(port));
2982379bc100SJani Nikula if (val & DDI_BUF_CTL_ENABLE) {
2983379bc100SJani Nikula val &= ~DDI_BUF_CTL_ENABLE;
2984f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_CTL(port), val);
2985379bc100SJani Nikula wait = true;
2986379bc100SJani Nikula }
2987379bc100SJani Nikula
29888910d8b7SAndrzej Hajda if (intel_crtc_has_dp_encoder(crtc_state))
29898910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
29908c042949SVille Syrjälä DP_TP_CTL_ENABLE, 0);
2991379bc100SJani Nikula
29920cfdf662SImre Deak intel_ddi_disable_fec(encoder, crtc_state);
2993379bc100SJani Nikula
2994379bc100SJani Nikula if (wait)
2995379bc100SJani Nikula intel_wait_ddi_buf_idle(dev_priv, port);
2996379bc100SJani Nikula }
2997379bc100SJani Nikula
intel_disable_ddi_buf(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)299823ef6194SJosé Roberto de Souza static void intel_disable_ddi_buf(struct intel_encoder *encoder,
299923ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state)
300023ef6194SJosé Roberto de Souza {
300123ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
300223ef6194SJosé Roberto de Souza
300323ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14) {
300423ef6194SJosé Roberto de Souza mtl_disable_ddi_buf(encoder, crtc_state);
300523ef6194SJosé Roberto de Souza
300623ef6194SJosé Roberto de Souza /* 3.f Disable DP_TP_CTL FEC Enable if it is needed */
30070cfdf662SImre Deak intel_ddi_disable_fec(encoder, crtc_state);
300823ef6194SJosé Roberto de Souza } else {
300923ef6194SJosé Roberto de Souza disable_ddi_buf(encoder, crtc_state);
301023ef6194SJosé Roberto de Souza }
30116e916b35SImre Deak
30126e916b35SImre Deak intel_ddi_wait_for_fec_status(encoder, crtc_state, false);
301323ef6194SJosé Roberto de Souza }
301423ef6194SJosé Roberto de Souza
intel_ddi_post_disable_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3015ede9771dSVille Syrjälä static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
3016ede9771dSVille Syrjälä struct intel_encoder *encoder,
3017379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state,
3018379bc100SJani Nikula const struct drm_connector_state *old_conn_state)
3019379bc100SJani Nikula {
3020379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3021b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3022379bc100SJani Nikula struct intel_dp *intel_dp = &dig_port->dp;
302323ef6194SJosé Roberto de Souza intel_wakeref_t wakeref;
3024379bc100SJani Nikula bool is_mst = intel_crtc_has_type(old_crtc_state,
3025379bc100SJani Nikula INTEL_OUTPUT_DP_MST);
3026379bc100SJani Nikula
3027c980216dSImre Deak if (!is_mst)
3028c980216dSImre Deak intel_dp_set_infoframes(encoder, false,
3029c980216dSImre Deak old_crtc_state, old_conn_state);
3030fa37a213SGwan-gyeong Mun
3031379bc100SJani Nikula /*
3032379bc100SJani Nikula * Power down sink before disabling the port, otherwise we end
3033379bc100SJani Nikula * up getting interrupts from the sink on detecting link loss.
3034379bc100SJani Nikula */
30350e634efdSVille Syrjälä intel_dp_set_power(intel_dp, DP_SET_POWER_D3);
303678eaaba3SJosé Roberto de Souza
3037005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) {
3038c59053dcSJosé Roberto de Souza if (is_mst) {
3039c59053dcSJosé Roberto de Souza enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
3040c59053dcSJosé Roberto de Souza
3041b092d6adSJani Nikula intel_de_rmw(dev_priv,
3042b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder),
30438910d8b7SAndrzej Hajda TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK,
30448910d8b7SAndrzej Hajda 0);
3045c59053dcSJosé Roberto de Souza }
3046c59053dcSJosé Roberto de Souza } else {
3047c59053dcSJosé Roberto de Souza if (!is_mst)
304855a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state);
3049c59053dcSJosé Roberto de Souza }
3050379bc100SJani Nikula
3051379bc100SJani Nikula intel_disable_ddi_buf(encoder, old_crtc_state);
3052379bc100SJani Nikula
30538ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, old_crtc_state, false);
30548ab5a036SImre Deak
30553ca8f191SJosé Roberto de Souza /*
30563ca8f191SJosé Roberto de Souza * From TGL spec: "If single stream or multi-stream master transcoder:
30573ca8f191SJosé Roberto de Souza * Configure Transcoder Clock select to direct no clock to the
30583ca8f191SJosé Roberto de Souza * transcoder"
30593ca8f191SJosé Roberto de Souza */
3060005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12)
306155a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state);
30623ca8f191SJosé Roberto de Souza
3063eb46f498SJani Nikula intel_pps_vdd_on(intel_dp);
3064eb46f498SJani Nikula intel_pps_off(intel_dp);
3065379bc100SJani Nikula
306623ef6194SJosé Roberto de Souza wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
306723ef6194SJosé Roberto de Souza
306823ef6194SJosé Roberto de Souza if (wakeref)
3069a4550977SImre Deak intel_display_power_put(dev_priv,
3070a4550977SImre Deak dig_port->ddi_io_power_domain,
307123ef6194SJosé Roberto de Souza wakeref);
3072379bc100SJani Nikula
3073c133df69SVille Syrjälä intel_ddi_disable_clock(encoder);
307423ef6194SJosé Roberto de Souza
307523ef6194SJosé Roberto de Souza /* De-select Thunderbolt */
307623ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14)
3077fe4c6ff5SLucas De Marchi intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(dev_priv, encoder->port),
307823ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_IO_SELECT_TBT, 0);
3079379bc100SJani Nikula }
3080379bc100SJani Nikula
intel_ddi_post_disable_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3081ede9771dSVille Syrjälä static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state,
3082ede9771dSVille Syrjälä struct intel_encoder *encoder,
3083379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state,
3084379bc100SJani Nikula const struct drm_connector_state *old_conn_state)
3085379bc100SJani Nikula {
3086379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3087b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3088379bc100SJani Nikula struct intel_hdmi *intel_hdmi = &dig_port->hdmi;
308923ef6194SJosé Roberto de Souza intel_wakeref_t wakeref;
3090379bc100SJani Nikula
3091379bc100SJani Nikula dig_port->set_infoframes(encoder, false,
3092379bc100SJani Nikula old_crtc_state, old_conn_state);
3093379bc100SJani Nikula
3094c1949189SImre Deak if (DISPLAY_VER(dev_priv) < 12)
309555a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state);
3096379bc100SJani Nikula
3097379bc100SJani Nikula intel_disable_ddi_buf(encoder, old_crtc_state);
3098379bc100SJani Nikula
3099c1949189SImre Deak if (DISPLAY_VER(dev_priv) >= 12)
310055a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state);
3101c1949189SImre Deak
310223ef6194SJosé Roberto de Souza wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref);
310323ef6194SJosé Roberto de Souza if (wakeref)
3104a4550977SImre Deak intel_display_power_put(dev_priv,
3105a4550977SImre Deak dig_port->ddi_io_power_domain,
310623ef6194SJosé Roberto de Souza wakeref);
3107379bc100SJani Nikula
3108c133df69SVille Syrjälä intel_ddi_disable_clock(encoder);
3109379bc100SJani Nikula
3110379bc100SJani Nikula intel_dp_dual_mode_set_tmds_output(intel_hdmi, false);
3111379bc100SJani Nikula }
3112379bc100SJani Nikula
intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3113f3b93eaeSVille Syrjälä static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state,
3114ede9771dSVille Syrjälä struct intel_encoder *encoder,
3115379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state,
3116379bc100SJani Nikula const struct drm_connector_state *old_conn_state)
3117379bc100SJani Nikula {
3118379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3119b7ce2803SVille Syrjälä struct intel_crtc *pipe_crtc;
3120379bc100SJani Nikula
3121b7ce2803SVille Syrjälä for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
3122b7ce2803SVille Syrjälä intel_crtc_joined_pipe_mask(old_crtc_state)) {
3123b7ce2803SVille Syrjälä const struct intel_crtc_state *old_pipe_crtc_state =
3124b7ce2803SVille Syrjälä intel_atomic_get_old_crtc_state(state, pipe_crtc);
3125b7ce2803SVille Syrjälä
3126b7ce2803SVille Syrjälä intel_crtc_vblank_off(old_pipe_crtc_state);
3127b7ce2803SVille Syrjälä }
3128773b4b54SVille Syrjälä
31290504d0acSVille Syrjälä intel_disable_transcoder(old_crtc_state);
31300504d0acSVille Syrjälä
3131773b4b54SVille Syrjälä intel_ddi_disable_transcoder_func(old_crtc_state);
3132773b4b54SVille Syrjälä
3133b7ce2803SVille Syrjälä for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc,
3134b7ce2803SVille Syrjälä intel_crtc_joined_pipe_mask(old_crtc_state)) {
3135b7ce2803SVille Syrjälä const struct intel_crtc_state *old_pipe_crtc_state =
3136b7ce2803SVille Syrjälä intel_atomic_get_old_crtc_state(state, pipe_crtc);
3137b7ce2803SVille Syrjälä
3138b7ce2803SVille Syrjälä intel_dsc_disable(old_pipe_crtc_state);
3139773b4b54SVille Syrjälä
3140005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 9)
3141b7ce2803SVille Syrjälä skl_scaler_disable(old_pipe_crtc_state);
3142773b4b54SVille Syrjälä else
3143b7ce2803SVille Syrjälä ilk_pfit_disable(old_pipe_crtc_state);
31444e3cdb45SManasi Navare }
3145f3b93eaeSVille Syrjälä }
3146f3b93eaeSVille Syrjälä
intel_ddi_post_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3147f3b93eaeSVille Syrjälä static void intel_ddi_post_disable(struct intel_atomic_state *state,
3148f3b93eaeSVille Syrjälä struct intel_encoder *encoder,
3149f3b93eaeSVille Syrjälä const struct intel_crtc_state *old_crtc_state,
3150f3b93eaeSVille Syrjälä const struct drm_connector_state *old_conn_state)
3151f3b93eaeSVille Syrjälä {
3152f3b93eaeSVille Syrjälä if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST))
3153f3b93eaeSVille Syrjälä intel_ddi_post_disable_hdmi_or_sst(state, encoder, old_crtc_state,
3154f3b93eaeSVille Syrjälä old_conn_state);
31554e3cdb45SManasi Navare
3156379bc100SJani Nikula /*
3157379bc100SJani Nikula * When called from DP MST code:
3158379bc100SJani Nikula * - old_conn_state will be NULL
3159379bc100SJani Nikula * - encoder will be the main encoder (ie. mst->primary)
3160379bc100SJani Nikula * - the main connector associated with this port
3161379bc100SJani Nikula * won't be active or linked to a crtc
3162379bc100SJani Nikula * - old_crtc_state will be the state of the last stream to
3163379bc100SJani Nikula * be deactivated on this port, and it may not be the same
3164379bc100SJani Nikula * stream that was activated last, but each stream
3165379bc100SJani Nikula * should have a state that is identical when it comes to
3166379bc100SJani Nikula * the DP link parameteres
3167379bc100SJani Nikula */
3168379bc100SJani Nikula
3169379bc100SJani Nikula if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3170ede9771dSVille Syrjälä intel_ddi_post_disable_hdmi(state, encoder, old_crtc_state,
3171ede9771dSVille Syrjälä old_conn_state);
3172379bc100SJani Nikula else
3173ede9771dSVille Syrjälä intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
3174ede9771dSVille Syrjälä old_conn_state);
3175b108bdd0SImre Deak }
3176b108bdd0SImre Deak
intel_ddi_post_pll_disable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3177b108bdd0SImre Deak static void intel_ddi_post_pll_disable(struct intel_atomic_state *state,
3178b108bdd0SImre Deak struct intel_encoder *encoder,
3179b108bdd0SImre Deak const struct intel_crtc_state *old_crtc_state,
3180b108bdd0SImre Deak const struct drm_connector_state *old_conn_state)
3181b108bdd0SImre Deak {
3182b108bdd0SImre Deak struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3183379bc100SJani Nikula
3184637c7aa2SImre Deak main_link_aux_power_domain_put(dig_port, old_crtc_state);
318517bef9baSVille Syrjälä
31867fcf7558SJani Nikula if (intel_encoder_is_tc(encoder))
318717bef9baSVille Syrjälä intel_tc_port_put_link(dig_port);
3188379bc100SJani Nikula }
3189379bc100SJani Nikula
trans_port_sync_stop_link_train(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)3190d82a855aSVille Syrjälä static void trans_port_sync_stop_link_train(struct intel_atomic_state *state,
3191d82a855aSVille Syrjälä struct intel_encoder *encoder,
3192d82a855aSVille Syrjälä const struct intel_crtc_state *crtc_state)
3193d82a855aSVille Syrjälä {
3194d82a855aSVille Syrjälä const struct drm_connector_state *conn_state;
3195d82a855aSVille Syrjälä struct drm_connector *conn;
3196d82a855aSVille Syrjälä int i;
3197d82a855aSVille Syrjälä
3198d82a855aSVille Syrjälä if (!crtc_state->sync_mode_slaves_mask)
3199d82a855aSVille Syrjälä return;
3200d82a855aSVille Syrjälä
3201d82a855aSVille Syrjälä for_each_new_connector_in_state(&state->base, conn, conn_state, i) {
3202d82a855aSVille Syrjälä struct intel_encoder *slave_encoder =
3203d82a855aSVille Syrjälä to_intel_encoder(conn_state->best_encoder);
3204d82a855aSVille Syrjälä struct intel_crtc *slave_crtc = to_intel_crtc(conn_state->crtc);
3205d82a855aSVille Syrjälä const struct intel_crtc_state *slave_crtc_state;
3206d82a855aSVille Syrjälä
3207d82a855aSVille Syrjälä if (!slave_crtc)
3208d82a855aSVille Syrjälä continue;
3209d82a855aSVille Syrjälä
3210d82a855aSVille Syrjälä slave_crtc_state =
3211d82a855aSVille Syrjälä intel_atomic_get_new_crtc_state(state, slave_crtc);
3212d82a855aSVille Syrjälä
3213d82a855aSVille Syrjälä if (slave_crtc_state->master_transcoder !=
3214d82a855aSVille Syrjälä crtc_state->cpu_transcoder)
3215d82a855aSVille Syrjälä continue;
3216d82a855aSVille Syrjälä
3217a621860aSVille Syrjälä intel_dp_stop_link_train(enc_to_intel_dp(slave_encoder),
3218a621860aSVille Syrjälä slave_crtc_state);
3219d82a855aSVille Syrjälä }
3220d82a855aSVille Syrjälä
3221d82a855aSVille Syrjälä usleep_range(200, 400);
3222d82a855aSVille Syrjälä
3223a621860aSVille Syrjälä intel_dp_stop_link_train(enc_to_intel_dp(encoder),
3224a621860aSVille Syrjälä crtc_state);
3225d82a855aSVille Syrjälä }
3226d82a855aSVille Syrjälä
intel_enable_ddi_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3227ede9771dSVille Syrjälä static void intel_enable_ddi_dp(struct intel_atomic_state *state,
3228ede9771dSVille Syrjälä struct intel_encoder *encoder,
3229379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
3230379bc100SJani Nikula const struct drm_connector_state *conn_state)
3231379bc100SJani Nikula {
3232379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3233b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
3234998cc864SUma Shankar struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3235379bc100SJani Nikula enum port port = encoder->port;
3236379bc100SJani Nikula
3237005e9537SMatt Roper if (port == PORT_A && DISPLAY_VER(dev_priv) < 9)
3238a621860aSVille Syrjälä intel_dp_stop_link_train(intel_dp, crtc_state);
3239379bc100SJani Nikula
32406306d8dbSHans de Goede drm_connector_update_privacy_screen(conn_state);
3241379bc100SJani Nikula intel_edp_backlight_on(crtc_state, conn_state);
3242998cc864SUma Shankar
32437ffa2f27SJani Nikula if (!dig_port->lspcon.active || intel_dp_has_hdmi_sink(&dig_port->dp))
32441bf3657cSGwan-gyeong Mun intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3245998cc864SUma Shankar
3246d82a855aSVille Syrjälä trans_port_sync_stop_link_train(state, encoder, crtc_state);
3247379bc100SJani Nikula }
3248379bc100SJani Nikula
3249a379bf3dSVille Syrjälä /* FIXME bad home for this function */
hsw_chicken_trans_reg(struct drm_i915_private * i915,enum transcoder cpu_transcoder)3250a379bf3dSVille Syrjälä i915_reg_t hsw_chicken_trans_reg(struct drm_i915_private *i915,
3251a379bf3dSVille Syrjälä enum transcoder cpu_transcoder)
3252a379bf3dSVille Syrjälä {
3253a379bf3dSVille Syrjälä return DISPLAY_VER(i915) >= 14 ?
3254a379bf3dSVille Syrjälä MTL_CHICKEN_TRANS(cpu_transcoder) :
3255a379bf3dSVille Syrjälä CHICKEN_TRANS(cpu_transcoder);
3256a379bf3dSVille Syrjälä }
3257a379bf3dSVille Syrjälä
3258379bc100SJani Nikula static i915_reg_t
gen9_chicken_trans_reg_by_port(struct drm_i915_private * dev_priv,enum port port)3259379bc100SJani Nikula gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv,
3260379bc100SJani Nikula enum port port)
3261379bc100SJani Nikula {
326212c4d4c1SVille Syrjälä static const enum transcoder trans[] = {
326312c4d4c1SVille Syrjälä [PORT_A] = TRANSCODER_EDP,
326412c4d4c1SVille Syrjälä [PORT_B] = TRANSCODER_A,
326512c4d4c1SVille Syrjälä [PORT_C] = TRANSCODER_B,
326612c4d4c1SVille Syrjälä [PORT_D] = TRANSCODER_C,
326712c4d4c1SVille Syrjälä [PORT_E] = TRANSCODER_A,
3268379bc100SJani Nikula };
3269379bc100SJani Nikula
3270005e9537SMatt Roper drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9);
3271379bc100SJani Nikula
32721de143ccSPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E))
3273379bc100SJani Nikula port = PORT_A;
3274379bc100SJani Nikula
327512c4d4c1SVille Syrjälä return CHICKEN_TRANS(trans[port]);
3276379bc100SJani Nikula }
3277379bc100SJani Nikula
intel_enable_ddi_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3278ede9771dSVille Syrjälä static void intel_enable_ddi_hdmi(struct intel_atomic_state *state,
3279ede9771dSVille Syrjälä struct intel_encoder *encoder,
3280379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
3281379bc100SJani Nikula const struct drm_connector_state *conn_state)
3282379bc100SJani Nikula {
3283379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3284b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3285379bc100SJani Nikula struct drm_connector *connector = conn_state->connector;
3286379bc100SJani Nikula enum port port = encoder->port;
3287e99ba962SImre Deak u32 buf_ctl;
3288379bc100SJani Nikula
3289379bc100SJani Nikula if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3290379bc100SJani Nikula crtc_state->hdmi_high_tmds_clock_ratio,
3291379bc100SJani Nikula crtc_state->hdmi_scrambling))
329247bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm,
329347bdb1caSJani Nikula "[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n",
3294379bc100SJani Nikula connector->base.id, connector->name);
3295379bc100SJani Nikula
32965bafd85dSVille Syrjälä if (has_buf_trans_select(dev_priv))
3297e722ab8bSVille Syrjälä hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state);
3298c9b69041SVille Syrjälä
3299b66a8abaSAnkit Nautiyal /* e. Enable D2D Link for C10/C20 Phy */
3300b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14)
3301b66a8abaSAnkit Nautiyal mtl_ddi_enable_d2d(encoder);
3302b66a8abaSAnkit Nautiyal
3303e722ab8bSVille Syrjälä encoder->set_signal_levels(encoder, crtc_state);
3304c9b69041SVille Syrjälä
3305379bc100SJani Nikula /* Display WA #1143: skl,kbl,cfl */
330693e7e61eSLucas De Marchi if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) {
3307379bc100SJani Nikula /*
3308379bc100SJani Nikula * For some reason these chicken bits have been
3309379bc100SJani Nikula * stuffed into a transcoder register, event though
3310379bc100SJani Nikula * the bits affect a specific DDI port rather than
3311379bc100SJani Nikula * a specific transcoder.
3312379bc100SJani Nikula */
3313379bc100SJani Nikula i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port);
3314379bc100SJani Nikula u32 val;
3315379bc100SJani Nikula
3316f7960e7fSJani Nikula val = intel_de_read(dev_priv, reg);
3317379bc100SJani Nikula
3318379bc100SJani Nikula if (port == PORT_E)
3319379bc100SJani Nikula val |= DDIE_TRAINING_OVERRIDE_ENABLE |
3320379bc100SJani Nikula DDIE_TRAINING_OVERRIDE_VALUE;
3321379bc100SJani Nikula else
3322379bc100SJani Nikula val |= DDI_TRAINING_OVERRIDE_ENABLE |
3323379bc100SJani Nikula DDI_TRAINING_OVERRIDE_VALUE;
3324379bc100SJani Nikula
3325f7960e7fSJani Nikula intel_de_write(dev_priv, reg, val);
3326f7960e7fSJani Nikula intel_de_posting_read(dev_priv, reg);
3327379bc100SJani Nikula
3328379bc100SJani Nikula udelay(1);
3329379bc100SJani Nikula
3330379bc100SJani Nikula if (port == PORT_E)
3331379bc100SJani Nikula val &= ~(DDIE_TRAINING_OVERRIDE_ENABLE |
3332379bc100SJani Nikula DDIE_TRAINING_OVERRIDE_VALUE);
3333379bc100SJani Nikula else
3334379bc100SJani Nikula val &= ~(DDI_TRAINING_OVERRIDE_ENABLE |
3335379bc100SJani Nikula DDI_TRAINING_OVERRIDE_VALUE);
3336379bc100SJani Nikula
3337f7960e7fSJani Nikula intel_de_write(dev_priv, reg, val);
3338379bc100SJani Nikula }
3339379bc100SJani Nikula
33401e0cb7beSVille Syrjälä intel_ddi_power_up_lanes(encoder, crtc_state);
33411e0cb7beSVille Syrjälä
3342379bc100SJani Nikula /* In HDMI/DVI mode, the port width, and swing/emphasis values
3343379bc100SJani Nikula * are ignored so nothing special needs to be done besides
3344379bc100SJani Nikula * enabling the port.
3345414002f1SImre Deak *
3346414002f1SImre Deak * On ADL_P the PHY link rate and lane count must be programmed but
3347414002f1SImre Deak * these are both 0 for HDMI.
3348b66a8abaSAnkit Nautiyal *
3349b66a8abaSAnkit Nautiyal * But MTL onwards HDMI2.1 is supported and in TMDS mode this
3350b66a8abaSAnkit Nautiyal * is filled with lane count, already set in the crtc_state.
3351b66a8abaSAnkit Nautiyal * The same is required to be filled in PORT_BUF_CTL for C10/20 Phy.
3352379bc100SJani Nikula */
3353e99ba962SImre Deak buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE;
3354b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14) {
3355b66a8abaSAnkit Nautiyal u8 lane_count = mtl_get_port_width(crtc_state->lane_count);
3356b66a8abaSAnkit Nautiyal u32 port_buf = 0;
3357b66a8abaSAnkit Nautiyal
3358b66a8abaSAnkit Nautiyal port_buf |= XELPDP_PORT_WIDTH(lane_count);
3359b66a8abaSAnkit Nautiyal
3360b66a8abaSAnkit Nautiyal if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL)
3361b66a8abaSAnkit Nautiyal port_buf |= XELPDP_PORT_REVERSAL;
3362b66a8abaSAnkit Nautiyal
3363fe4c6ff5SLucas De Marchi intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(dev_priv, port),
3364b66a8abaSAnkit Nautiyal XELPDP_PORT_WIDTH_MASK | XELPDP_PORT_REVERSAL, port_buf);
3365b66a8abaSAnkit Nautiyal
3366b66a8abaSAnkit Nautiyal buf_ctl |= DDI_PORT_WIDTH(lane_count);
3367d5c7854bSLucas De Marchi
3368d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20)
3369d5c7854bSLucas De Marchi buf_ctl |= XE2LPD_DDI_BUF_D2D_LINK_ENABLE;
33707fcf7558SJani Nikula } else if (IS_ALDERLAKE_P(dev_priv) && intel_encoder_is_tc(encoder)) {
3371e99ba962SImre Deak drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port));
3372e99ba962SImre Deak buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
3373e99ba962SImre Deak }
3374b66a8abaSAnkit Nautiyal
3375e99ba962SImre Deak intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl);
3376379bc100SJani Nikula
3377684a37a6SJani Nikula intel_wait_ddi_buf_active(encoder);
3378379bc100SJani Nikula }
3379379bc100SJani Nikula
intel_enable_ddi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3380ede9771dSVille Syrjälä static void intel_enable_ddi(struct intel_atomic_state *state,
3381ede9771dSVille Syrjälä struct intel_encoder *encoder,
3382379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
3383379bc100SJani Nikula const struct drm_connector_state *conn_state)
3384379bc100SJani Nikula {
33853607b308SStanislav Lisovskiy struct drm_i915_private *i915 = to_i915(encoder->base.dev);
33863607b308SStanislav Lisovskiy struct intel_crtc *pipe_crtc;
338721fd23acSJani Nikula
3388eed22a46SVille Syrjälä intel_ddi_enable_transcoder_func(encoder, crtc_state);
33897c2fedd7SVille Syrjälä
33908853750dSVinod Govindapillai /* Enable/Disable DP2.0 SDP split config before transcoder */
33912f092c0cSVinod Govindapillai intel_audio_sdp_split_update(crtc_state);
33928853750dSVinod Govindapillai
33938c66081bSVille Syrjälä intel_enable_transcoder(crtc_state);
339421fd23acSJani Nikula
33956e916b35SImre Deak intel_ddi_wait_for_fec_status(encoder, crtc_state, true);
33966e916b35SImre Deak
33973607b308SStanislav Lisovskiy for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc,
33983607b308SStanislav Lisovskiy intel_crtc_joined_pipe_mask(crtc_state)) {
33993607b308SStanislav Lisovskiy const struct intel_crtc_state *pipe_crtc_state =
34003607b308SStanislav Lisovskiy intel_atomic_get_new_crtc_state(state, pipe_crtc);
34013607b308SStanislav Lisovskiy
34023607b308SStanislav Lisovskiy intel_crtc_vblank_on(pipe_crtc_state);
34033607b308SStanislav Lisovskiy }
340421fd23acSJani Nikula
3405379bc100SJani Nikula if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI))
3406ede9771dSVille Syrjälä intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state);
3407379bc100SJani Nikula else
3408ede9771dSVille Syrjälä intel_enable_ddi_dp(state, encoder, crtc_state, conn_state);
3409379bc100SJani Nikula
34104c4279a8SSuraj Kandpal intel_hdcp_enable(state, encoder, crtc_state, conn_state);
34117966a93aSVille Syrjälä
3412379bc100SJani Nikula }
3413379bc100SJani Nikula
intel_disable_ddi_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3414ede9771dSVille Syrjälä static void intel_disable_ddi_dp(struct intel_atomic_state *state,
3415ede9771dSVille Syrjälä struct intel_encoder *encoder,
3416379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state,
3417379bc100SJani Nikula const struct drm_connector_state *old_conn_state)
3418379bc100SJani Nikula {
3419b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
34207c4631ffSImre Deak struct intel_connector *connector =
34217c4631ffSImre Deak to_intel_connector(old_conn_state->connector);
3422379bc100SJani Nikula
3423379bc100SJani Nikula intel_dp->link_trained = false;
3424379bc100SJani Nikula
3425f28c5950SVille Syrjälä intel_psr_disable(intel_dp, old_crtc_state);
3426379bc100SJani Nikula intel_edp_backlight_off(old_conn_state);
3427379bc100SJani Nikula /* Disable the decompression in DP Sink */
34287c4631ffSImre Deak intel_dp_sink_disable_decompression(state,
34297c4631ffSImre Deak connector, old_crtc_state);
34301639406aSManasi Navare /* Disable Ignore_MSA bit in DP Sink */
34311639406aSManasi Navare intel_dp_sink_set_msa_timing_par_ignore_state(intel_dp, old_crtc_state,
34321639406aSManasi Navare false);
3433379bc100SJani Nikula }
3434379bc100SJani Nikula
intel_disable_ddi_hdmi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3435ede9771dSVille Syrjälä static void intel_disable_ddi_hdmi(struct intel_atomic_state *state,
3436ede9771dSVille Syrjälä struct intel_encoder *encoder,
3437379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state,
3438379bc100SJani Nikula const struct drm_connector_state *old_conn_state)
3439379bc100SJani Nikula {
344047bdb1caSJani Nikula struct drm_i915_private *i915 = to_i915(encoder->base.dev);
3441379bc100SJani Nikula struct drm_connector *connector = old_conn_state->connector;
3442379bc100SJani Nikula
3443379bc100SJani Nikula if (!intel_hdmi_handle_sink_scrambling(encoder, connector,
3444379bc100SJani Nikula false, false))
344547bdb1caSJani Nikula drm_dbg_kms(&i915->drm,
344647bdb1caSJani Nikula "[CONNECTOR:%d:%s] Failed to reset sink scrambling/TMDS bit clock ratio\n",
3447379bc100SJani Nikula connector->base.id, connector->name);
3448379bc100SJani Nikula }
3449379bc100SJani Nikula
intel_disable_ddi(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * old_crtc_state,const struct drm_connector_state * old_conn_state)3450ede9771dSVille Syrjälä static void intel_disable_ddi(struct intel_atomic_state *state,
3451ede9771dSVille Syrjälä struct intel_encoder *encoder,
3452379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state,
3453379bc100SJani Nikula const struct drm_connector_state *old_conn_state)
3454379bc100SJani Nikula {
3455c598c335SImre Deak intel_tc_port_link_cancel_reset_work(enc_to_dig_port(encoder));
3456c598c335SImre Deak
3457379bc100SJani Nikula intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
3458379bc100SJani Nikula
3459379bc100SJani Nikula if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
3460ede9771dSVille Syrjälä intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
3461ede9771dSVille Syrjälä old_conn_state);
3462379bc100SJani Nikula else
3463ede9771dSVille Syrjälä intel_disable_ddi_dp(state, encoder, old_crtc_state,
3464ede9771dSVille Syrjälä old_conn_state);
3465379bc100SJani Nikula }
3466379bc100SJani Nikula
intel_ddi_update_pipe_dp(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3467ede9771dSVille Syrjälä static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state,
3468ede9771dSVille Syrjälä struct intel_encoder *encoder,
3469379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
3470379bc100SJani Nikula const struct drm_connector_state *conn_state)
3471379bc100SJani Nikula {
34720c06fa15SGwan-gyeong Mun intel_ddi_set_dp_msa(crtc_state, conn_state);
3473379bc100SJani Nikula
347476d45d06SGwan-gyeong Mun intel_dp_set_infoframes(encoder, true, crtc_state, conn_state);
3475379bc100SJani Nikula
3476c0a52f8bSJani Nikula intel_backlight_update(state, encoder, crtc_state, conn_state);
34776306d8dbSHans de Goede drm_connector_update_privacy_screen(conn_state);
3478379bc100SJani Nikula }
3479379bc100SJani Nikula
intel_ddi_update_pipe(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3480f1c7a36bSSean Paul void intel_ddi_update_pipe(struct intel_atomic_state *state,
3481ede9771dSVille Syrjälä struct intel_encoder *encoder,
3482379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
3483379bc100SJani Nikula const struct drm_connector_state *conn_state)
3484379bc100SJani Nikula {
3485d456512cSRamalingam C
3486f1c7a36bSSean Paul if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
3487f1c7a36bSSean Paul !intel_encoder_is_mst(encoder))
3488ede9771dSVille Syrjälä intel_ddi_update_pipe_dp(state, encoder, crtc_state,
3489ede9771dSVille Syrjälä conn_state);
3490379bc100SJani Nikula
3491ede9771dSVille Syrjälä intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state);
3492379bc100SJani Nikula }
3493379bc100SJani Nikula
intel_ddi_update_active_dpll(struct intel_atomic_state * state,struct intel_encoder * encoder,struct intel_crtc * crtc)349427ac123bSImre Deak void intel_ddi_update_active_dpll(struct intel_atomic_state *state,
349527ac123bSImre Deak struct intel_encoder *encoder,
349627ac123bSImre Deak struct intel_crtc *crtc)
349727ac123bSImre Deak {
349827ac123bSImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev);
34992b8ad19dSVille Syrjälä const struct intel_crtc_state *crtc_state =
350027ac123bSImre Deak intel_atomic_get_new_crtc_state(state, crtc);
35012b8ad19dSVille Syrjälä struct intel_crtc *pipe_crtc;
350227ac123bSImre Deak
350362618c7fSMika Kahola /* FIXME: Add MTL pll_mgr */
35047fcf7558SJani Nikula if (DISPLAY_VER(i915) >= 14 || !intel_encoder_is_tc(encoder))
350527ac123bSImre Deak return;
350627ac123bSImre Deak
35072b8ad19dSVille Syrjälä for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc,
35082b8ad19dSVille Syrjälä intel_crtc_joined_pipe_mask(crtc_state))
35092b8ad19dSVille Syrjälä intel_update_active_dpll(state, pipe_crtc, encoder);
351027ac123bSImre Deak }
351127ac123bSImre Deak
3512379bc100SJani Nikula static void
intel_ddi_pre_pll_enable(struct intel_atomic_state * state,struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)3513ede9771dSVille Syrjälä intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
3514ede9771dSVille Syrjälä struct intel_encoder *encoder,
3515379bc100SJani Nikula const struct intel_crtc_state *crtc_state,
3516379bc100SJani Nikula const struct drm_connector_state *conn_state)
3517379bc100SJani Nikula {
3518379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3519b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
35207fcf7558SJani Nikula bool is_tc_port = intel_encoder_is_tc(encoder);
3521379bc100SJani Nikula
35220f752b21SImre Deak if (is_tc_port) {
3523da8c3cdbSStanislav Lisovskiy struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
35240f752b21SImre Deak
352524a7bfe0SImre Deak intel_tc_port_get_link(dig_port, crtc_state->lane_count);
3526da8c3cdbSStanislav Lisovskiy intel_ddi_update_active_dpll(state, encoder, crtc);
35270f752b21SImre Deak }
35280f752b21SImre Deak
3529637c7aa2SImre Deak main_link_aux_power_domain_get(dig_port, crtc_state);
3530379bc100SJani Nikula
353111a89708SImre Deak if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port))
35329d44dcb9SLucas De Marchi /*
35339d44dcb9SLucas De Marchi * Program the lane count for static/dynamic connections on
35349d44dcb9SLucas De Marchi * Type-C ports. Skip this step for TBT.
35359d44dcb9SLucas De Marchi */
35369d44dcb9SLucas De Marchi intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count);
35372446e1d6SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3538ba07c3edSVille Syrjälä bxt_dpio_phy_set_lane_optim_mask(encoder,
3539379bc100SJani Nikula crtc_state->lane_lat_optim_mask);
3540379bc100SJani Nikula }
3541379bc100SJani Nikula
adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder * encoder)354255223c3bSImre Deak static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
354355223c3bSImre Deak {
354455223c3bSImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev);
35457fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder);
354655223c3bSImre Deak int ln;
354755223c3bSImre Deak
354889cb0ba4SImre Deak for (ln = 0; ln < 2; ln++)
3549b8ed5533SImre Deak intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0);
355055223c3bSImre Deak }
355155223c3bSImre Deak
mtl_ddi_prepare_link_retrain(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state)355223ef6194SJosé Roberto de Souza static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
355323ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state)
355423ef6194SJosé Roberto de Souza {
355523ef6194SJosé Roberto de Souza struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
355623ef6194SJosé Roberto de Souza struct intel_encoder *encoder = &dig_port->base;
355723ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
355823ef6194SJosé Roberto de Souza enum port port = encoder->port;
355923ef6194SJosé Roberto de Souza u32 dp_tp_ctl;
356023ef6194SJosé Roberto de Souza
356123ef6194SJosé Roberto de Souza /*
356223ef6194SJosé Roberto de Souza * TODO: To train with only a different voltage swing entry is not
356323ef6194SJosé Roberto de Souza * necessary disable and enable port
356423ef6194SJosé Roberto de Souza */
356523ef6194SJosé Roberto de Souza dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
356623ef6194SJosé Roberto de Souza if (dp_tp_ctl & DP_TP_CTL_ENABLE)
356723ef6194SJosé Roberto de Souza mtl_disable_ddi_buf(encoder, crtc_state);
356823ef6194SJosé Roberto de Souza
356923ef6194SJosé Roberto de Souza /* 6.d Configure and enable DP_TP_CTL with link training pattern 1 selected */
357023ef6194SJosé Roberto de Souza dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
357123ef6194SJosé Roberto de Souza if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
357223ef6194SJosé Roberto de Souza dp_tp_ctl |= DP_TP_CTL_MODE_MST;
357323ef6194SJosé Roberto de Souza } else {
357423ef6194SJosé Roberto de Souza dp_tp_ctl |= DP_TP_CTL_MODE_SST;
35753072a24cSVille Syrjälä if (crtc_state->enhanced_framing)
357623ef6194SJosé Roberto de Souza dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
357723ef6194SJosé Roberto de Souza }
357823ef6194SJosé Roberto de Souza intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
357923ef6194SJosé Roberto de Souza intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
358023ef6194SJosé Roberto de Souza
358123ef6194SJosé Roberto de Souza /* 6.f Enable D2D Link */
358223ef6194SJosé Roberto de Souza mtl_ddi_enable_d2d(encoder);
358323ef6194SJosé Roberto de Souza
358423ef6194SJosé Roberto de Souza /* 6.g Configure voltage swing and related IO settings */
358523ef6194SJosé Roberto de Souza encoder->set_signal_levels(encoder, crtc_state);
358623ef6194SJosé Roberto de Souza
358723ef6194SJosé Roberto de Souza /* 6.h Configure PORT_BUF_CTL1 */
358823ef6194SJosé Roberto de Souza mtl_port_buf_ctl_program(encoder, crtc_state);
358923ef6194SJosé Roberto de Souza
359023ef6194SJosé Roberto de Souza /* 6.i Configure and enable DDI_CTL_DE to start sending valid data to port slice */
359123ef6194SJosé Roberto de Souza intel_dp->DP |= DDI_BUF_CTL_ENABLE;
3592d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20)
3593d5c7854bSLucas De Marchi intel_dp->DP |= XE2LPD_DDI_BUF_D2D_LINK_ENABLE;
3594d5c7854bSLucas De Marchi
359523ef6194SJosé Roberto de Souza intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
359623ef6194SJosé Roberto de Souza intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
359723ef6194SJosé Roberto de Souza
359823ef6194SJosé Roberto de Souza /* 6.j Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 us */
3599684a37a6SJani Nikula intel_wait_ddi_buf_active(encoder);
360023ef6194SJosé Roberto de Souza }
360123ef6194SJosé Roberto de Souza
intel_ddi_prepare_link_retrain(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state)3602a621860aSVille Syrjälä static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
3603a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state)
3604379bc100SJani Nikula {
360555223c3bSImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
360655223c3bSImre Deak struct intel_encoder *encoder = &dig_port->base;
3607ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3608ef79fafeSVille Syrjälä enum port port = encoder->port;
360935ac28a8SLucas De Marchi u32 dp_tp_ctl, ddi_buf_ctl;
3610379bc100SJani Nikula bool wait = false;
3611379bc100SJani Nikula
3612ef79fafeSVille Syrjälä dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
361335ac28a8SLucas De Marchi
361435ac28a8SLucas De Marchi if (dp_tp_ctl & DP_TP_CTL_ENABLE) {
3615f7960e7fSJani Nikula ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port));
361635ac28a8SLucas De Marchi if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) {
3617f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_CTL(port),
361835ac28a8SLucas De Marchi ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE);
3619379bc100SJani Nikula wait = true;
3620379bc100SJani Nikula }
3621379bc100SJani Nikula
36228c042949SVille Syrjälä dp_tp_ctl &= ~DP_TP_CTL_ENABLE;
3623ef79fafeSVille Syrjälä intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3624ef79fafeSVille Syrjälä intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3625379bc100SJani Nikula
3626379bc100SJani Nikula if (wait)
3627379bc100SJani Nikula intel_wait_ddi_buf_idle(dev_priv, port);
3628379bc100SJani Nikula }
3629379bc100SJani Nikula
3630963501bdSImre Deak dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1;
3631a621860aSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
363235ac28a8SLucas De Marchi dp_tp_ctl |= DP_TP_CTL_MODE_MST;
3633a621860aSVille Syrjälä } else {
363435ac28a8SLucas De Marchi dp_tp_ctl |= DP_TP_CTL_MODE_SST;
36353072a24cSVille Syrjälä if (crtc_state->enhanced_framing)
363635ac28a8SLucas De Marchi dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE;
3637379bc100SJani Nikula }
3638ef79fafeSVille Syrjälä intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl);
3639ef79fafeSVille Syrjälä intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3640379bc100SJani Nikula
364155223c3bSImre Deak if (IS_ALDERLAKE_P(dev_priv) &&
364255223c3bSImre Deak (intel_tc_port_in_dp_alt_mode(dig_port) || intel_tc_port_in_legacy_mode(dig_port)))
364355223c3bSImre Deak adlp_tbt_to_dp_alt_switch_wa(encoder);
364455223c3bSImre Deak
3645379bc100SJani Nikula intel_dp->DP |= DDI_BUF_CTL_ENABLE;
3646f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
3647f7960e7fSJani Nikula intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
3648379bc100SJani Nikula
3649684a37a6SJani Nikula intel_wait_ddi_buf_active(encoder);
3650379bc100SJani Nikula }
3651379bc100SJani Nikula
intel_ddi_set_link_train(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state,u8 dp_train_pat)3652eee3f911SVille Syrjälä static void intel_ddi_set_link_train(struct intel_dp *intel_dp,
3653a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state,
3654eee3f911SVille Syrjälä u8 dp_train_pat)
3655eee3f911SVille Syrjälä {
3656ef79fafeSVille Syrjälä struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
3657ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3658eee3f911SVille Syrjälä u32 temp;
3659eee3f911SVille Syrjälä
3660ef79fafeSVille Syrjälä temp = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state));
3661eee3f911SVille Syrjälä
3662eee3f911SVille Syrjälä temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
36636777a855SImre Deak switch (intel_dp_training_pattern_symbol(dp_train_pat)) {
3664eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_DISABLE:
3665eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
3666eee3f911SVille Syrjälä break;
3667eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_1:
3668eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
3669eee3f911SVille Syrjälä break;
3670eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_2:
3671eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
3672eee3f911SVille Syrjälä break;
3673eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_3:
3674eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
3675eee3f911SVille Syrjälä break;
3676eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_4:
3677eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT4;
3678eee3f911SVille Syrjälä break;
3679eee3f911SVille Syrjälä }
3680eee3f911SVille Syrjälä
3681ef79fafeSVille Syrjälä intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), temp);
3682eee3f911SVille Syrjälä }
3683eee3f911SVille Syrjälä
intel_ddi_set_idle_link_train(struct intel_dp * intel_dp,const struct intel_crtc_state * crtc_state)3684a621860aSVille Syrjälä static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp,
3685a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state)
36868fdda385SVille Syrjälä {
36878fdda385SVille Syrjälä struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
36888fdda385SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
36898fdda385SVille Syrjälä enum port port = encoder->port;
36908fdda385SVille Syrjälä
36918910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state),
36928910d8b7SAndrzej Hajda DP_TP_CTL_LINK_TRAIN_MASK, DP_TP_CTL_LINK_TRAIN_IDLE);
36938fdda385SVille Syrjälä
36948fdda385SVille Syrjälä /*
36958fdda385SVille Syrjälä * Until TGL on PORT_A we can have only eDP in SST mode. There the only
36968fdda385SVille Syrjälä * reason we need to set idle transmission mode is to work around a HW
36978fdda385SVille Syrjälä * issue where we enable the pipe while not in idle link-training mode.
36988fdda385SVille Syrjälä * In this case there is requirement to wait for a minimum number of
36998fdda385SVille Syrjälä * idle patterns to be sent.
37008fdda385SVille Syrjälä */
3701005e9537SMatt Roper if (port == PORT_A && DISPLAY_VER(dev_priv) < 12)
37028fdda385SVille Syrjälä return;
37038fdda385SVille Syrjälä
3704ef79fafeSVille Syrjälä if (intel_de_wait_for_set(dev_priv,
3705ef79fafeSVille Syrjälä dp_tp_status_reg(encoder, crtc_state),
37062c215a93SShekhar Chauhan DP_TP_STATUS_IDLE_DONE, 2))
37078fdda385SVille Syrjälä drm_err(&dev_priv->drm,
37088fdda385SVille Syrjälä "Timed out waiting for DP idle patterns\n");
37098fdda385SVille Syrjälä }
37108fdda385SVille Syrjälä
intel_ddi_is_audio_enabled(struct drm_i915_private * dev_priv,enum transcoder cpu_transcoder)3711379bc100SJani Nikula static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
3712379bc100SJani Nikula enum transcoder cpu_transcoder)
3713379bc100SJani Nikula {
3714379bc100SJani Nikula if (cpu_transcoder == TRANSCODER_EDP)
3715379bc100SJani Nikula return false;
3716379bc100SJani Nikula
3717615a7724SAnshuman Gupta if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO_MMIO))
3718379bc100SJani Nikula return false;
3719379bc100SJani Nikula
3720f7960e7fSJani Nikula return intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD) &
3721379bc100SJani Nikula AUDIO_OUTPUT_ENABLE(cpu_transcoder);
3722379bc100SJani Nikula }
3723379bc100SJani Nikula
tgl_ddi_min_voltage_level(const struct intel_crtc_state * crtc_state)372446bdb77dSVille Syrjälä static int tgl_ddi_min_voltage_level(const struct intel_crtc_state *crtc_state)
372546bdb77dSVille Syrjälä {
372646bdb77dSVille Syrjälä if (crtc_state->port_clock > 594000)
372746bdb77dSVille Syrjälä return 2;
372846bdb77dSVille Syrjälä else
372946bdb77dSVille Syrjälä return 0;
373046bdb77dSVille Syrjälä }
373146bdb77dSVille Syrjälä
jsl_ddi_min_voltage_level(const struct intel_crtc_state * crtc_state)373246bdb77dSVille Syrjälä static int jsl_ddi_min_voltage_level(const struct intel_crtc_state *crtc_state)
373346bdb77dSVille Syrjälä {
373446bdb77dSVille Syrjälä if (crtc_state->port_clock > 594000)
373546bdb77dSVille Syrjälä return 3;
373646bdb77dSVille Syrjälä else
373746bdb77dSVille Syrjälä return 0;
373846bdb77dSVille Syrjälä }
373946bdb77dSVille Syrjälä
icl_ddi_min_voltage_level(const struct intel_crtc_state * crtc_state)374046bdb77dSVille Syrjälä static int icl_ddi_min_voltage_level(const struct intel_crtc_state *crtc_state)
374146bdb77dSVille Syrjälä {
374246bdb77dSVille Syrjälä if (crtc_state->port_clock > 594000)
374346bdb77dSVille Syrjälä return 1;
374446bdb77dSVille Syrjälä else
374546bdb77dSVille Syrjälä return 0;
374646bdb77dSVille Syrjälä }
374746bdb77dSVille Syrjälä
intel_ddi_compute_min_voltage_level(struct intel_crtc_state * crtc_state)37488cd53c6bSVille Syrjälä void intel_ddi_compute_min_voltage_level(struct intel_crtc_state *crtc_state)
3749379bc100SJani Nikula {
37508cd53c6bSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
37518cd53c6bSVille Syrjälä
37520656afabSVille Syrjälä if (DISPLAY_VER(dev_priv) >= 14)
37530656afabSVille Syrjälä crtc_state->min_voltage_level = icl_ddi_min_voltage_level(crtc_state);
37540656afabSVille Syrjälä else if (DISPLAY_VER(dev_priv) >= 12)
375546bdb77dSVille Syrjälä crtc_state->min_voltage_level = tgl_ddi_min_voltage_level(crtc_state);
375646bdb77dSVille Syrjälä else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv))
375746bdb77dSVille Syrjälä crtc_state->min_voltage_level = jsl_ddi_min_voltage_level(crtc_state);
375846bdb77dSVille Syrjälä else if (DISPLAY_VER(dev_priv) >= 11)
375946bdb77dSVille Syrjälä crtc_state->min_voltage_level = icl_ddi_min_voltage_level(crtc_state);
3760379bc100SJani Nikula }
3761379bc100SJani Nikula
bdw_transcoder_master_readout(struct drm_i915_private * dev_priv,enum transcoder cpu_transcoder)3762dc5b8ed5SVille Syrjälä static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *dev_priv,
376302d8ea47SVille Syrjälä enum transcoder cpu_transcoder)
376402d8ea47SVille Syrjälä {
3765dc5b8ed5SVille Syrjälä u32 master_select;
376602d8ea47SVille Syrjälä
3767005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) {
376876f1b2b1SJani Nikula u32 ctl2 = intel_de_read(dev_priv,
376976f1b2b1SJani Nikula TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder));
377002d8ea47SVille Syrjälä
377102d8ea47SVille Syrjälä if ((ctl2 & PORT_SYNC_MODE_ENABLE) == 0)
377202d8ea47SVille Syrjälä return INVALID_TRANSCODER;
377302d8ea47SVille Syrjälä
3774d4d7d9caSVille Syrjälä master_select = REG_FIELD_GET(PORT_SYNC_MODE_MASTER_SELECT_MASK, ctl2);
3775dc5b8ed5SVille Syrjälä } else {
3776b092d6adSJani Nikula u32 ctl = intel_de_read(dev_priv,
3777b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
3778dc5b8ed5SVille Syrjälä
3779dc5b8ed5SVille Syrjälä if ((ctl & TRANS_DDI_PORT_SYNC_ENABLE) == 0)
3780dc5b8ed5SVille Syrjälä return INVALID_TRANSCODER;
3781dc5b8ed5SVille Syrjälä
3782dc5b8ed5SVille Syrjälä master_select = REG_FIELD_GET(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, ctl);
3783dc5b8ed5SVille Syrjälä }
378402d8ea47SVille Syrjälä
378502d8ea47SVille Syrjälä if (master_select == 0)
378602d8ea47SVille Syrjälä return TRANSCODER_EDP;
378702d8ea47SVille Syrjälä else
378802d8ea47SVille Syrjälä return master_select - 1;
378902d8ea47SVille Syrjälä }
379002d8ea47SVille Syrjälä
bdw_get_trans_port_sync_config(struct intel_crtc_state * crtc_state)3791dc5b8ed5SVille Syrjälä static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state)
379202d8ea47SVille Syrjälä {
379302d8ea47SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
379402d8ea47SVille Syrjälä u32 transcoders = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
379502d8ea47SVille Syrjälä BIT(TRANSCODER_C) | BIT(TRANSCODER_D);
379602d8ea47SVille Syrjälä enum transcoder cpu_transcoder;
379702d8ea47SVille Syrjälä
379802d8ea47SVille Syrjälä crtc_state->master_transcoder =
3799dc5b8ed5SVille Syrjälä bdw_transcoder_master_readout(dev_priv, crtc_state->cpu_transcoder);
380002d8ea47SVille Syrjälä
380102d8ea47SVille Syrjälä for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) {
380202d8ea47SVille Syrjälä enum intel_display_power_domain power_domain;
380302d8ea47SVille Syrjälä intel_wakeref_t trans_wakeref;
380402d8ea47SVille Syrjälä
380502d8ea47SVille Syrjälä power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
380602d8ea47SVille Syrjälä trans_wakeref = intel_display_power_get_if_enabled(dev_priv,
380702d8ea47SVille Syrjälä power_domain);
380802d8ea47SVille Syrjälä
380902d8ea47SVille Syrjälä if (!trans_wakeref)
381002d8ea47SVille Syrjälä continue;
381102d8ea47SVille Syrjälä
3812dc5b8ed5SVille Syrjälä if (bdw_transcoder_master_readout(dev_priv, cpu_transcoder) ==
381302d8ea47SVille Syrjälä crtc_state->cpu_transcoder)
381402d8ea47SVille Syrjälä crtc_state->sync_mode_slaves_mask |= BIT(cpu_transcoder);
381502d8ea47SVille Syrjälä
381602d8ea47SVille Syrjälä intel_display_power_put(dev_priv, power_domain, trans_wakeref);
381702d8ea47SVille Syrjälä }
381802d8ea47SVille Syrjälä
381902d8ea47SVille Syrjälä drm_WARN_ON(&dev_priv->drm,
382002d8ea47SVille Syrjälä crtc_state->master_transcoder != INVALID_TRANSCODER &&
382102d8ea47SVille Syrjälä crtc_state->sync_mode_slaves_mask);
382202d8ea47SVille Syrjälä }
382302d8ea47SVille Syrjälä
intel_ddi_read_func_ctl(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config)38240385eceaSManasi Navare static void intel_ddi_read_func_ctl(struct intel_encoder *encoder,
3825379bc100SJani Nikula struct intel_crtc_state *pipe_config)
3826379bc100SJani Nikula {
3827379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3828f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
3829379bc100SJani Nikula enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
3830a44289b9SUma Shankar struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
3831379bc100SJani Nikula u32 temp, flags = 0;
3832379bc100SJani Nikula
3833b092d6adSJani Nikula temp = intel_de_read(dev_priv,
3834b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder));
3835379bc100SJani Nikula if (temp & TRANS_DDI_PHSYNC)
3836379bc100SJani Nikula flags |= DRM_MODE_FLAG_PHSYNC;
3837379bc100SJani Nikula else
3838379bc100SJani Nikula flags |= DRM_MODE_FLAG_NHSYNC;
3839379bc100SJani Nikula if (temp & TRANS_DDI_PVSYNC)
3840379bc100SJani Nikula flags |= DRM_MODE_FLAG_PVSYNC;
3841379bc100SJani Nikula else
3842379bc100SJani Nikula flags |= DRM_MODE_FLAG_NVSYNC;
3843379bc100SJani Nikula
38441326a92cSMaarten Lankhorst pipe_config->hw.adjusted_mode.flags |= flags;
3845379bc100SJani Nikula
3846379bc100SJani Nikula switch (temp & TRANS_DDI_BPC_MASK) {
3847379bc100SJani Nikula case TRANS_DDI_BPC_6:
3848379bc100SJani Nikula pipe_config->pipe_bpp = 18;
3849379bc100SJani Nikula break;
3850379bc100SJani Nikula case TRANS_DDI_BPC_8:
3851379bc100SJani Nikula pipe_config->pipe_bpp = 24;
3852379bc100SJani Nikula break;
3853379bc100SJani Nikula case TRANS_DDI_BPC_10:
3854379bc100SJani Nikula pipe_config->pipe_bpp = 30;
3855379bc100SJani Nikula break;
3856379bc100SJani Nikula case TRANS_DDI_BPC_12:
3857379bc100SJani Nikula pipe_config->pipe_bpp = 36;
3858379bc100SJani Nikula break;
3859379bc100SJani Nikula default:
3860379bc100SJani Nikula break;
3861379bc100SJani Nikula }
3862379bc100SJani Nikula
3863379bc100SJani Nikula switch (temp & TRANS_DDI_MODE_SELECT_MASK) {
3864379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_HDMI:
3865379bc100SJani Nikula pipe_config->has_hdmi_sink = true;
3866379bc100SJani Nikula
3867379bc100SJani Nikula pipe_config->infoframes.enable |=
3868379bc100SJani Nikula intel_hdmi_infoframes_enabled(encoder, pipe_config);
3869379bc100SJani Nikula
3870379bc100SJani Nikula if (pipe_config->infoframes.enable)
3871379bc100SJani Nikula pipe_config->has_infoframe = true;
3872379bc100SJani Nikula
3873379bc100SJani Nikula if (temp & TRANS_DDI_HDMI_SCRAMBLING)
3874379bc100SJani Nikula pipe_config->hdmi_scrambling = true;
3875379bc100SJani Nikula if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)
3876379bc100SJani Nikula pipe_config->hdmi_high_tmds_clock_ratio = true;
3877df561f66SGustavo A. R. Silva fallthrough;
3878379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DVI:
3879379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI);
3880b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14)
3881b66a8abaSAnkit Nautiyal pipe_config->lane_count =
3882b66a8abaSAnkit Nautiyal ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
3883b66a8abaSAnkit Nautiyal else
3884379bc100SJani Nikula pipe_config->lane_count = 4;
3885379bc100SJani Nikula break;
3886379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DP_SST:
3887379bc100SJani Nikula if (encoder->type == INTEL_OUTPUT_EDP)
3888379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP);
3889379bc100SJani Nikula else
3890379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_DP);
3891379bc100SJani Nikula pipe_config->lane_count =
3892379bc100SJani Nikula ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
38936149cb68SVille Syrjälä
38945cd06644SVille Syrjälä intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
38955cd06644SVille Syrjälä &pipe_config->dp_m_n);
38965cd06644SVille Syrjälä intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder,
38976149cb68SVille Syrjälä &pipe_config->dp_m2_n2);
38988aa940c8SMaarten Lankhorst
38993072a24cSVille Syrjälä pipe_config->enhanced_framing =
39003072a24cSVille Syrjälä intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
39013072a24cSVille Syrjälä DP_TP_CTL_ENHANCED_FRAME_ENABLE;
39023072a24cSVille Syrjälä
39033dfeb80bSVille Syrjälä if (DISPLAY_VER(dev_priv) >= 11)
39048aa940c8SMaarten Lankhorst pipe_config->fec_enable =
39053dfeb80bSVille Syrjälä intel_de_read(dev_priv,
39063dfeb80bSVille Syrjälä dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
39078aa940c8SMaarten Lankhorst
39087ffa2f27SJani Nikula if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp))
3909a44289b9SUma Shankar pipe_config->infoframes.enable |=
3910a44289b9SUma Shankar intel_lspcon_infoframes_enabled(encoder, pipe_config);
3911a44289b9SUma Shankar else
3912dee66f3eSGwan-gyeong Mun pipe_config->infoframes.enable |=
3913dee66f3eSGwan-gyeong Mun intel_hdmi_infoframes_enabled(encoder, pipe_config);
3914379bc100SJani Nikula break;
391565213594SJani Nikula case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B:
391665213594SJani Nikula if (!HAS_DP20(dev_priv)) {
391765213594SJani Nikula /* FDI */
391865213594SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG);
39193072a24cSVille Syrjälä pipe_config->enhanced_framing =
39203072a24cSVille Syrjälä intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) &
39213072a24cSVille Syrjälä DP_TP_CTL_ENHANCED_FRAME_ENABLE;
392265213594SJani Nikula break;
392365213594SJani Nikula }
392465213594SJani Nikula fallthrough; /* 128b/132b */
3925379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DP_MST:
3926379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST);
3927379bc100SJani Nikula pipe_config->lane_count =
3928379bc100SJani Nikula ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1;
39296671c367SJosé Roberto de Souza
3930005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12)
39316671c367SJosé Roberto de Souza pipe_config->mst_master_transcoder =
39326671c367SJosé Roberto de Souza REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp);
39336671c367SJosé Roberto de Souza
39345cd06644SVille Syrjälä intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder,
39355cd06644SVille Syrjälä &pipe_config->dp_m_n);
3936dee66f3eSGwan-gyeong Mun
3937cbbfe915SVille Syrjälä if (DISPLAY_VER(dev_priv) >= 11)
3938cbbfe915SVille Syrjälä pipe_config->fec_enable =
3939cbbfe915SVille Syrjälä intel_de_read(dev_priv,
3940cbbfe915SVille Syrjälä dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE;
3941cbbfe915SVille Syrjälä
3942dee66f3eSGwan-gyeong Mun pipe_config->infoframes.enable |=
3943dee66f3eSGwan-gyeong Mun intel_hdmi_infoframes_enabled(encoder, pipe_config);
3944379bc100SJani Nikula break;
3945379bc100SJani Nikula default:
3946379bc100SJani Nikula break;
3947379bc100SJani Nikula }
39480385eceaSManasi Navare }
39490385eceaSManasi Navare
intel_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config)3950351221ffSVille Syrjälä static void intel_ddi_get_config(struct intel_encoder *encoder,
39510385eceaSManasi Navare struct intel_crtc_state *pipe_config)
39520385eceaSManasi Navare {
39530385eceaSManasi Navare struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
39540385eceaSManasi Navare enum transcoder cpu_transcoder = pipe_config->cpu_transcoder;
39550385eceaSManasi Navare
39560385eceaSManasi Navare /* XXX: DSI transcoder paranoia */
39570385eceaSManasi Navare if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder)))
39580385eceaSManasi Navare return;
39590385eceaSManasi Navare
39600385eceaSManasi Navare intel_ddi_read_func_ctl(encoder, pipe_config);
3961379bc100SJani Nikula
39625b616a29SJani Nikula intel_ddi_mso_get_config(encoder, pipe_config);
39635b616a29SJani Nikula
3964379bc100SJani Nikula pipe_config->has_audio =
3965379bc100SJani Nikula intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder);
3966379bc100SJani Nikula
3967822e5ae7SVille Syrjälä if (encoder->type == INTEL_OUTPUT_EDP)
3968822e5ae7SVille Syrjälä intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp);
3969379bc100SJani Nikula
3970351221ffSVille Syrjälä ddi_dotclock_get(pipe_config);
3971379bc100SJani Nikula
39722446e1d6SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
3973379bc100SJani Nikula pipe_config->lane_lat_optim_mask =
3974ba07c3edSVille Syrjälä bxt_dpio_phy_get_lane_lat_optim_mask(encoder);
3975379bc100SJani Nikula
39768cd53c6bSVille Syrjälä intel_ddi_compute_min_voltage_level(pipe_config);
3977379bc100SJani Nikula
3978379bc100SJani Nikula intel_hdmi_read_gcp_infoframe(encoder, pipe_config);
3979379bc100SJani Nikula
3980379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config,
3981379bc100SJani Nikula HDMI_INFOFRAME_TYPE_AVI,
3982379bc100SJani Nikula &pipe_config->infoframes.avi);
3983379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config,
3984379bc100SJani Nikula HDMI_INFOFRAME_TYPE_SPD,
3985379bc100SJani Nikula &pipe_config->infoframes.spd);
3986379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config,
3987379bc100SJani Nikula HDMI_INFOFRAME_TYPE_VENDOR,
3988379bc100SJani Nikula &pipe_config->infoframes.hdmi);
3989379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config,
3990379bc100SJani Nikula HDMI_INFOFRAME_TYPE_DRM,
3991379bc100SJani Nikula &pipe_config->infoframes.drm);
399202d8ea47SVille Syrjälä
3993005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 8)
3994dc5b8ed5SVille Syrjälä bdw_get_trans_port_sync_config(pipe_config);
3995dee66f3eSGwan-gyeong Mun
399616448cf4SJouni Högander intel_psr_get_config(encoder, pipe_config);
399716448cf4SJouni Högander
3998dee66f3eSGwan-gyeong Mun intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA);
39992c3928e4SGwan-gyeong Mun intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC);
40008845021bSMitul Golani intel_read_dp_sdp(encoder, pipe_config, DP_SDP_ADAPTIVE_SYNC);
400178b772e1SJosé Roberto de Souza
400261a60df6SVille Syrjälä intel_audio_codec_get_config(encoder, pipe_config);
4003379bc100SJani Nikula }
4004379bc100SJani Nikula
intel_ddi_get_clock(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state,struct intel_shared_dpll * pll)4005351221ffSVille Syrjälä void intel_ddi_get_clock(struct intel_encoder *encoder,
4006351221ffSVille Syrjälä struct intel_crtc_state *crtc_state,
4007351221ffSVille Syrjälä struct intel_shared_dpll *pll)
4008351221ffSVille Syrjälä {
4009351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4010351221ffSVille Syrjälä enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
4011351221ffSVille Syrjälä struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
4012351221ffSVille Syrjälä bool pll_active;
4013351221ffSVille Syrjälä
4014086877a1SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
4015086877a1SVille Syrjälä return;
4016086877a1SVille Syrjälä
4017351221ffSVille Syrjälä port_dpll->pll = pll;
4018351221ffSVille Syrjälä pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
4019351221ffSVille Syrjälä drm_WARN_ON(&i915->drm, !pll_active);
4020351221ffSVille Syrjälä
4021351221ffSVille Syrjälä icl_set_active_port_dpll(crtc_state, port_dpll_id);
4022351221ffSVille Syrjälä
4023351221ffSVille Syrjälä crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
4024351221ffSVille Syrjälä &crtc_state->dpll_hw_state);
4025351221ffSVille Syrjälä }
4026351221ffSVille Syrjälä
mtl_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)402751390cc0SRadhakrishna Sripada static void mtl_ddi_get_config(struct intel_encoder *encoder,
402851390cc0SRadhakrishna Sripada struct intel_crtc_state *crtc_state)
402951390cc0SRadhakrishna Sripada {
40304bbb8932SVille Syrjälä intel_cx0pll_readout_hw_state(encoder, &crtc_state->dpll_hw_state.cx0pll);
403132a120f5SImre Deak
403232a120f5SImre Deak if (crtc_state->dpll_hw_state.cx0pll.tbt_mode)
403332a120f5SImre Deak crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder);
403432a120f5SImre Deak else
40354bbb8932SVille Syrjälä crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll);
4036929f527aSMika Kahola
403751390cc0SRadhakrishna Sripada intel_ddi_get_config(encoder, crtc_state);
403851390cc0SRadhakrishna Sripada }
403951390cc0SRadhakrishna Sripada
dg2_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4040865b73eaSMatt Roper static void dg2_ddi_get_config(struct intel_encoder *encoder,
4041865b73eaSMatt Roper struct intel_crtc_state *crtc_state)
4042865b73eaSMatt Roper {
40434bbb8932SVille Syrjälä intel_mpllb_readout_hw_state(encoder, &crtc_state->dpll_hw_state.mpllb);
40444bbb8932SVille Syrjälä crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->dpll_hw_state.mpllb);
4045865b73eaSMatt Roper
4046865b73eaSMatt Roper intel_ddi_get_config(encoder, crtc_state);
4047865b73eaSMatt Roper }
4048865b73eaSMatt Roper
adls_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4049351221ffSVille Syrjälä static void adls_ddi_get_config(struct intel_encoder *encoder,
4050351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4051351221ffSVille Syrjälä {
4052351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, adls_ddi_get_pll(encoder));
4053351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4054351221ffSVille Syrjälä }
4055351221ffSVille Syrjälä
rkl_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4056351221ffSVille Syrjälä static void rkl_ddi_get_config(struct intel_encoder *encoder,
4057351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4058351221ffSVille Syrjälä {
4059351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, rkl_ddi_get_pll(encoder));
4060351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4061351221ffSVille Syrjälä }
4062351221ffSVille Syrjälä
dg1_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4063351221ffSVille Syrjälä static void dg1_ddi_get_config(struct intel_encoder *encoder,
4064351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4065351221ffSVille Syrjälä {
4066351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, dg1_ddi_get_pll(encoder));
4067351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4068351221ffSVille Syrjälä }
4069351221ffSVille Syrjälä
icl_ddi_combo_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4070351221ffSVille Syrjälä static void icl_ddi_combo_get_config(struct intel_encoder *encoder,
4071351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4072351221ffSVille Syrjälä {
4073351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, icl_ddi_combo_get_pll(encoder));
4074351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4075351221ffSVille Syrjälä }
4076351221ffSVille Syrjälä
icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll * pll)40777c1da068SImre Deak static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll)
40787c1da068SImre Deak {
40797c1da068SImre Deak return pll->info->id == DPLL_ID_ICL_TBTPLL;
40807c1da068SImre Deak }
40817c1da068SImre Deak
40827c1da068SImre Deak static enum icl_port_dpll_id
icl_ddi_tc_port_pll_type(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)40837c1da068SImre Deak icl_ddi_tc_port_pll_type(struct intel_encoder *encoder,
40847c1da068SImre Deak const struct intel_crtc_state *crtc_state)
40857c1da068SImre Deak {
40867c1da068SImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev);
40877c1da068SImre Deak const struct intel_shared_dpll *pll = crtc_state->shared_dpll;
40887c1da068SImre Deak
40897c1da068SImre Deak if (drm_WARN_ON(&i915->drm, !pll))
40907c1da068SImre Deak return ICL_PORT_DPLL_DEFAULT;
40917c1da068SImre Deak
40927c1da068SImre Deak if (icl_ddi_tc_pll_is_tbt(pll))
40937c1da068SImre Deak return ICL_PORT_DPLL_DEFAULT;
40947c1da068SImre Deak else
40957c1da068SImre Deak return ICL_PORT_DPLL_MG_PHY;
40967c1da068SImre Deak }
40977c1da068SImre Deak
40987c1da068SImre Deak enum icl_port_dpll_id
intel_ddi_port_pll_type(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)40997c1da068SImre Deak intel_ddi_port_pll_type(struct intel_encoder *encoder,
41007c1da068SImre Deak const struct intel_crtc_state *crtc_state)
41017c1da068SImre Deak {
41027c1da068SImre Deak if (!encoder->port_pll_type)
41037c1da068SImre Deak return ICL_PORT_DPLL_DEFAULT;
41047c1da068SImre Deak
41057c1da068SImre Deak return encoder->port_pll_type(encoder, crtc_state);
41067c1da068SImre Deak }
41077c1da068SImre Deak
icl_ddi_tc_get_clock(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state,struct intel_shared_dpll * pll)4108086877a1SVille Syrjälä static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
4109086877a1SVille Syrjälä struct intel_crtc_state *crtc_state,
4110086877a1SVille Syrjälä struct intel_shared_dpll *pll)
4111351221ffSVille Syrjälä {
4112351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4113351221ffSVille Syrjälä enum icl_port_dpll_id port_dpll_id;
4114351221ffSVille Syrjälä struct icl_port_dpll *port_dpll;
4115351221ffSVille Syrjälä bool pll_active;
4116351221ffSVille Syrjälä
4117086877a1SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll))
4118086877a1SVille Syrjälä return;
4119351221ffSVille Syrjälä
41207c1da068SImre Deak if (icl_ddi_tc_pll_is_tbt(pll))
4121351221ffSVille Syrjälä port_dpll_id = ICL_PORT_DPLL_DEFAULT;
4122351221ffSVille Syrjälä else
4123351221ffSVille Syrjälä port_dpll_id = ICL_PORT_DPLL_MG_PHY;
4124351221ffSVille Syrjälä
4125351221ffSVille Syrjälä port_dpll = &crtc_state->icl_port_dplls[port_dpll_id];
4126351221ffSVille Syrjälä
4127351221ffSVille Syrjälä port_dpll->pll = pll;
4128351221ffSVille Syrjälä pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state);
4129351221ffSVille Syrjälä drm_WARN_ON(&i915->drm, !pll_active);
4130351221ffSVille Syrjälä
4131351221ffSVille Syrjälä icl_set_active_port_dpll(crtc_state, port_dpll_id);
4132351221ffSVille Syrjälä
41337c1da068SImre Deak if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll))
4134351221ffSVille Syrjälä crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port);
4135351221ffSVille Syrjälä else
4136351221ffSVille Syrjälä crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
4137351221ffSVille Syrjälä &crtc_state->dpll_hw_state);
4138086877a1SVille Syrjälä }
4139351221ffSVille Syrjälä
icl_ddi_tc_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4140086877a1SVille Syrjälä static void icl_ddi_tc_get_config(struct intel_encoder *encoder,
4141086877a1SVille Syrjälä struct intel_crtc_state *crtc_state)
4142086877a1SVille Syrjälä {
4143086877a1SVille Syrjälä icl_ddi_tc_get_clock(encoder, crtc_state, icl_ddi_tc_get_pll(encoder));
4144351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4145351221ffSVille Syrjälä }
4146351221ffSVille Syrjälä
bxt_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4147351221ffSVille Syrjälä static void bxt_ddi_get_config(struct intel_encoder *encoder,
4148351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4149351221ffSVille Syrjälä {
4150351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, bxt_ddi_get_pll(encoder));
4151351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4152351221ffSVille Syrjälä }
4153351221ffSVille Syrjälä
skl_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4154351221ffSVille Syrjälä static void skl_ddi_get_config(struct intel_encoder *encoder,
4155351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4156351221ffSVille Syrjälä {
4157351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, skl_ddi_get_pll(encoder));
4158351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4159351221ffSVille Syrjälä }
4160351221ffSVille Syrjälä
hsw_ddi_get_config(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4161351221ffSVille Syrjälä void hsw_ddi_get_config(struct intel_encoder *encoder,
4162351221ffSVille Syrjälä struct intel_crtc_state *crtc_state)
4163351221ffSVille Syrjälä {
4164351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, hsw_ddi_get_pll(encoder));
4165351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state);
4166351221ffSVille Syrjälä }
4167351221ffSVille Syrjälä
intel_ddi_sync_state(struct intel_encoder * encoder,const struct intel_crtc_state * crtc_state)4168f9e76a6eSImre Deak static void intel_ddi_sync_state(struct intel_encoder *encoder,
4169f9e76a6eSImre Deak const struct intel_crtc_state *crtc_state)
4170f9e76a6eSImre Deak {
41717fcf7558SJani Nikula if (intel_encoder_is_tc(encoder))
41722a4d292fSImre Deak intel_tc_port_sanitize_mode(enc_to_dig_port(encoder),
41732a4d292fSImre Deak crtc_state);
41747194dc99SImre Deak
4175a64d5fe4SImre Deak if ((crtc_state && intel_crtc_has_dp_encoder(crtc_state)) ||
4176a64d5fe4SImre Deak (!crtc_state && intel_encoder_is_dp(encoder)))
4177f9e76a6eSImre Deak intel_dp_sync_state(encoder, crtc_state);
4178f9e76a6eSImre Deak }
4179f9e76a6eSImre Deak
intel_ddi_initial_fastset_check(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state)4180b671d6efSImre Deak static bool intel_ddi_initial_fastset_check(struct intel_encoder *encoder,
4181b671d6efSImre Deak struct intel_crtc_state *crtc_state)
4182b671d6efSImre Deak {
4183eddb4afcSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4184eddb4afcSVille Syrjälä bool fastset = true;
4185b671d6efSImre Deak
41867fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) {
4187eddb4afcSVille Syrjälä drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute TC port DPLLs\n",
4188eddb4afcSVille Syrjälä encoder->base.base.id, encoder->base.name);
4189eddb4afcSVille Syrjälä crtc_state->uapi.mode_changed = true;
4190eddb4afcSVille Syrjälä fastset = false;
4191eddb4afcSVille Syrjälä }
4192eddb4afcSVille Syrjälä
4193eddb4afcSVille Syrjälä if (intel_crtc_has_dp_encoder(crtc_state) &&
4194eddb4afcSVille Syrjälä !intel_dp_initial_fastset_check(encoder, crtc_state))
4195eddb4afcSVille Syrjälä fastset = false;
4196eddb4afcSVille Syrjälä
4197eddb4afcSVille Syrjälä return fastset;
4198b671d6efSImre Deak }
4199b671d6efSImre Deak
4200379bc100SJani Nikula static enum intel_output_type
intel_ddi_compute_output_type(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state,struct drm_connector_state * conn_state)4201379bc100SJani Nikula intel_ddi_compute_output_type(struct intel_encoder *encoder,
4202379bc100SJani Nikula struct intel_crtc_state *crtc_state,
4203379bc100SJani Nikula struct drm_connector_state *conn_state)
4204379bc100SJani Nikula {
4205379bc100SJani Nikula switch (conn_state->connector->connector_type) {
4206379bc100SJani Nikula case DRM_MODE_CONNECTOR_HDMIA:
4207379bc100SJani Nikula return INTEL_OUTPUT_HDMI;
4208379bc100SJani Nikula case DRM_MODE_CONNECTOR_eDP:
4209379bc100SJani Nikula return INTEL_OUTPUT_EDP;
4210379bc100SJani Nikula case DRM_MODE_CONNECTOR_DisplayPort:
4211379bc100SJani Nikula return INTEL_OUTPUT_DP;
4212379bc100SJani Nikula default:
4213379bc100SJani Nikula MISSING_CASE(conn_state->connector->connector_type);
4214379bc100SJani Nikula return INTEL_OUTPUT_UNUSED;
4215379bc100SJani Nikula }
4216379bc100SJani Nikula }
4217379bc100SJani Nikula
intel_ddi_compute_config(struct intel_encoder * encoder,struct intel_crtc_state * pipe_config,struct drm_connector_state * conn_state)4218379bc100SJani Nikula static int intel_ddi_compute_config(struct intel_encoder *encoder,
4219379bc100SJani Nikula struct intel_crtc_state *pipe_config,
4220379bc100SJani Nikula struct drm_connector_state *conn_state)
4221379bc100SJani Nikula {
42222225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
4223379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4224379bc100SJani Nikula enum port port = encoder->port;
4225379bc100SJani Nikula int ret;
4226379bc100SJani Nikula
422710cf8e75SVille Syrjälä if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A)
4228379bc100SJani Nikula pipe_config->cpu_transcoder = TRANSCODER_EDP;
4229379bc100SJani Nikula
4230bdacf087SAnshuman Gupta if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) {
423134682d60SVille Syrjälä pipe_config->has_hdmi_sink =
423234682d60SVille Syrjälä intel_hdmi_compute_has_hdmi_sink(encoder, pipe_config, conn_state);
423334682d60SVille Syrjälä
4234379bc100SJani Nikula ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state);
4235bdacf087SAnshuman Gupta } else {
4236379bc100SJani Nikula ret = intel_dp_compute_config(encoder, pipe_config, conn_state);
4237bdacf087SAnshuman Gupta }
4238bdacf087SAnshuman Gupta
4239379bc100SJani Nikula if (ret)
4240379bc100SJani Nikula return ret;
4241379bc100SJani Nikula
4242379bc100SJani Nikula if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A &&
4243379bc100SJani Nikula pipe_config->cpu_transcoder == TRANSCODER_EDP)
4244379bc100SJani Nikula pipe_config->pch_pfit.force_thru =
4245379bc100SJani Nikula pipe_config->pch_pfit.enabled ||
4246379bc100SJani Nikula pipe_config->crc_enabled;
4247379bc100SJani Nikula
42482446e1d6SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4249379bc100SJani Nikula pipe_config->lane_lat_optim_mask =
4250ba07c3edSVille Syrjälä bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
4251379bc100SJani Nikula
42528cd53c6bSVille Syrjälä intel_ddi_compute_min_voltage_level(pipe_config);
4253379bc100SJani Nikula
4254379bc100SJani Nikula return 0;
4255379bc100SJani Nikula }
4256379bc100SJani Nikula
mode_equal(const struct drm_display_mode * mode1,const struct drm_display_mode * mode2)4257b50a1aa6SManasi Navare static bool mode_equal(const struct drm_display_mode *mode1,
4258b50a1aa6SManasi Navare const struct drm_display_mode *mode2)
4259b50a1aa6SManasi Navare {
4260b50a1aa6SManasi Navare return drm_mode_match(mode1, mode2,
4261b50a1aa6SManasi Navare DRM_MODE_MATCH_TIMINGS |
4262b50a1aa6SManasi Navare DRM_MODE_MATCH_FLAGS |
4263b50a1aa6SManasi Navare DRM_MODE_MATCH_3D_FLAGS) &&
4264b50a1aa6SManasi Navare mode1->clock == mode2->clock; /* we want an exact match */
4265b50a1aa6SManasi Navare }
4266b50a1aa6SManasi Navare
m_n_equal(const struct intel_link_m_n * m_n_1,const struct intel_link_m_n * m_n_2)4267b50a1aa6SManasi Navare static bool m_n_equal(const struct intel_link_m_n *m_n_1,
4268b50a1aa6SManasi Navare const struct intel_link_m_n *m_n_2)
4269b50a1aa6SManasi Navare {
4270b50a1aa6SManasi Navare return m_n_1->tu == m_n_2->tu &&
42715f721a5dSVille Syrjälä m_n_1->data_m == m_n_2->data_m &&
42725f721a5dSVille Syrjälä m_n_1->data_n == m_n_2->data_n &&
4273b50a1aa6SManasi Navare m_n_1->link_m == m_n_2->link_m &&
4274b50a1aa6SManasi Navare m_n_1->link_n == m_n_2->link_n;
4275b50a1aa6SManasi Navare }
4276b50a1aa6SManasi Navare
crtcs_port_sync_compatible(const struct intel_crtc_state * crtc_state1,const struct intel_crtc_state * crtc_state2)4277b50a1aa6SManasi Navare static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
4278b50a1aa6SManasi Navare const struct intel_crtc_state *crtc_state2)
4279b50a1aa6SManasi Navare {
4280b37e1347SVille Syrjälä /*
4281b37e1347SVille Syrjälä * FIXME the modeset sequence is currently wrong and
4282fb494357SStanislav Lisovskiy * can't deal with joiner + port sync at the same time.
4283b37e1347SVille Syrjälä */
4284b50a1aa6SManasi Navare return crtc_state1->hw.active && crtc_state2->hw.active &&
4285fb494357SStanislav Lisovskiy !crtc_state1->joiner_pipes && !crtc_state2->joiner_pipes &&
4286b50a1aa6SManasi Navare crtc_state1->output_types == crtc_state2->output_types &&
4287b50a1aa6SManasi Navare crtc_state1->output_format == crtc_state2->output_format &&
4288b50a1aa6SManasi Navare crtc_state1->lane_count == crtc_state2->lane_count &&
4289b50a1aa6SManasi Navare crtc_state1->port_clock == crtc_state2->port_clock &&
4290b50a1aa6SManasi Navare mode_equal(&crtc_state1->hw.adjusted_mode,
4291b50a1aa6SManasi Navare &crtc_state2->hw.adjusted_mode) &&
4292b50a1aa6SManasi Navare m_n_equal(&crtc_state1->dp_m_n, &crtc_state2->dp_m_n);
4293b50a1aa6SManasi Navare }
4294b50a1aa6SManasi Navare
4295b50a1aa6SManasi Navare static u8
intel_ddi_port_sync_transcoders(const struct intel_crtc_state * ref_crtc_state,int tile_group_id)4296b50a1aa6SManasi Navare intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state,
4297b50a1aa6SManasi Navare int tile_group_id)
4298b50a1aa6SManasi Navare {
4299b50a1aa6SManasi Navare struct drm_connector *connector;
4300b50a1aa6SManasi Navare const struct drm_connector_state *conn_state;
4301b50a1aa6SManasi Navare struct drm_i915_private *dev_priv = to_i915(ref_crtc_state->uapi.crtc->dev);
4302b50a1aa6SManasi Navare struct intel_atomic_state *state =
4303b50a1aa6SManasi Navare to_intel_atomic_state(ref_crtc_state->uapi.state);
4304b50a1aa6SManasi Navare u8 transcoders = 0;
4305b50a1aa6SManasi Navare int i;
4306b50a1aa6SManasi Navare
4307dc5b8ed5SVille Syrjälä /*
4308dc5b8ed5SVille Syrjälä * We don't enable port sync on BDW due to missing w/as and
4309dc5b8ed5SVille Syrjälä * due to not having adjusted the modeset sequence appropriately.
4310dc5b8ed5SVille Syrjälä */
4311005e9537SMatt Roper if (DISPLAY_VER(dev_priv) < 9)
4312b50a1aa6SManasi Navare return 0;
4313b50a1aa6SManasi Navare
4314b50a1aa6SManasi Navare if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP))
4315b50a1aa6SManasi Navare return 0;
4316b50a1aa6SManasi Navare
4317b50a1aa6SManasi Navare for_each_new_connector_in_state(&state->base, connector, conn_state, i) {
4318b50a1aa6SManasi Navare struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc);
4319b50a1aa6SManasi Navare const struct intel_crtc_state *crtc_state;
4320b50a1aa6SManasi Navare
4321b50a1aa6SManasi Navare if (!crtc)
4322b50a1aa6SManasi Navare continue;
4323b50a1aa6SManasi Navare
4324b50a1aa6SManasi Navare if (!connector->has_tile ||
4325b50a1aa6SManasi Navare connector->tile_group->id !=
4326b50a1aa6SManasi Navare tile_group_id)
4327b50a1aa6SManasi Navare continue;
4328b50a1aa6SManasi Navare crtc_state = intel_atomic_get_new_crtc_state(state,
4329b50a1aa6SManasi Navare crtc);
4330b50a1aa6SManasi Navare if (!crtcs_port_sync_compatible(ref_crtc_state,
4331b50a1aa6SManasi Navare crtc_state))
4332b50a1aa6SManasi Navare continue;
4333b50a1aa6SManasi Navare transcoders |= BIT(crtc_state->cpu_transcoder);
4334b50a1aa6SManasi Navare }
4335b50a1aa6SManasi Navare
4336b50a1aa6SManasi Navare return transcoders;
4337b50a1aa6SManasi Navare }
4338b50a1aa6SManasi Navare
intel_ddi_compute_config_late(struct intel_encoder * encoder,struct intel_crtc_state * crtc_state,struct drm_connector_state * conn_state)4339b50a1aa6SManasi Navare static int intel_ddi_compute_config_late(struct intel_encoder *encoder,
4340b50a1aa6SManasi Navare struct intel_crtc_state *crtc_state,
4341b50a1aa6SManasi Navare struct drm_connector_state *conn_state)
4342b50a1aa6SManasi Navare {
434347bdb1caSJani Nikula struct drm_i915_private *i915 = to_i915(encoder->base.dev);
4344b50a1aa6SManasi Navare struct drm_connector *connector = conn_state->connector;
4345b50a1aa6SManasi Navare u8 port_sync_transcoders = 0;
4346b50a1aa6SManasi Navare
434718367034SJim Cromie drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]\n",
4348b50a1aa6SManasi Navare encoder->base.base.id, encoder->base.name,
4349b50a1aa6SManasi Navare crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name);
4350b50a1aa6SManasi Navare
4351b50a1aa6SManasi Navare if (connector->has_tile)
4352b50a1aa6SManasi Navare port_sync_transcoders = intel_ddi_port_sync_transcoders(crtc_state,
4353b50a1aa6SManasi Navare connector->tile_group->id);
4354b50a1aa6SManasi Navare
4355b50a1aa6SManasi Navare /*
4356b50a1aa6SManasi Navare * EDP Transcoders cannot be ensalved
4357b50a1aa6SManasi Navare * make them a master always when present
4358b50a1aa6SManasi Navare */
4359b50a1aa6SManasi Navare if (port_sync_transcoders & BIT(TRANSCODER_EDP))
4360b50a1aa6SManasi Navare crtc_state->master_transcoder = TRANSCODER_EDP;
4361b50a1aa6SManasi Navare else
4362b50a1aa6SManasi Navare crtc_state->master_transcoder = ffs(port_sync_transcoders) - 1;
4363b50a1aa6SManasi Navare
4364b50a1aa6SManasi Navare if (crtc_state->master_transcoder == crtc_state->cpu_transcoder) {
4365b50a1aa6SManasi Navare crtc_state->master_transcoder = INVALID_TRANSCODER;
4366b50a1aa6SManasi Navare crtc_state->sync_mode_slaves_mask =
4367b50a1aa6SManasi Navare port_sync_transcoders & ~BIT(crtc_state->cpu_transcoder);
4368b50a1aa6SManasi Navare }
4369b50a1aa6SManasi Navare
4370b50a1aa6SManasi Navare return 0;
4371b50a1aa6SManasi Navare }
4372b50a1aa6SManasi Navare
intel_ddi_encoder_destroy(struct drm_encoder * encoder)4373379bc100SJani Nikula static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
4374379bc100SJani Nikula {
43754a300e65SImre Deak struct drm_i915_private *i915 = to_i915(encoder->dev);
4376b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
4377379bc100SJani Nikula
4378379bc100SJani Nikula intel_dp_encoder_flush_work(encoder);
43797fcf7558SJani Nikula if (intel_encoder_is_tc(&dig_port->base))
4380c5879999SImre Deak intel_tc_port_cleanup(dig_port);
43814a300e65SImre Deak intel_display_power_flush_work(i915);
4382379bc100SJani Nikula
4383379bc100SJani Nikula drm_encoder_cleanup(encoder);
4384a6c6eac9SAnshuman Gupta kfree(dig_port->hdcp_port_data.streams);
4385379bc100SJani Nikula kfree(dig_port);
4386379bc100SJani Nikula }
4387379bc100SJani Nikula
intel_ddi_encoder_reset(struct drm_encoder * encoder)4388764f6729SVille Syrjälä static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
4389764f6729SVille Syrjälä {
4390764f6729SVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
4391a82796a2SImre Deak struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
4392764f6729SVille Syrjälä
4393764f6729SVille Syrjälä intel_dp->reset_link_params = true;
4394764f6729SVille Syrjälä
4395764f6729SVille Syrjälä intel_pps_encoder_reset(intel_dp);
4396a82796a2SImre Deak
43977fcf7558SJani Nikula if (intel_encoder_is_tc(&dig_port->base))
4398a82796a2SImre Deak intel_tc_port_init_mode(dig_port);
4399764f6729SVille Syrjälä }
4400764f6729SVille Syrjälä
intel_ddi_encoder_late_register(struct drm_encoder * _encoder)4401c598c335SImre Deak static int intel_ddi_encoder_late_register(struct drm_encoder *_encoder)
4402c598c335SImre Deak {
4403c598c335SImre Deak struct intel_encoder *encoder = to_intel_encoder(_encoder);
4404c598c335SImre Deak
4405c598c335SImre Deak intel_tc_port_link_reset(enc_to_dig_port(encoder));
4406c598c335SImre Deak
4407c598c335SImre Deak return 0;
4408c598c335SImre Deak }
4409c598c335SImre Deak
4410379bc100SJani Nikula static const struct drm_encoder_funcs intel_ddi_funcs = {
4411764f6729SVille Syrjälä .reset = intel_ddi_encoder_reset,
4412379bc100SJani Nikula .destroy = intel_ddi_encoder_destroy,
4413c598c335SImre Deak .late_register = intel_ddi_encoder_late_register,
4414379bc100SJani Nikula };
4415379bc100SJani Nikula
4416379bc100SJani Nikula static struct intel_connector *
intel_ddi_init_dp_connector(struct intel_digital_port * dig_port)44177801f3b7SLucas De Marchi intel_ddi_init_dp_connector(struct intel_digital_port *dig_port)
4418379bc100SJani Nikula {
441923ef6194SJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
4420379bc100SJani Nikula struct intel_connector *connector;
44217801f3b7SLucas De Marchi enum port port = dig_port->base.port;
4422379bc100SJani Nikula
4423379bc100SJani Nikula connector = intel_connector_alloc();
4424379bc100SJani Nikula if (!connector)
4425379bc100SJani Nikula return NULL;
4426379bc100SJani Nikula
44277801f3b7SLucas De Marchi dig_port->dp.output_reg = DDI_BUF_CTL(port);
442823ef6194SJosé Roberto de Souza if (DISPLAY_VER(i915) >= 14)
442923ef6194SJosé Roberto de Souza dig_port->dp.prepare_link_retrain = mtl_ddi_prepare_link_retrain;
443023ef6194SJosé Roberto de Souza else
44317801f3b7SLucas De Marchi dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain;
44327801f3b7SLucas De Marchi dig_port->dp.set_link_train = intel_ddi_set_link_train;
44337801f3b7SLucas De Marchi dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train;
4434eee3f911SVille Syrjälä
44357801f3b7SLucas De Marchi dig_port->dp.voltage_max = intel_ddi_dp_voltage_max;
44367801f3b7SLucas De Marchi dig_port->dp.preemph_max = intel_ddi_dp_preemph_max;
443753de0a20SVille Syrjälä
44387801f3b7SLucas De Marchi if (!intel_dp_init_connector(dig_port, connector)) {
4439379bc100SJani Nikula kfree(connector);
4440379bc100SJani Nikula return NULL;
4441379bc100SJani Nikula }
4442379bc100SJani Nikula
44436306d8dbSHans de Goede if (dig_port->base.type == INTEL_OUTPUT_EDP) {
44446306d8dbSHans de Goede struct drm_device *dev = dig_port->base.base.dev;
44456306d8dbSHans de Goede struct drm_privacy_screen *privacy_screen;
44466306d8dbSHans de Goede
44476306d8dbSHans de Goede privacy_screen = drm_privacy_screen_get(dev->dev, NULL);
44486306d8dbSHans de Goede if (!IS_ERR(privacy_screen)) {
44496306d8dbSHans de Goede drm_connector_attach_privacy_screen_provider(&connector->base,
44506306d8dbSHans de Goede privacy_screen);
44516306d8dbSHans de Goede } else if (PTR_ERR(privacy_screen) != -ENODEV) {
44526306d8dbSHans de Goede drm_warn(dev, "Error getting privacy-screen\n");
44536306d8dbSHans de Goede }
44546306d8dbSHans de Goede }
44556306d8dbSHans de Goede
4456379bc100SJani Nikula return connector;
4457379bc100SJani Nikula }
4458379bc100SJani Nikula
intel_hdmi_reset_link(struct intel_encoder * encoder,struct drm_modeset_acquire_ctx * ctx)4459379bc100SJani Nikula static int intel_hdmi_reset_link(struct intel_encoder *encoder,
4460379bc100SJani Nikula struct drm_modeset_acquire_ctx *ctx)
4461379bc100SJani Nikula {
4462379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
4463b7d02c3aSVille Syrjälä struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder);
4464379bc100SJani Nikula struct intel_connector *connector = hdmi->attached_connector;
4465e046d156SVille Syrjälä struct i2c_adapter *ddc = connector->base.ddc;
4466379bc100SJani Nikula struct drm_connector_state *conn_state;
4467379bc100SJani Nikula struct intel_crtc_state *crtc_state;
4468379bc100SJani Nikula struct intel_crtc *crtc;
4469379bc100SJani Nikula u8 config;
4470379bc100SJani Nikula int ret;
4471379bc100SJani Nikula
44723385375bSSuraj Kandpal if (connector->base.status != connector_status_connected)
4473379bc100SJani Nikula return 0;
4474379bc100SJani Nikula
4475379bc100SJani Nikula ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex,
4476379bc100SJani Nikula ctx);
4477379bc100SJani Nikula if (ret)
4478379bc100SJani Nikula return ret;
4479379bc100SJani Nikula
4480379bc100SJani Nikula conn_state = connector->base.state;
4481379bc100SJani Nikula
4482379bc100SJani Nikula crtc = to_intel_crtc(conn_state->crtc);
4483379bc100SJani Nikula if (!crtc)
4484379bc100SJani Nikula return 0;
4485379bc100SJani Nikula
4486379bc100SJani Nikula ret = drm_modeset_lock(&crtc->base.mutex, ctx);
4487379bc100SJani Nikula if (ret)
4488379bc100SJani Nikula return ret;
4489379bc100SJani Nikula
4490379bc100SJani Nikula crtc_state = to_intel_crtc_state(crtc->base.state);
4491379bc100SJani Nikula
44921de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm,
44931de143ccSPankaj Bharadiya !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI));
4494379bc100SJani Nikula
44951326a92cSMaarten Lankhorst if (!crtc_state->hw.active)
4496379bc100SJani Nikula return 0;
4497379bc100SJani Nikula
4498379bc100SJani Nikula if (!crtc_state->hdmi_high_tmds_clock_ratio &&
4499379bc100SJani Nikula !crtc_state->hdmi_scrambling)
4500379bc100SJani Nikula return 0;
4501379bc100SJani Nikula
4502379bc100SJani Nikula if (conn_state->commit &&
4503379bc100SJani Nikula !try_wait_for_completion(&conn_state->commit->hw_done))
4504379bc100SJani Nikula return 0;
4505379bc100SJani Nikula
450630b98ecbSVille Syrjälä ret = drm_scdc_readb(ddc, SCDC_TMDS_CONFIG, &config);
4507379bc100SJani Nikula if (ret < 0) {
45085d844091SVille Syrjälä drm_err(&dev_priv->drm, "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n",
45095d844091SVille Syrjälä connector->base.base.id, connector->base.name, ret);
4510379bc100SJani Nikula return 0;
4511379bc100SJani Nikula }
4512379bc100SJani Nikula
4513379bc100SJani Nikula if (!!(config & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) ==
4514379bc100SJani Nikula crtc_state->hdmi_high_tmds_clock_ratio &&
4515379bc100SJani Nikula !!(config & SCDC_SCRAMBLING_ENABLE) ==
4516379bc100SJani Nikula crtc_state->hdmi_scrambling)
4517379bc100SJani Nikula return 0;
4518379bc100SJani Nikula
4519379bc100SJani Nikula /*
4520379bc100SJani Nikula * HDMI 2.0 says that one should not send scrambled data
4521379bc100SJani Nikula * prior to configuring the sink scrambling, and that
4522379bc100SJani Nikula * TMDS clock/data transmission should be suspended when
4523379bc100SJani Nikula * changing the TMDS clock rate in the sink. So let's
4524379bc100SJani Nikula * just do a full modeset here, even though some sinks
4525379bc100SJani Nikula * would be perfectly happy if were to just reconfigure
4526379bc100SJani Nikula * the SCDC settings on the fly.
4527379bc100SJani Nikula */
4528e5bf189aSImre Deak return intel_modeset_commit_pipes(dev_priv, BIT(crtc->pipe), ctx);
4529379bc100SJani Nikula }
4530379bc100SJani Nikula
intel_ddi_link_check(struct intel_encoder * encoder)45313b3be899SImre Deak static void intel_ddi_link_check(struct intel_encoder *encoder)
45323b3be899SImre Deak {
45333b3be899SImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev);
45343b3be899SImre Deak struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
45353b3be899SImre Deak
45363b3be899SImre Deak /* TODO: Move checking the HDMI link state here as well. */
45373b3be899SImre Deak drm_WARN_ON(&i915->drm, !dig_port->dp.attached_connector);
45383b3be899SImre Deak
45393b3be899SImre Deak intel_dp_link_check(encoder);
45403b3be899SImre Deak }
45413b3be899SImre Deak
45423944709dSImre Deak static enum intel_hotplug_state
intel_ddi_hotplug(struct intel_encoder * encoder,struct intel_connector * connector)45433944709dSImre Deak intel_ddi_hotplug(struct intel_encoder *encoder,
45448c8919c7SImre Deak struct intel_connector *connector)
4545379bc100SJani Nikula {
4546b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
4547699390f7SVille Syrjälä struct intel_dp *intel_dp = &dig_port->dp;
45487fcf7558SJani Nikula bool is_tc = intel_encoder_is_tc(encoder);
4549379bc100SJani Nikula struct drm_modeset_acquire_ctx ctx;
45503944709dSImre Deak enum intel_hotplug_state state;
4551379bc100SJani Nikula int ret;
4552379bc100SJani Nikula
4553699390f7SVille Syrjälä if (intel_dp->compliance.test_active &&
4554699390f7SVille Syrjälä intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) {
4555699390f7SVille Syrjälä intel_dp_phy_test(encoder);
4556699390f7SVille Syrjälä /* just do the PHY test and nothing else */
4557699390f7SVille Syrjälä return INTEL_HOTPLUG_UNCHANGED;
4558699390f7SVille Syrjälä }
4559699390f7SVille Syrjälä
45608c8919c7SImre Deak state = intel_encoder_hotplug(encoder, connector);
4561379bc100SJani Nikula
4562c598c335SImre Deak if (!intel_tc_port_link_reset(dig_port)) {
4563b22b4dd9SImre Deak if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) {
4564b22b4dd9SImre Deak intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret)
4565379bc100SJani Nikula ret = intel_hdmi_reset_link(encoder, &ctx);
456660ded7ccSImre Deak drm_WARN_ON(encoder->base.dev, ret);
4567b22b4dd9SImre Deak } else {
4568b22b4dd9SImre Deak intel_dp_check_link_state(intel_dp);
4569b22b4dd9SImre Deak }
4570c598c335SImre Deak }
4571379bc100SJani Nikula
4572bb80c925SJosé Roberto de Souza /*
4573bb80c925SJosé Roberto de Souza * Unpowered type-c dongles can take some time to boot and be
4574bb80c925SJosé Roberto de Souza * responsible, so here giving some time to those dongles to power up
4575bb80c925SJosé Roberto de Souza * and then retrying the probe.
4576bb80c925SJosé Roberto de Souza *
4577bb80c925SJosé Roberto de Souza * On many platforms the HDMI live state signal is known to be
4578bb80c925SJosé Roberto de Souza * unreliable, so we can't use it to detect if a sink is connected or
4579bb80c925SJosé Roberto de Souza * not. Instead we detect if it's connected based on whether we can
4580bb80c925SJosé Roberto de Souza * read the EDID or not. That in turn has a problem during disconnect,
4581bb80c925SJosé Roberto de Souza * since the HPD interrupt may be raised before the DDC lines get
4582bb80c925SJosé Roberto de Souza * disconnected (due to how the required length of DDC vs. HPD
4583bb80c925SJosé Roberto de Souza * connector pins are specified) and so we'll still be able to get a
4584bb80c925SJosé Roberto de Souza * valid EDID. To solve this schedule another detection cycle if this
4585bb80c925SJosé Roberto de Souza * time around we didn't detect any change in the sink's connection
4586bb80c925SJosé Roberto de Souza * status.
4587b4df5405SImre Deak *
4588b4df5405SImre Deak * Type-c connectors which get their HPD signal deasserted then
4589b4df5405SImre Deak * reasserted, without unplugging/replugging the sink from the
4590b4df5405SImre Deak * connector, introduce a delay until the AUX channel communication
4591b4df5405SImre Deak * becomes functional. Retry the detection for 5 seconds on type-c
4592b4df5405SImre Deak * connectors to account for this delay.
4593bb80c925SJosé Roberto de Souza */
4594b4df5405SImre Deak if (state == INTEL_HOTPLUG_UNCHANGED &&
4595b4df5405SImre Deak connector->hotplug_retries < (is_tc ? 5 : 1) &&
4596bb80c925SJosé Roberto de Souza !dig_port->dp.is_mst)
4597bb80c925SJosé Roberto de Souza state = INTEL_HOTPLUG_RETRY;
4598bb80c925SJosé Roberto de Souza
45993944709dSImre Deak return state;
4600379bc100SJani Nikula }
4601379bc100SJani Nikula
lpt_digital_port_connected(struct intel_encoder * encoder)4602edc0e09cSVille Syrjälä static bool lpt_digital_port_connected(struct intel_encoder *encoder)
4603edc0e09cSVille Syrjälä {
4604edc0e09cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
46055a4dd6f0SJani Nikula u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin];
4606edc0e09cSVille Syrjälä
4607edc0e09cSVille Syrjälä return intel_de_read(dev_priv, SDEISR) & bit;
4608edc0e09cSVille Syrjälä }
4609edc0e09cSVille Syrjälä
hsw_digital_port_connected(struct intel_encoder * encoder)4610edc0e09cSVille Syrjälä static bool hsw_digital_port_connected(struct intel_encoder *encoder)
4611edc0e09cSVille Syrjälä {
4612edc0e09cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
46135a4dd6f0SJani Nikula u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4614edc0e09cSVille Syrjälä
4615c7e8a3d6SVille Syrjälä return intel_de_read(dev_priv, DEISR) & bit;
4616edc0e09cSVille Syrjälä }
4617edc0e09cSVille Syrjälä
bdw_digital_port_connected(struct intel_encoder * encoder)4618edc0e09cSVille Syrjälä static bool bdw_digital_port_connected(struct intel_encoder *encoder)
4619edc0e09cSVille Syrjälä {
4620edc0e09cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
46215a4dd6f0SJani Nikula u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin];
4622edc0e09cSVille Syrjälä
4623edc0e09cSVille Syrjälä return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit;
4624edc0e09cSVille Syrjälä }
4625edc0e09cSVille Syrjälä
4626379bc100SJani Nikula static struct intel_connector *
intel_ddi_init_hdmi_connector(struct intel_digital_port * dig_port)46277801f3b7SLucas De Marchi intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port)
4628379bc100SJani Nikula {
4629379bc100SJani Nikula struct intel_connector *connector;
46307801f3b7SLucas De Marchi enum port port = dig_port->base.port;
4631379bc100SJani Nikula
4632379bc100SJani Nikula connector = intel_connector_alloc();
4633379bc100SJani Nikula if (!connector)
4634379bc100SJani Nikula return NULL;
4635379bc100SJani Nikula
46367801f3b7SLucas De Marchi dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port);
46377801f3b7SLucas De Marchi intel_hdmi_init_connector(dig_port, connector);
4638379bc100SJani Nikula
4639379bc100SJani Nikula return connector;
4640379bc100SJani Nikula }
4641379bc100SJani Nikula
intel_ddi_a_force_4_lanes(struct intel_digital_port * dig_port)46427801f3b7SLucas De Marchi static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port)
4643379bc100SJani Nikula {
46447801f3b7SLucas De Marchi struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
4645379bc100SJani Nikula
46467801f3b7SLucas De Marchi if (dig_port->base.port != PORT_A)
4647379bc100SJani Nikula return false;
4648379bc100SJani Nikula
46497801f3b7SLucas De Marchi if (dig_port->saved_port_bits & DDI_A_4_LANES)
4650379bc100SJani Nikula return false;
4651379bc100SJani Nikula
4652379bc100SJani Nikula /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only
4653379bc100SJani Nikula * supported configuration
4654379bc100SJani Nikula */
46552446e1d6SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))
4656379bc100SJani Nikula return true;
4657379bc100SJani Nikula
4658379bc100SJani Nikula return false;
4659379bc100SJani Nikula }
4660379bc100SJani Nikula
4661379bc100SJani Nikula static int
intel_ddi_max_lanes(struct intel_digital_port * dig_port)46627801f3b7SLucas De Marchi intel_ddi_max_lanes(struct intel_digital_port *dig_port)
4663379bc100SJani Nikula {
46647801f3b7SLucas De Marchi struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
46657801f3b7SLucas De Marchi enum port port = dig_port->base.port;
4666379bc100SJani Nikula int max_lanes = 4;
4667379bc100SJani Nikula
4668005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11)
4669379bc100SJani Nikula return max_lanes;
4670379bc100SJani Nikula
4671379bc100SJani Nikula if (port == PORT_A || port == PORT_E) {
4672f7960e7fSJani Nikula if (intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)
4673379bc100SJani Nikula max_lanes = port == PORT_A ? 4 : 0;
4674379bc100SJani Nikula else
4675379bc100SJani Nikula /* Both A and E share 2 lanes */
4676379bc100SJani Nikula max_lanes = 2;
4677379bc100SJani Nikula }
4678379bc100SJani Nikula
4679379bc100SJani Nikula /*
4680379bc100SJani Nikula * Some BIOS might fail to set this bit on port A if eDP
4681379bc100SJani Nikula * wasn't lit up at boot. Force this bit set when needed
4682379bc100SJani Nikula * so we use the proper lane count for our calculations.
4683379bc100SJani Nikula */
46847801f3b7SLucas De Marchi if (intel_ddi_a_force_4_lanes(dig_port)) {
468547bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm,
468647bdb1caSJani Nikula "Forcing DDI_A_4_LANES for port A\n");
46877801f3b7SLucas De Marchi dig_port->saved_port_bits |= DDI_A_4_LANES;
4688379bc100SJani Nikula max_lanes = 4;
4689379bc100SJani Nikula }
4690379bc100SJani Nikula
4691379bc100SJani Nikula return max_lanes;
4692379bc100SJani Nikula }
4693379bc100SJani Nikula
xelpd_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4694ed2615a8SMatt Roper static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv,
4695ed2615a8SMatt Roper enum port port)
4696ed2615a8SMatt Roper {
4697ed2615a8SMatt Roper if (port >= PORT_D_XELPD)
4698ed2615a8SMatt Roper return HPD_PORT_D + port - PORT_D_XELPD;
4699ed2615a8SMatt Roper else if (port >= PORT_TC1)
4700ed2615a8SMatt Roper return HPD_PORT_TC1 + port - PORT_TC1;
4701ed2615a8SMatt Roper else
4702ed2615a8SMatt Roper return HPD_PORT_A + port - PORT_A;
4703ed2615a8SMatt Roper }
4704ed2615a8SMatt Roper
dg1_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4705229f31e2SLucas De Marchi static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv,
4706229f31e2SLucas De Marchi enum port port)
4707229f31e2SLucas De Marchi {
47081d8ca002SVille Syrjälä if (port >= PORT_TC1)
47091d8ca002SVille Syrjälä return HPD_PORT_C + port - PORT_TC1;
4710229f31e2SLucas De Marchi else
4711229f31e2SLucas De Marchi return HPD_PORT_A + port - PORT_A;
4712229f31e2SLucas De Marchi }
4713229f31e2SLucas De Marchi
tgl_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4714da51e4baSVille Syrjälä static enum hpd_pin tgl_hpd_pin(struct drm_i915_private *dev_priv,
4715da51e4baSVille Syrjälä enum port port)
4716da51e4baSVille Syrjälä {
47171d8ca002SVille Syrjälä if (port >= PORT_TC1)
47181d8ca002SVille Syrjälä return HPD_PORT_TC1 + port - PORT_TC1;
4719da51e4baSVille Syrjälä else
4720da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A;
4721da51e4baSVille Syrjälä }
4722da51e4baSVille Syrjälä
rkl_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4723da51e4baSVille Syrjälä static enum hpd_pin rkl_hpd_pin(struct drm_i915_private *dev_priv,
4724da51e4baSVille Syrjälä enum port port)
4725da51e4baSVille Syrjälä {
4726da51e4baSVille Syrjälä if (HAS_PCH_TGP(dev_priv))
4727da51e4baSVille Syrjälä return tgl_hpd_pin(dev_priv, port);
4728da51e4baSVille Syrjälä
47291d8ca002SVille Syrjälä if (port >= PORT_TC1)
47301d8ca002SVille Syrjälä return HPD_PORT_C + port - PORT_TC1;
4731da51e4baSVille Syrjälä else
4732da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A;
4733da51e4baSVille Syrjälä }
4734da51e4baSVille Syrjälä
icl_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4735da51e4baSVille Syrjälä static enum hpd_pin icl_hpd_pin(struct drm_i915_private *dev_priv,
4736da51e4baSVille Syrjälä enum port port)
4737da51e4baSVille Syrjälä {
4738da51e4baSVille Syrjälä if (port >= PORT_C)
4739da51e4baSVille Syrjälä return HPD_PORT_TC1 + port - PORT_C;
4740da51e4baSVille Syrjälä else
4741da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A;
4742da51e4baSVille Syrjälä }
4743da51e4baSVille Syrjälä
ehl_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4744da51e4baSVille Syrjälä static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv,
4745da51e4baSVille Syrjälä enum port port)
4746da51e4baSVille Syrjälä {
4747da51e4baSVille Syrjälä if (port == PORT_D)
4748da51e4baSVille Syrjälä return HPD_PORT_A;
4749da51e4baSVille Syrjälä
4750f24d1d45SVille Syrjälä if (HAS_PCH_TGP(dev_priv))
4751da51e4baSVille Syrjälä return icl_hpd_pin(dev_priv, port);
4752da51e4baSVille Syrjälä
4753da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A;
4754da51e4baSVille Syrjälä }
4755da51e4baSVille Syrjälä
skl_hpd_pin(struct drm_i915_private * dev_priv,enum port port)4756c8455098SLyude Paul static enum hpd_pin skl_hpd_pin(struct drm_i915_private *dev_priv, enum port port)
4757c8455098SLyude Paul {
4758c8455098SLyude Paul if (HAS_PCH_TGP(dev_priv))
4759c8455098SLyude Paul return icl_hpd_pin(dev_priv, port);
4760c8455098SLyude Paul
4761c8455098SLyude Paul return HPD_PORT_A + port - PORT_A;
4762c8455098SLyude Paul }
4763c8455098SLyude Paul
intel_ddi_is_tc(struct drm_i915_private * i915,enum port port)476436ecb0ecSVille Syrjälä static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port)
476536ecb0ecSVille Syrjälä {
4766005e9537SMatt Roper if (DISPLAY_VER(i915) >= 12)
476736ecb0ecSVille Syrjälä return port >= PORT_TC1;
4768005e9537SMatt Roper else if (DISPLAY_VER(i915) >= 11)
476936ecb0ecSVille Syrjälä return port >= PORT_C;
477036ecb0ecSVille Syrjälä else
477136ecb0ecSVille Syrjälä return false;
477236ecb0ecSVille Syrjälä }
477336ecb0ecSVille Syrjälä
intel_ddi_encoder_suspend(struct intel_encoder * encoder)4774151ec347SImre Deak static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
4775151ec347SImre Deak {
4776151ec347SImre Deak intel_dp_encoder_suspend(encoder);
4777b61fad5fSImre Deak }
4778151ec347SImre Deak
intel_ddi_tc_encoder_suspend_complete(struct intel_encoder * encoder)4779b61fad5fSImre Deak static void intel_ddi_tc_encoder_suspend_complete(struct intel_encoder *encoder)
4780b61fad5fSImre Deak {
4781b61fad5fSImre Deak struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4782b61fad5fSImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4783151ec347SImre Deak
47843b3be899SImre Deak /*
47853b3be899SImre Deak * TODO: Move this to intel_dp_encoder_suspend(),
47863b3be899SImre Deak * once modeset locking around that is removed.
47873b3be899SImre Deak */
47883b3be899SImre Deak intel_encoder_link_check_flush_work(encoder);
4789c598c335SImre Deak intel_tc_port_suspend(dig_port);
4790151ec347SImre Deak }
4791151ec347SImre Deak
intel_ddi_encoder_shutdown(struct intel_encoder * encoder)4792151ec347SImre Deak static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder)
4793151ec347SImre Deak {
4794151ec347SImre Deak intel_dp_encoder_shutdown(encoder);
479549c55f7bSVille Syrjälä intel_hdmi_encoder_shutdown(encoder);
4796b61fad5fSImre Deak }
4797151ec347SImre Deak
intel_ddi_tc_encoder_shutdown_complete(struct intel_encoder * encoder)4798b61fad5fSImre Deak static void intel_ddi_tc_encoder_shutdown_complete(struct intel_encoder *encoder)
4799b61fad5fSImre Deak {
4800b61fad5fSImre Deak struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
4801b61fad5fSImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
4802151ec347SImre Deak
4803c5879999SImre Deak intel_tc_port_cleanup(dig_port);
4804151ec347SImre Deak }
4805151ec347SImre Deak
480683566d13SVille Syrjälä #define port_tc_name(port) ((port) - PORT_TC1 + '1')
480783566d13SVille Syrjälä #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1')
480883566d13SVille Syrjälä
port_strap_detected(struct drm_i915_private * i915,enum port port)4809d77721c1SVille Syrjälä static bool port_strap_detected(struct drm_i915_private *i915, enum port port)
4810d77721c1SVille Syrjälä {
4811d77721c1SVille Syrjälä /* straps not used on skl+ */
4812d77721c1SVille Syrjälä if (DISPLAY_VER(i915) >= 9)
4813d77721c1SVille Syrjälä return true;
4814d77721c1SVille Syrjälä
4815d77721c1SVille Syrjälä switch (port) {
4816d77721c1SVille Syrjälä case PORT_A:
4817d77721c1SVille Syrjälä return intel_de_read(i915, DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED;
4818d77721c1SVille Syrjälä case PORT_B:
4819d77721c1SVille Syrjälä return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDIB_DETECTED;
4820d77721c1SVille Syrjälä case PORT_C:
4821d77721c1SVille Syrjälä return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDIC_DETECTED;
4822d77721c1SVille Syrjälä case PORT_D:
4823d77721c1SVille Syrjälä return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDID_DETECTED;
4824d77721c1SVille Syrjälä case PORT_E:
4825d77721c1SVille Syrjälä return true; /* no strap for DDI-E */
4826d77721c1SVille Syrjälä default:
4827d77721c1SVille Syrjälä MISSING_CASE(port);
4828d77721c1SVille Syrjälä return false;
4829d77721c1SVille Syrjälä }
4830d77721c1SVille Syrjälä }
4831d77721c1SVille Syrjälä
need_aux_ch(struct intel_encoder * encoder,bool init_dp)48329856308cSVille Syrjälä static bool need_aux_ch(struct intel_encoder *encoder, bool init_dp)
48339856308cSVille Syrjälä {
48347fcf7558SJani Nikula return init_dp || intel_encoder_is_tc(encoder);
48359856308cSVille Syrjälä }
48369856308cSVille Syrjälä
assert_has_icl_dsi(struct drm_i915_private * i915)4837021a62a5SVille Syrjälä static bool assert_has_icl_dsi(struct drm_i915_private *i915)
4838021a62a5SVille Syrjälä {
4839021a62a5SVille Syrjälä return !drm_WARN(&i915->drm, !IS_ALDERLAKE_P(i915) &&
4840021a62a5SVille Syrjälä !IS_TIGERLAKE(i915) && DISPLAY_VER(i915) != 11,
4841021a62a5SVille Syrjälä "Platform does not support DSI\n");
4842021a62a5SVille Syrjälä }
4843021a62a5SVille Syrjälä
port_in_use(struct drm_i915_private * i915,enum port port)4844021a62a5SVille Syrjälä static bool port_in_use(struct drm_i915_private *i915, enum port port)
4845021a62a5SVille Syrjälä {
4846021a62a5SVille Syrjälä struct intel_encoder *encoder;
4847021a62a5SVille Syrjälä
4848021a62a5SVille Syrjälä for_each_intel_encoder(&i915->drm, encoder) {
4849021a62a5SVille Syrjälä /* FIXME what about second port for dual link DSI? */
4850021a62a5SVille Syrjälä if (encoder->port == port)
4851021a62a5SVille Syrjälä return true;
4852021a62a5SVille Syrjälä }
4853021a62a5SVille Syrjälä
4854021a62a5SVille Syrjälä return false;
4855021a62a5SVille Syrjälä }
4856021a62a5SVille Syrjälä
intel_ddi_init(struct intel_display * display,const struct intel_bios_encoder_data * devdata)48579aec6f76SJani Nikula void intel_ddi_init(struct intel_display *display,
4858021a62a5SVille Syrjälä const struct intel_bios_encoder_data *devdata)
4859379bc100SJani Nikula {
48609aec6f76SJani Nikula struct drm_i915_private *dev_priv = to_i915(display->drm);
48617801f3b7SLucas De Marchi struct intel_digital_port *dig_port;
486270dfbc29SLucas De Marchi struct intel_encoder *encoder;
4863f542d671SKai-Heng Feng bool init_hdmi, init_dp;
4864021a62a5SVille Syrjälä enum port port;
4865021a62a5SVille Syrjälä enum phy phy;
4866021a62a5SVille Syrjälä
4867021a62a5SVille Syrjälä port = intel_bios_encoder_port(devdata);
4868021a62a5SVille Syrjälä if (port == PORT_NONE)
4869021a62a5SVille Syrjälä return;
4870379bc100SJani Nikula
4871d77721c1SVille Syrjälä if (!port_strap_detected(dev_priv, port)) {
4872d77721c1SVille Syrjälä drm_dbg_kms(&dev_priv->drm,
4873d77721c1SVille Syrjälä "Port %c strap not detected\n", port_name(port));
4874d77721c1SVille Syrjälä return;
4875d77721c1SVille Syrjälä }
4876d77721c1SVille Syrjälä
4877679df6f1SVille Syrjälä if (!assert_port_valid(dev_priv, port))
4878679df6f1SVille Syrjälä return;
4879679df6f1SVille Syrjälä
4880021a62a5SVille Syrjälä if (port_in_use(dev_priv, port)) {
4881021a62a5SVille Syrjälä drm_dbg_kms(&dev_priv->drm,
4882021a62a5SVille Syrjälä "Port %c already claimed\n", port_name(port));
4883021a62a5SVille Syrjälä return;
4884021a62a5SVille Syrjälä }
4885021a62a5SVille Syrjälä
4886021a62a5SVille Syrjälä if (intel_bios_encoder_supports_dsi(devdata)) {
4887021a62a5SVille Syrjälä /* BXT/GLK handled elsewhere, for now at least */
4888021a62a5SVille Syrjälä if (!assert_has_icl_dsi(dev_priv))
4889021a62a5SVille Syrjälä return;
4890021a62a5SVille Syrjälä
4891021a62a5SVille Syrjälä icl_dsi_init(dev_priv, devdata);
4892021a62a5SVille Syrjälä return;
4893021a62a5SVille Syrjälä }
4894021a62a5SVille Syrjälä
4895021a62a5SVille Syrjälä phy = intel_port_to_phy(dev_priv, port);
4896021a62a5SVille Syrjälä
4897ddff9a60SMatt Roper /*
4898ddff9a60SMatt Roper * On platforms with HTI (aka HDPORT), if it's enabled at boot it may
4899ddff9a60SMatt Roper * have taken over some of the PHYs and made them unavailable to the
4900ddff9a60SMatt Roper * driver. In that case we should skip initializing the corresponding
4901ddff9a60SMatt Roper * outputs.
4902ddff9a60SMatt Roper */
49037d085bb1SJani Nikula if (intel_hti_uses_phy(display, phy)) {
4904ddff9a60SMatt Roper drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n",
4905ddff9a60SMatt Roper port_name(port), phy_name(phy));
4906ddff9a60SMatt Roper return;
4907ddff9a60SMatt Roper }
4908ddff9a60SMatt Roper
490945c0673aSJani Nikula init_hdmi = intel_bios_encoder_supports_dvi(devdata) ||
491045c0673aSJani Nikula intel_bios_encoder_supports_hdmi(devdata);
491145c0673aSJani Nikula init_dp = intel_bios_encoder_supports_dp(devdata);
4912379bc100SJani Nikula
4913db5d650fSVille Syrjälä if (intel_bios_encoder_is_lspcon(devdata)) {
4914379bc100SJani Nikula /*
4915379bc100SJani Nikula * Lspcon device needs to be driven with DP connector
4916379bc100SJani Nikula * with special detection sequence. So make sure DP
4917379bc100SJani Nikula * is initialized before lspcon.
4918379bc100SJani Nikula */
4919379bc100SJani Nikula init_dp = true;
4920379bc100SJani Nikula init_hdmi = false;
492147bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm, "VBT says port %c has lspcon\n",
492247bdb1caSJani Nikula port_name(port));
4923379bc100SJani Nikula }
4924379bc100SJani Nikula
4925379bc100SJani Nikula if (!init_dp && !init_hdmi) {
492647bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm,
492747bdb1caSJani Nikula "VBT says port %c is not DVI/HDMI/DP compatible, respect it\n",
4928379bc100SJani Nikula port_name(port));
4929379bc100SJani Nikula return;
4930379bc100SJani Nikula }
4931379bc100SJani Nikula
4932b4eb76d8SMatt Roper if (intel_phy_is_snps(dev_priv, phy) &&
49333a7e2d58SJani Nikula dev_priv->display.snps.phy_failed_calibration & BIT(phy)) {
4934b4eb76d8SMatt Roper drm_dbg_kms(&dev_priv->drm,
493582c362f2SLucas De Marchi "SNPS PHY %c failed to calibrate, proceeding anyway\n",
4936b4eb76d8SMatt Roper phy_name(phy));
4937b4eb76d8SMatt Roper }
4938b4eb76d8SMatt Roper
49397801f3b7SLucas De Marchi dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL);
49407801f3b7SLucas De Marchi if (!dig_port)
4941379bc100SJani Nikula return;
4942379bc100SJani Nikula
49434cca9676SVille Syrjälä dig_port->aux_ch = AUX_CH_NONE;
49444cca9676SVille Syrjälä
49457801f3b7SLucas De Marchi encoder = &dig_port->base;
4946c0a950d1SJani Nikula encoder->devdata = devdata;
4947379bc100SJani Nikula
4948ed2615a8SMatt Roper if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) {
4949ed2615a8SMatt Roper drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
4950ed2615a8SMatt Roper DRM_MODE_ENCODER_TMDS,
4951ed2615a8SMatt Roper "DDI %c/PHY %c",
4952ed2615a8SMatt Roper port_name(port - PORT_D_XELPD + PORT_D),
4953ed2615a8SMatt Roper phy_name(phy));
4954ed2615a8SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 12) {
49552d709a5aSVille Syrjälä enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
49562d709a5aSVille Syrjälä
495770dfbc29SLucas De Marchi drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
49582d709a5aSVille Syrjälä DRM_MODE_ENCODER_TMDS,
49592d709a5aSVille Syrjälä "DDI %s%c/PHY %s%c",
49602d709a5aSVille Syrjälä port >= PORT_TC1 ? "TC" : "",
496183566d13SVille Syrjälä port >= PORT_TC1 ? port_tc_name(port) : port_name(port),
49622d709a5aSVille Syrjälä tc_port != TC_PORT_NONE ? "TC" : "",
496383566d13SVille Syrjälä tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
4964005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 11) {
49652d709a5aSVille Syrjälä enum tc_port tc_port = intel_port_to_tc(dev_priv, port);
49662d709a5aSVille Syrjälä
49672d709a5aSVille Syrjälä drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
49682d709a5aSVille Syrjälä DRM_MODE_ENCODER_TMDS,
49692d709a5aSVille Syrjälä "DDI %c%s/PHY %s%c",
49702d709a5aSVille Syrjälä port_name(port),
49712d709a5aSVille Syrjälä port >= PORT_C ? " (TC)" : "",
49722d709a5aSVille Syrjälä tc_port != TC_PORT_NONE ? "TC" : "",
497383566d13SVille Syrjälä tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy));
49742d709a5aSVille Syrjälä } else {
49752d709a5aSVille Syrjälä drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs,
49762d709a5aSVille Syrjälä DRM_MODE_ENCODER_TMDS,
49772d709a5aSVille Syrjälä "DDI %c/PHY %c", port_name(port), phy_name(phy));
49782d709a5aSVille Syrjälä }
4979379bc100SJani Nikula
49803b3be899SImre Deak intel_encoder_link_check_init(encoder, intel_ddi_link_check);
49813b3be899SImre Deak
498236e5e704SSean Paul mutex_init(&dig_port->hdcp_mutex);
498336e5e704SSean Paul dig_port->num_hdcp_streams = 0;
498436e5e704SSean Paul
498570dfbc29SLucas De Marchi encoder->hotplug = intel_ddi_hotplug;
498670dfbc29SLucas De Marchi encoder->compute_output_type = intel_ddi_compute_output_type;
498770dfbc29SLucas De Marchi encoder->compute_config = intel_ddi_compute_config;
4988b50a1aa6SManasi Navare encoder->compute_config_late = intel_ddi_compute_config_late;
498970dfbc29SLucas De Marchi encoder->enable = intel_enable_ddi;
499070dfbc29SLucas De Marchi encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
499170dfbc29SLucas De Marchi encoder->pre_enable = intel_ddi_pre_enable;
499270dfbc29SLucas De Marchi encoder->disable = intel_disable_ddi;
4993b108bdd0SImre Deak encoder->post_pll_disable = intel_ddi_post_pll_disable;
499470dfbc29SLucas De Marchi encoder->post_disable = intel_ddi_post_disable;
499570dfbc29SLucas De Marchi encoder->update_pipe = intel_ddi_update_pipe;
49963654a48aSVille Syrjälä encoder->audio_enable = intel_audio_codec_enable;
49973654a48aSVille Syrjälä encoder->audio_disable = intel_audio_codec_disable;
499870dfbc29SLucas De Marchi encoder->get_hw_state = intel_ddi_get_hw_state;
4999f9e76a6eSImre Deak encoder->sync_state = intel_ddi_sync_state;
5000b671d6efSImre Deak encoder->initial_fastset_check = intel_ddi_initial_fastset_check;
5001151ec347SImre Deak encoder->suspend = intel_ddi_encoder_suspend;
5002151ec347SImre Deak encoder->shutdown = intel_ddi_encoder_shutdown;
500370dfbc29SLucas De Marchi encoder->get_power_domains = intel_ddi_get_power_domains;
500470dfbc29SLucas De Marchi
500570dfbc29SLucas De Marchi encoder->type = INTEL_OUTPUT_DDI;
5006979e1b32SImre Deak encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port);
500770dfbc29SLucas De Marchi encoder->port = port;
500870dfbc29SLucas De Marchi encoder->cloneable = 0;
500970dfbc29SLucas De Marchi encoder->pipe_mask = ~0;
5010da51e4baSVille Syrjälä
501151390cc0SRadhakrishna Sripada if (DISPLAY_VER(dev_priv) >= 14) {
501273fc3abcSMika Kahola encoder->enable_clock = intel_mtl_pll_enable;
501373fc3abcSMika Kahola encoder->disable_clock = intel_mtl_pll_disable;
50146f0423b0SMika Kahola encoder->port_pll_type = intel_mtl_port_pll_type;
501551390cc0SRadhakrishna Sripada encoder->get_config = mtl_ddi_get_config;
501651390cc0SRadhakrishna Sripada } else if (IS_DG2(dev_priv)) {
5017f82f2563SMatt Roper encoder->enable_clock = intel_mpllb_enable;
5018f82f2563SMatt Roper encoder->disable_clock = intel_mpllb_disable;
5019865b73eaSMatt Roper encoder->get_config = dg2_ddi_get_config;
5020865b73eaSMatt Roper } else if (IS_ALDERLAKE_S(dev_priv)) {
502140b316d4SVille Syrjälä encoder->enable_clock = adls_ddi_enable_clock;
502240b316d4SVille Syrjälä encoder->disable_clock = adls_ddi_disable_clock;
50230fbd8694SVille Syrjälä encoder->is_clock_enabled = adls_ddi_is_clock_enabled;
5024351221ffSVille Syrjälä encoder->get_config = adls_ddi_get_config;
502540b316d4SVille Syrjälä } else if (IS_ROCKETLAKE(dev_priv)) {
502640b316d4SVille Syrjälä encoder->enable_clock = rkl_ddi_enable_clock;
502740b316d4SVille Syrjälä encoder->disable_clock = rkl_ddi_disable_clock;
50280fbd8694SVille Syrjälä encoder->is_clock_enabled = rkl_ddi_is_clock_enabled;
5029351221ffSVille Syrjälä encoder->get_config = rkl_ddi_get_config;
503036ecb0ecSVille Syrjälä } else if (IS_DG1(dev_priv)) {
503135bb6b1aSVille Syrjälä encoder->enable_clock = dg1_ddi_enable_clock;
503235bb6b1aSVille Syrjälä encoder->disable_clock = dg1_ddi_disable_clock;
50330fbd8694SVille Syrjälä encoder->is_clock_enabled = dg1_ddi_is_clock_enabled;
5034351221ffSVille Syrjälä encoder->get_config = dg1_ddi_get_config;
50350c65dc06SDnyaneshwar Bhadane } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) {
503636ecb0ecSVille Syrjälä if (intel_ddi_is_tc(dev_priv, port)) {
503736ecb0ecSVille Syrjälä encoder->enable_clock = jsl_ddi_tc_enable_clock;
503836ecb0ecSVille Syrjälä encoder->disable_clock = jsl_ddi_tc_disable_clock;
50390fbd8694SVille Syrjälä encoder->is_clock_enabled = jsl_ddi_tc_is_clock_enabled;
50407c1da068SImre Deak encoder->port_pll_type = icl_ddi_tc_port_pll_type;
5041351221ffSVille Syrjälä encoder->get_config = icl_ddi_combo_get_config;
504236ecb0ecSVille Syrjälä } else {
504336ecb0ecSVille Syrjälä encoder->enable_clock = icl_ddi_combo_enable_clock;
504436ecb0ecSVille Syrjälä encoder->disable_clock = icl_ddi_combo_disable_clock;
50450fbd8694SVille Syrjälä encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
5046351221ffSVille Syrjälä encoder->get_config = icl_ddi_combo_get_config;
504736ecb0ecSVille Syrjälä }
5048005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 11) {
504936ecb0ecSVille Syrjälä if (intel_ddi_is_tc(dev_priv, port)) {
505036ecb0ecSVille Syrjälä encoder->enable_clock = icl_ddi_tc_enable_clock;
505136ecb0ecSVille Syrjälä encoder->disable_clock = icl_ddi_tc_disable_clock;
50520fbd8694SVille Syrjälä encoder->is_clock_enabled = icl_ddi_tc_is_clock_enabled;
50537c1da068SImre Deak encoder->port_pll_type = icl_ddi_tc_port_pll_type;
5054351221ffSVille Syrjälä encoder->get_config = icl_ddi_tc_get_config;
505536ecb0ecSVille Syrjälä } else {
505636ecb0ecSVille Syrjälä encoder->enable_clock = icl_ddi_combo_enable_clock;
505736ecb0ecSVille Syrjälä encoder->disable_clock = icl_ddi_combo_disable_clock;
50580fbd8694SVille Syrjälä encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled;
5059351221ffSVille Syrjälä encoder->get_config = icl_ddi_combo_get_config;
506036ecb0ecSVille Syrjälä }
50612446e1d6SMatt Roper } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
5062351221ffSVille Syrjälä /* BXT/GLK have fixed PLL->port mapping */
5063351221ffSVille Syrjälä encoder->get_config = bxt_ddi_get_config;
506493e7e61eSLucas De Marchi } else if (DISPLAY_VER(dev_priv) == 9) {
506538e31f1aSVille Syrjälä encoder->enable_clock = skl_ddi_enable_clock;
506638e31f1aSVille Syrjälä encoder->disable_clock = skl_ddi_disable_clock;
50670fbd8694SVille Syrjälä encoder->is_clock_enabled = skl_ddi_is_clock_enabled;
5068351221ffSVille Syrjälä encoder->get_config = skl_ddi_get_config;
506938e31f1aSVille Syrjälä } else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) {
5070d135368dSVille Syrjälä encoder->enable_clock = hsw_ddi_enable_clock;
5071d135368dSVille Syrjälä encoder->disable_clock = hsw_ddi_disable_clock;
50720fbd8694SVille Syrjälä encoder->is_clock_enabled = hsw_ddi_is_clock_enabled;
5073351221ffSVille Syrjälä encoder->get_config = hsw_ddi_get_config;
5074d135368dSVille Syrjälä }
5075d135368dSVille Syrjälä
5076ea8af87aSMika Kahola if (DISPLAY_VER(dev_priv) >= 14) {
5077ea8af87aSMika Kahola encoder->set_signal_levels = intel_cx0_phy_set_signal_levels;
5078ea8af87aSMika Kahola } else if (IS_DG2(dev_priv)) {
5079193299adSVille Syrjälä encoder->set_signal_levels = intel_snps_phy_set_signal_levels;
5080193299adSVille Syrjälä } else if (DISPLAY_VER(dev_priv) >= 12) {
50817fcf7558SJani Nikula if (intel_encoder_is_combo(encoder))
5082193299adSVille Syrjälä encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
5083e722ab8bSVille Syrjälä else
5084193299adSVille Syrjälä encoder->set_signal_levels = tgl_dkl_phy_set_signal_levels;
5085193299adSVille Syrjälä } else if (DISPLAY_VER(dev_priv) >= 11) {
50867fcf7558SJani Nikula if (intel_encoder_is_combo(encoder))
5087193299adSVille Syrjälä encoder->set_signal_levels = icl_combo_phy_set_signal_levels;
5088193299adSVille Syrjälä else
5089193299adSVille Syrjälä encoder->set_signal_levels = icl_mg_phy_set_signal_levels;
5090193299adSVille Syrjälä } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
5091ba07c3edSVille Syrjälä encoder->set_signal_levels = bxt_dpio_phy_set_signal_levels;
5092193299adSVille Syrjälä } else {
5093e722ab8bSVille Syrjälä encoder->set_signal_levels = hsw_set_signal_levels;
5094193299adSVille Syrjälä }
5095e722ab8bSVille Syrjälä
5096c40a253bSVille Syrjälä intel_ddi_buf_trans_init(encoder);
5097c40a253bSVille Syrjälä
5098ed2615a8SMatt Roper if (DISPLAY_VER(dev_priv) >= 13)
5099ed2615a8SMatt Roper encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port);
5100ed2615a8SMatt Roper else if (IS_DG1(dev_priv))
5101229f31e2SLucas De Marchi encoder->hpd_pin = dg1_hpd_pin(dev_priv, port);
5102229f31e2SLucas De Marchi else if (IS_ROCKETLAKE(dev_priv))
5103da51e4baSVille Syrjälä encoder->hpd_pin = rkl_hpd_pin(dev_priv, port);
5104005e9537SMatt Roper else if (DISPLAY_VER(dev_priv) >= 12)
5105da51e4baSVille Syrjälä encoder->hpd_pin = tgl_hpd_pin(dev_priv, port);
51060c65dc06SDnyaneshwar Bhadane else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv))
5107da51e4baSVille Syrjälä encoder->hpd_pin = ehl_hpd_pin(dev_priv, port);
510893e7e61eSLucas De Marchi else if (DISPLAY_VER(dev_priv) == 11)
5109da51e4baSVille Syrjälä encoder->hpd_pin = icl_hpd_pin(dev_priv, port);
511093e7e61eSLucas De Marchi else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv))
5111c8455098SLyude Paul encoder->hpd_pin = skl_hpd_pin(dev_priv, port);
5112da51e4baSVille Syrjälä else
511303c7e4f1SVille Syrjälä encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
5114379bc100SJani Nikula
5115005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11)
51167801f3b7SLucas De Marchi dig_port->saved_port_bits =
51177801f3b7SLucas De Marchi intel_de_read(dev_priv, DDI_BUF_CTL(port))
51187801f3b7SLucas De Marchi & DDI_BUF_PORT_REVERSAL;
5119379bc100SJani Nikula else
51207801f3b7SLucas De Marchi dig_port->saved_port_bits =
51217801f3b7SLucas De Marchi intel_de_read(dev_priv, DDI_BUF_CTL(port))
51227801f3b7SLucas De Marchi & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES);
512370dfbc29SLucas De Marchi
51245f42196dSVille Syrjälä if (intel_bios_encoder_lane_reversal(devdata))
5125aaab24bbSUma Shankar dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL;
5126aaab24bbSUma Shankar
51277801f3b7SLucas De Marchi dig_port->dp.output_reg = INVALID_MMIO_REG;
51287801f3b7SLucas De Marchi dig_port->max_lanes = intel_ddi_max_lanes(dig_port);
51299856308cSVille Syrjälä
5130b8a13e87SVille Syrjälä if (need_aux_ch(encoder, init_dp)) {
5131bb45217fSVille Syrjälä dig_port->aux_ch = intel_dp_aux_ch(encoder);
5132b8a13e87SVille Syrjälä if (dig_port->aux_ch == AUX_CH_NONE)
5133b8a13e87SVille Syrjälä goto err;
5134b8a13e87SVille Syrjälä }
5135379bc100SJani Nikula
51367fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) {
5137c5faae5aSJani Nikula bool is_legacy =
5138f08fbe6aSJani Nikula !intel_bios_encoder_supports_typec_usb(devdata) &&
5139f08fbe6aSJani Nikula !intel_bios_encoder_supports_tbt(devdata);
5140379bc100SJani Nikula
514140a55b84SImre Deak if (!is_legacy && init_hdmi) {
514240a55b84SImre Deak is_legacy = !init_dp;
514340a55b84SImre Deak
514440a55b84SImre Deak drm_dbg_kms(&dev_priv->drm,
514540a55b84SImre Deak "VBT says port %c is non-legacy TC and has HDMI (with DP: %s), assume it's %s\n",
514640a55b84SImre Deak port_name(port),
514740a55b84SImre Deak str_yes_no(init_dp),
514840a55b84SImre Deak is_legacy ? "legacy" : "non-legacy");
514940a55b84SImre Deak }
515040a55b84SImre Deak
5151b61fad5fSImre Deak encoder->suspend_complete = intel_ddi_tc_encoder_suspend_complete;
5152b61fad5fSImre Deak encoder->shutdown_complete = intel_ddi_tc_encoder_shutdown_complete;
5153b61fad5fSImre Deak
51549210e94aSImre Deak dig_port->lock = intel_tc_port_lock;
51559210e94aSImre Deak dig_port->unlock = intel_tc_port_unlock;
51569210e94aSImre Deak
5157c5879999SImre Deak if (intel_tc_port_init(dig_port, is_legacy) < 0)
5158c5879999SImre Deak goto err;
5159ab7bc4e1SImre Deak }
5160ab7bc4e1SImre Deak
51611de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, port > PORT_I);
5162979e1b32SImre Deak dig_port->ddi_io_power_domain = intel_display_power_ddi_io_domain(dev_priv, port);
5163379bc100SJani Nikula
5164005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) {
51657fcf7558SJani Nikula if (intel_encoder_is_tc(encoder))
51667801f3b7SLucas De Marchi dig_port->connected = intel_tc_port_connected;
5167edc0e09cSVille Syrjälä else
51687801f3b7SLucas De Marchi dig_port->connected = lpt_digital_port_connected;
5169dded35acSVille Syrjälä } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) {
5170dded35acSVille Syrjälä dig_port->connected = bdw_digital_port_connected;
5171dded35acSVille Syrjälä } else if (DISPLAY_VER(dev_priv) == 9) {
5172dded35acSVille Syrjälä dig_port->connected = lpt_digital_port_connected;
5173dded35acSVille Syrjälä } else if (IS_BROADWELL(dev_priv)) {
5174dded35acSVille Syrjälä if (port == PORT_A)
51757801f3b7SLucas De Marchi dig_port->connected = bdw_digital_port_connected;
5176edc0e09cSVille Syrjälä else
51777801f3b7SLucas De Marchi dig_port->connected = lpt_digital_port_connected;
5178dded35acSVille Syrjälä } else if (IS_HASWELL(dev_priv)) {
5179c7e8a3d6SVille Syrjälä if (port == PORT_A)
51807801f3b7SLucas De Marchi dig_port->connected = hsw_digital_port_connected;
5181edc0e09cSVille Syrjälä else
51827801f3b7SLucas De Marchi dig_port->connected = lpt_digital_port_connected;
5183edc0e09cSVille Syrjälä }
5184edc0e09cSVille Syrjälä
51857801f3b7SLucas De Marchi intel_infoframe_init(dig_port);
5186379bc100SJani Nikula
5187a98ffd6eSVille Syrjälä if (init_dp) {
5188a98ffd6eSVille Syrjälä if (!intel_ddi_init_dp_connector(dig_port))
5189a98ffd6eSVille Syrjälä goto err;
5190a98ffd6eSVille Syrjälä
5191a98ffd6eSVille Syrjälä dig_port->hpd_pulse = intel_dp_hpd_pulse;
5192a98ffd6eSVille Syrjälä
5193a98ffd6eSVille Syrjälä if (dig_port->dp.mso_link_count)
5194a98ffd6eSVille Syrjälä encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv);
5195a98ffd6eSVille Syrjälä }
5196a98ffd6eSVille Syrjälä
5197a98ffd6eSVille Syrjälä /*
5198a98ffd6eSVille Syrjälä * In theory we don't need the encoder->type check,
5199a98ffd6eSVille Syrjälä * but leave it just in case we have some really bad VBTs...
5200a98ffd6eSVille Syrjälä */
5201a98ffd6eSVille Syrjälä if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) {
5202a98ffd6eSVille Syrjälä if (!intel_ddi_init_hdmi_connector(dig_port))
5203a98ffd6eSVille Syrjälä goto err;
5204a98ffd6eSVille Syrjälä }
5205a98ffd6eSVille Syrjälä
5206379bc100SJani Nikula return;
5207379bc100SJani Nikula
5208379bc100SJani Nikula err:
520970dfbc29SLucas De Marchi drm_encoder_cleanup(&encoder->base);
52107801f3b7SLucas De Marchi kfree(dig_port);
5211379bc100SJani Nikula }
5212