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 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 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ä 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 919f645cbdaSImre Deak if (intel_encoder_can_psr(&dig_port->base)) 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 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 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 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 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 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 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 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 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 */ 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 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ä 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 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 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 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 1400a621860aSVille Syrjälä static int translate_signal_level(struct intel_dp *intel_dp, 1401a621860aSVille Syrjälä u8 signal_levels) 1402379bc100SJani Nikula { 14038b4f2137SPankaj Bharadiya struct drm_i915_private *i915 = dp_to_i915(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 14118b4f2137SPankaj Bharadiya drm_WARN(&i915->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 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 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 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 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ä 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ä 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 * 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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 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ä 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ä 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ä 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 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 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ä 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ä 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 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ä 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ä 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ä 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 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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ä 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 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 20997fcf7558SJani Nikula if (!intel_encoder_is_tc(&dig_port->base) || 210011a89708SImre Deak intel_tc_port_in_tbt_alt_mode(dig_port)) 2101379bc100SJani Nikula return; 2102379bc100SJani Nikula 2103005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 2104b8ed5533SImre Deak ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0)); 2105b8ed5533SImre Deak ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1)); 2106978c3e53SClinton A Taylor } else { 2107f7960e7fSJani Nikula ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port)); 2108f7960e7fSJani Nikula ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port)); 2109978c3e53SClinton A Taylor } 2110379bc100SJani Nikula 21114f72a8eeSKhaled Almahallawy ln0 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE); 2112379bc100SJani Nikula ln1 &= ~(MG_DP_MODE_CFG_DP_X1_MODE | MG_DP_MODE_CFG_DP_X2_MODE); 2113379bc100SJani Nikula 21143b51be4eSClinton A Taylor /* DPPATC */ 21157801f3b7SLucas De Marchi pin_assignment = intel_tc_port_get_pin_assignment_mask(dig_port); 21163b51be4eSClinton A Taylor width = crtc_state->lane_count; 2117379bc100SJani Nikula 21183b51be4eSClinton A Taylor switch (pin_assignment) { 21193b51be4eSClinton A Taylor case 0x0: 21201de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, 212111a89708SImre Deak !intel_tc_port_in_legacy_mode(dig_port)); 21223b51be4eSClinton A Taylor if (width == 1) { 2123379bc100SJani Nikula ln1 |= MG_DP_MODE_CFG_DP_X1_MODE; 21243b51be4eSClinton A Taylor } else { 21253b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE; 21263b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE; 2127379bc100SJani Nikula } 2128379bc100SJani Nikula break; 21293b51be4eSClinton A Taylor case 0x1: 21303b51be4eSClinton A Taylor if (width == 4) { 21313b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE; 21323b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE; 21333b51be4eSClinton A Taylor } 2134379bc100SJani Nikula break; 21353b51be4eSClinton A Taylor case 0x2: 21363b51be4eSClinton A Taylor if (width == 2) { 21373b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE; 21383b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE; 21393b51be4eSClinton A Taylor } 21403b51be4eSClinton A Taylor break; 21413b51be4eSClinton A Taylor case 0x3: 21423b51be4eSClinton A Taylor case 0x5: 21433b51be4eSClinton A Taylor if (width == 1) { 21443b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X1_MODE; 21453b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X1_MODE; 21463b51be4eSClinton A Taylor } else { 21473b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE; 21483b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE; 21493b51be4eSClinton A Taylor } 21503b51be4eSClinton A Taylor break; 21513b51be4eSClinton A Taylor case 0x4: 21523b51be4eSClinton A Taylor case 0x6: 21533b51be4eSClinton A Taylor if (width == 1) { 21543b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X1_MODE; 21553b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X1_MODE; 21563b51be4eSClinton A Taylor } else { 21573b51be4eSClinton A Taylor ln0 |= MG_DP_MODE_CFG_DP_X2_MODE; 21583b51be4eSClinton A Taylor ln1 |= MG_DP_MODE_CFG_DP_X2_MODE; 21593b51be4eSClinton A Taylor } 21603b51be4eSClinton A Taylor break; 2161379bc100SJani Nikula default: 21623b51be4eSClinton A Taylor MISSING_CASE(pin_assignment); 2163379bc100SJani Nikula } 2164379bc100SJani Nikula 2165005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 2166b8ed5533SImre Deak intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0); 2167b8ed5533SImre Deak intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1); 2168978c3e53SClinton A Taylor } else { 2169f7960e7fSJani Nikula intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0); 2170f7960e7fSJani Nikula intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1); 2171379bc100SJani Nikula } 2172978c3e53SClinton A Taylor } 2173379bc100SJani Nikula 2174ef79fafeSVille Syrjälä static enum transcoder 2175ef79fafeSVille Syrjälä tgl_dp_tp_transcoder(const struct intel_crtc_state *crtc_state) 2176ef79fafeSVille Syrjälä { 2177ef79fafeSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) 2178ef79fafeSVille Syrjälä return crtc_state->mst_master_transcoder; 2179ef79fafeSVille Syrjälä else 2180ef79fafeSVille Syrjälä return crtc_state->cpu_transcoder; 2181ef79fafeSVille Syrjälä } 2182ef79fafeSVille Syrjälä 2183ef79fafeSVille Syrjälä i915_reg_t dp_tp_ctl_reg(struct intel_encoder *encoder, 2184ef79fafeSVille Syrjälä const struct intel_crtc_state *crtc_state) 2185ef79fafeSVille Syrjälä { 2186ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2187ef79fafeSVille Syrjälä 2188005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 21893cd5a36dSJani Nikula return TGL_DP_TP_CTL(dev_priv, 21903cd5a36dSJani Nikula tgl_dp_tp_transcoder(crtc_state)); 2191ef79fafeSVille Syrjälä else 2192ef79fafeSVille Syrjälä return DP_TP_CTL(encoder->port); 2193ef79fafeSVille Syrjälä } 2194ef79fafeSVille Syrjälä 2195ef79fafeSVille Syrjälä i915_reg_t dp_tp_status_reg(struct intel_encoder *encoder, 2196ef79fafeSVille Syrjälä const struct intel_crtc_state *crtc_state) 2197ef79fafeSVille Syrjälä { 2198ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2199ef79fafeSVille Syrjälä 2200005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 2201b11bf614SJani Nikula return TGL_DP_TP_STATUS(dev_priv, 2202b11bf614SJani Nikula tgl_dp_tp_transcoder(crtc_state)); 2203ef79fafeSVille Syrjälä else 2204ef79fafeSVille Syrjälä return DP_TP_STATUS(encoder->port); 2205ef79fafeSVille Syrjälä } 2206ef79fafeSVille Syrjälä 22071639406aSManasi Navare static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel_dp, 22081639406aSManasi Navare const struct intel_crtc_state *crtc_state, 22091639406aSManasi Navare bool enable) 22101639406aSManasi Navare { 22111639406aSManasi Navare struct drm_i915_private *i915 = dp_to_i915(intel_dp); 22121639406aSManasi Navare 22131639406aSManasi Navare if (!crtc_state->vrr.enable) 22141639406aSManasi Navare return; 22151639406aSManasi Navare 22161639406aSManasi Navare if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL, 22171639406aSManasi Navare enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0) 22181639406aSManasi Navare drm_dbg_kms(&i915->drm, 22190868b1ceSVille Syrjälä "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n", 2220707c3a7dSLucas De Marchi str_enable_disable(enable)); 22211639406aSManasi Navare } 22221639406aSManasi Navare 2223379bc100SJani Nikula static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, 22248ab5a036SImre Deak const struct intel_crtc_state *crtc_state, 22258ab5a036SImre Deak bool enable) 2226379bc100SJani Nikula { 222747bdb1caSJani Nikula struct drm_i915_private *i915 = dp_to_i915(intel_dp); 222847bdb1caSJani Nikula 2229379bc100SJani Nikula if (!crtc_state->fec_enable) 2230379bc100SJani Nikula return; 2231379bc100SJani Nikula 22328ab5a036SImre Deak if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION, 22338ab5a036SImre Deak enable ? DP_FEC_READY : 0) <= 0) 22348ab5a036SImre Deak drm_dbg_kms(&i915->drm, "Failed to set FEC_READY to %s in the sink\n", 22358ab5a036SImre Deak enable ? "enabled" : "disabled"); 22366e916b35SImre Deak 22378ab5a036SImre Deak if (enable && 22388ab5a036SImre Deak drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_STATUS, 22396e916b35SImre Deak DP_FEC_DECODE_EN_DETECTED | DP_FEC_DECODE_DIS_DETECTED) <= 0) 22406e916b35SImre Deak drm_dbg_kms(&i915->drm, "Failed to clear FEC detected flags\n"); 22416e916b35SImre Deak } 22426e916b35SImre Deak 22436e916b35SImre Deak static int read_fec_detected_status(struct drm_dp_aux *aux) 22446e916b35SImre Deak { 22456e916b35SImre Deak int ret; 22466e916b35SImre Deak u8 status; 22476e916b35SImre Deak 22486e916b35SImre Deak ret = drm_dp_dpcd_readb(aux, DP_FEC_STATUS, &status); 22496e916b35SImre Deak if (ret < 0) 22506e916b35SImre Deak return ret; 22516e916b35SImre Deak 22526e916b35SImre Deak return status; 22536e916b35SImre Deak } 22546e916b35SImre Deak 22556e916b35SImre Deak static void wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled) 22566e916b35SImre Deak { 22576e916b35SImre Deak struct drm_i915_private *i915 = to_i915(aux->drm_dev); 22586e916b35SImre Deak int mask = enabled ? DP_FEC_DECODE_EN_DETECTED : DP_FEC_DECODE_DIS_DETECTED; 22596e916b35SImre Deak int status; 22606e916b35SImre Deak int err; 22616e916b35SImre Deak 22626e916b35SImre Deak err = readx_poll_timeout(read_fec_detected_status, aux, status, 22636e916b35SImre Deak status & mask || status < 0, 22646e916b35SImre Deak 10000, 200000); 22656e916b35SImre Deak 22666e916b35SImre Deak if (!err && status >= 0) 22676e916b35SImre Deak return; 22686e916b35SImre Deak 22696e916b35SImre Deak if (err == -ETIMEDOUT) 2270dd99d5b1SImre Deak drm_dbg_kms(&i915->drm, "Timeout waiting for FEC %s to get detected\n", 22716e916b35SImre Deak str_enabled_disabled(enabled)); 22726e916b35SImre Deak else 22736e916b35SImre Deak drm_dbg_kms(&i915->drm, "FEC detected status read error: %d\n", status); 22746e916b35SImre Deak } 22756e916b35SImre Deak 22766e916b35SImre Deak void intel_ddi_wait_for_fec_status(struct intel_encoder *encoder, 22776e916b35SImre Deak const struct intel_crtc_state *crtc_state, 22786e916b35SImre Deak bool enabled) 22796e916b35SImre Deak { 22806e916b35SImre Deak struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 22816e916b35SImre Deak struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 22826e916b35SImre Deak int ret; 22836e916b35SImre Deak 22846e916b35SImre Deak if (!crtc_state->fec_enable) 22856e916b35SImre Deak return; 22866e916b35SImre Deak 22876e916b35SImre Deak if (enabled) 22886e916b35SImre Deak ret = intel_de_wait_for_set(i915, dp_tp_status_reg(encoder, crtc_state), 22896e916b35SImre Deak DP_TP_STATUS_FEC_ENABLE_LIVE, 1); 22906e916b35SImre Deak else 22916e916b35SImre Deak ret = intel_de_wait_for_clear(i915, dp_tp_status_reg(encoder, crtc_state), 22926e916b35SImre Deak DP_TP_STATUS_FEC_ENABLE_LIVE, 1); 22936e916b35SImre Deak 22946e916b35SImre Deak if (ret) 22956e916b35SImre Deak drm_err(&i915->drm, 22966e916b35SImre Deak "Timeout waiting for FEC live state to get %s\n", 22976e916b35SImre Deak str_enabled_disabled(enabled)); 22986e916b35SImre Deak 22996e916b35SImre Deak /* 23006e916b35SImre Deak * At least the Synoptics MST hub doesn't set the detected flag for 23016e916b35SImre Deak * FEC decoding disabling so skip waiting for that. 23026e916b35SImre Deak */ 23036e916b35SImre Deak if (enabled) 23046e916b35SImre Deak wait_for_fec_detected(&intel_dp->aux, enabled); 2305379bc100SJani Nikula } 2306379bc100SJani Nikula 2307379bc100SJani Nikula static void intel_ddi_enable_fec(struct intel_encoder *encoder, 2308379bc100SJani Nikula const struct intel_crtc_state *crtc_state) 2309379bc100SJani Nikula { 2310379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2311379bc100SJani Nikula 2312379bc100SJani Nikula if (!crtc_state->fec_enable) 2313379bc100SJani Nikula return; 2314379bc100SJani Nikula 23158910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), 23168910d8b7SAndrzej Hajda 0, DP_TP_CTL_FEC_ENABLE); 2317379bc100SJani Nikula } 2318379bc100SJani Nikula 23190cfdf662SImre Deak static void intel_ddi_disable_fec(struct intel_encoder *encoder, 2320379bc100SJani Nikula const struct intel_crtc_state *crtc_state) 2321379bc100SJani Nikula { 2322379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2323379bc100SJani Nikula 2324379bc100SJani Nikula if (!crtc_state->fec_enable) 2325379bc100SJani Nikula return; 2326379bc100SJani Nikula 23278910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), 23288910d8b7SAndrzej Hajda DP_TP_CTL_FEC_ENABLE, 0); 2329ef79fafeSVille Syrjälä intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 2330379bc100SJani Nikula } 2331379bc100SJani Nikula 23325cdf706fSVille Syrjälä static void intel_ddi_power_up_lanes(struct intel_encoder *encoder, 23335cdf706fSVille Syrjälä const struct intel_crtc_state *crtc_state) 23345cdf706fSVille Syrjälä { 23355cdf706fSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 23365cdf706fSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 23375cdf706fSVille Syrjälä 23387fcf7558SJani Nikula if (intel_encoder_is_combo(encoder)) { 23397fcf7558SJani Nikula enum phy phy = intel_encoder_to_phy(encoder); 23405cdf706fSVille Syrjälä bool lane_reversal = 23415cdf706fSVille Syrjälä dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL; 23425cdf706fSVille Syrjälä 23435cdf706fSVille Syrjälä intel_combo_phy_power_up_lanes(i915, phy, false, 23445cdf706fSVille Syrjälä crtc_state->lane_count, 23455cdf706fSVille Syrjälä lane_reversal); 23465cdf706fSVille Syrjälä } 23475cdf706fSVille Syrjälä } 23485cdf706fSVille Syrjälä 2349a3f610ddSLuca Coelho /* 2350a3f610ddSLuca Coelho * Splitter enable for eDP MSO is limited to certain pipes, on certain 2351a3f610ddSLuca Coelho * platforms. 2352a3f610ddSLuca Coelho */ 2353f6864b27SJani Nikula static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915) 2354f6864b27SJani Nikula { 2355a3f610ddSLuca Coelho if (DISPLAY_VER(i915) > 20) 2356a3f610ddSLuca Coelho return ~0; 2357a3f610ddSLuca Coelho else if (IS_ALDERLAKE_P(i915)) 2358f6864b27SJani Nikula return BIT(PIPE_A) | BIT(PIPE_B); 2359f6864b27SJani Nikula else 2360f6864b27SJani Nikula return BIT(PIPE_A); 2361f6864b27SJani Nikula } 2362f6864b27SJani Nikula 23635b616a29SJani Nikula static void intel_ddi_mso_get_config(struct intel_encoder *encoder, 23645b616a29SJani Nikula struct intel_crtc_state *pipe_config) 23655b616a29SJani Nikula { 23665b616a29SJani Nikula struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); 23675b616a29SJani Nikula struct drm_i915_private *i915 = to_i915(crtc->base.dev); 23685b616a29SJani Nikula enum pipe pipe = crtc->pipe; 23695b616a29SJani Nikula u32 dss1; 23705b616a29SJani Nikula 23715b616a29SJani Nikula if (!HAS_MSO(i915)) 23725b616a29SJani Nikula return; 23735b616a29SJani Nikula 23745b616a29SJani Nikula dss1 = intel_de_read(i915, ICL_PIPE_DSS_CTL1(pipe)); 23755b616a29SJani Nikula 23765b616a29SJani Nikula pipe_config->splitter.enable = dss1 & SPLITTER_ENABLE; 23775b616a29SJani Nikula if (!pipe_config->splitter.enable) 23785b616a29SJani Nikula return; 23795b616a29SJani Nikula 2380f6864b27SJani Nikula if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) { 23815b616a29SJani Nikula pipe_config->splitter.enable = false; 23825b616a29SJani Nikula return; 23835b616a29SJani Nikula } 23845b616a29SJani Nikula 23855b616a29SJani Nikula switch (dss1 & SPLITTER_CONFIGURATION_MASK) { 23865b616a29SJani Nikula default: 23875b616a29SJani Nikula drm_WARN(&i915->drm, true, 23885b616a29SJani Nikula "Invalid splitter configuration, dss1=0x%08x\n", dss1); 23895b616a29SJani Nikula fallthrough; 23905b616a29SJani Nikula case SPLITTER_CONFIGURATION_2_SEGMENT: 23915b616a29SJani Nikula pipe_config->splitter.link_count = 2; 23925b616a29SJani Nikula break; 23935b616a29SJani Nikula case SPLITTER_CONFIGURATION_4_SEGMENT: 23945b616a29SJani Nikula pipe_config->splitter.link_count = 4; 23955b616a29SJani Nikula break; 23965b616a29SJani Nikula } 23975b616a29SJani Nikula 23985b616a29SJani Nikula pipe_config->splitter.pixel_overlap = REG_FIELD_GET(OVERLAP_PIXELS_MASK, dss1); 23995b616a29SJani Nikula } 24005b616a29SJani Nikula 2401bc71194eSJani Nikula static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state) 2402bc71194eSJani Nikula { 2403bc71194eSJani Nikula struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2404bc71194eSJani Nikula struct drm_i915_private *i915 = to_i915(crtc->base.dev); 2405bc71194eSJani Nikula enum pipe pipe = crtc->pipe; 2406bc71194eSJani Nikula u32 dss1 = 0; 2407bc71194eSJani Nikula 2408bc71194eSJani Nikula if (!HAS_MSO(i915)) 2409bc71194eSJani Nikula return; 2410bc71194eSJani Nikula 2411bc71194eSJani Nikula if (crtc_state->splitter.enable) { 2412bc71194eSJani Nikula dss1 |= SPLITTER_ENABLE; 2413bc71194eSJani Nikula dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap); 2414bc71194eSJani Nikula if (crtc_state->splitter.link_count == 2) 2415bc71194eSJani Nikula dss1 |= SPLITTER_CONFIGURATION_2_SEGMENT; 2416bc71194eSJani Nikula else 2417bc71194eSJani Nikula dss1 |= SPLITTER_CONFIGURATION_4_SEGMENT; 2418bc71194eSJani Nikula } 2419bc71194eSJani Nikula 2420bc71194eSJani Nikula intel_de_rmw(i915, ICL_PIPE_DSS_CTL1(pipe), 2421bc71194eSJani Nikula SPLITTER_ENABLE | SPLITTER_CONFIGURATION_MASK | 2422bc71194eSJani Nikula OVERLAP_PIXELS_MASK, dss1); 2423bc71194eSJani Nikula } 2424bc71194eSJani Nikula 242523ef6194SJosé Roberto de Souza static u8 mtl_get_port_width(u8 lane_count) 242623ef6194SJosé Roberto de Souza { 242723ef6194SJosé Roberto de Souza switch (lane_count) { 242823ef6194SJosé Roberto de Souza case 1: 242923ef6194SJosé Roberto de Souza return 0; 243023ef6194SJosé Roberto de Souza case 2: 243123ef6194SJosé Roberto de Souza return 1; 243223ef6194SJosé Roberto de Souza case 3: 243323ef6194SJosé Roberto de Souza return 4; 243423ef6194SJosé Roberto de Souza case 4: 243523ef6194SJosé Roberto de Souza return 3; 243623ef6194SJosé Roberto de Souza default: 243723ef6194SJosé Roberto de Souza MISSING_CASE(lane_count); 243823ef6194SJosé Roberto de Souza return 4; 243923ef6194SJosé Roberto de Souza } 244023ef6194SJosé Roberto de Souza } 244123ef6194SJosé Roberto de Souza 244223ef6194SJosé Roberto de Souza static void 244323ef6194SJosé Roberto de Souza mtl_ddi_enable_d2d(struct intel_encoder *encoder) 244423ef6194SJosé Roberto de Souza { 244523ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 244623ef6194SJosé Roberto de Souza enum port port = encoder->port; 2447d5c7854bSLucas De Marchi i915_reg_t reg; 2448d5c7854bSLucas De Marchi u32 set_bits, wait_bits; 244923ef6194SJosé Roberto de Souza 2450d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20) { 2451d5c7854bSLucas De Marchi reg = DDI_BUF_CTL(port); 2452d5c7854bSLucas De Marchi set_bits = XE2LPD_DDI_BUF_D2D_LINK_ENABLE; 2453d5c7854bSLucas De Marchi wait_bits = XE2LPD_DDI_BUF_D2D_LINK_STATE; 2454d5c7854bSLucas De Marchi } else { 2455fe4c6ff5SLucas De Marchi reg = XELPDP_PORT_BUF_CTL1(dev_priv, port); 2456d5c7854bSLucas De Marchi set_bits = XELPDP_PORT_BUF_D2D_LINK_ENABLE; 2457d5c7854bSLucas De Marchi wait_bits = XELPDP_PORT_BUF_D2D_LINK_STATE; 2458d5c7854bSLucas De Marchi } 245923ef6194SJosé Roberto de Souza 2460d5c7854bSLucas De Marchi intel_de_rmw(dev_priv, reg, 0, set_bits); 2461d5c7854bSLucas De Marchi if (wait_for_us(intel_de_read(dev_priv, reg) & wait_bits, 100)) { 2462d5c7854bSLucas De Marchi drm_err(&dev_priv->drm, "Timeout waiting for D2D Link enable for DDI/PORT_BUF_CTL %c\n", 246323ef6194SJosé Roberto de Souza port_name(port)); 246423ef6194SJosé Roberto de Souza } 246523ef6194SJosé Roberto de Souza } 246623ef6194SJosé Roberto de Souza 246723ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_program(struct intel_encoder *encoder, 246823ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state) 246923ef6194SJosé Roberto de Souza { 247023ef6194SJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(encoder->base.dev); 247123ef6194SJosé Roberto de Souza struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 247223ef6194SJosé Roberto de Souza enum port port = encoder->port; 247323ef6194SJosé Roberto de Souza u32 val; 247423ef6194SJosé Roberto de Souza 2475fe4c6ff5SLucas De Marchi val = intel_de_read(i915, XELPDP_PORT_BUF_CTL1(i915, port)); 247623ef6194SJosé Roberto de Souza val &= ~XELPDP_PORT_WIDTH_MASK; 247723ef6194SJosé Roberto de Souza val |= XELPDP_PORT_WIDTH(mtl_get_port_width(crtc_state->lane_count)); 247823ef6194SJosé Roberto de Souza 247923ef6194SJosé Roberto de Souza val &= ~XELPDP_PORT_BUF_PORT_DATA_WIDTH_MASK; 248023ef6194SJosé Roberto de Souza if (intel_dp_is_uhbr(crtc_state)) 248123ef6194SJosé Roberto de Souza val |= XELPDP_PORT_BUF_PORT_DATA_40BIT; 248223ef6194SJosé Roberto de Souza else 248323ef6194SJosé Roberto de Souza val |= XELPDP_PORT_BUF_PORT_DATA_10BIT; 248423ef6194SJosé Roberto de Souza 248523ef6194SJosé Roberto de Souza if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL) 248623ef6194SJosé Roberto de Souza val |= XELPDP_PORT_REVERSAL; 248723ef6194SJosé Roberto de Souza 2488fe4c6ff5SLucas De Marchi intel_de_write(i915, XELPDP_PORT_BUF_CTL1(i915, port), val); 248923ef6194SJosé Roberto de Souza } 249023ef6194SJosé Roberto de Souza 249123ef6194SJosé Roberto de Souza static void mtl_port_buf_ctl_io_selection(struct intel_encoder *encoder) 249223ef6194SJosé Roberto de Souza { 249323ef6194SJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(encoder->base.dev); 249423ef6194SJosé Roberto de Souza struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 249523ef6194SJosé Roberto de Souza u32 val; 249623ef6194SJosé Roberto de Souza 249723ef6194SJosé Roberto de Souza val = intel_tc_port_in_tbt_alt_mode(dig_port) ? 249823ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_IO_SELECT_TBT : 0; 2499fe4c6ff5SLucas De Marchi intel_de_rmw(i915, XELPDP_PORT_BUF_CTL1(i915, encoder->port), 250023ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_IO_SELECT_TBT, val); 250123ef6194SJosé Roberto de Souza } 250223ef6194SJosé Roberto de Souza 250323ef6194SJosé Roberto de Souza static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, 250423ef6194SJosé Roberto de Souza struct intel_encoder *encoder, 250523ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state, 250623ef6194SJosé Roberto de Souza const struct drm_connector_state *conn_state) 250723ef6194SJosé Roberto de Souza { 250823ef6194SJosé Roberto de Souza struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 250923ef6194SJosé Roberto de Souza bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); 251023ef6194SJosé Roberto de Souza 251123ef6194SJosé Roberto de Souza intel_dp_set_link_params(intel_dp, 251223ef6194SJosé Roberto de Souza crtc_state->port_clock, 251323ef6194SJosé Roberto de Souza crtc_state->lane_count); 251423ef6194SJosé Roberto de Souza 251523ef6194SJosé Roberto de Souza /* 251623ef6194SJosé Roberto de Souza * We only configure what the register value will be here. Actual 251723ef6194SJosé Roberto de Souza * enabling happens during link training farther down. 251823ef6194SJosé Roberto de Souza */ 251923ef6194SJosé Roberto de Souza intel_ddi_init_dp_buf_reg(encoder, crtc_state); 252023ef6194SJosé Roberto de Souza 252123ef6194SJosé Roberto de Souza /* 252223ef6194SJosé Roberto de Souza * 1. Enable Power Wells 252323ef6194SJosé Roberto de Souza * 252423ef6194SJosé Roberto de Souza * This was handled at the beginning of intel_atomic_commit_tail(), 252523ef6194SJosé Roberto de Souza * before we called down into this function. 252623ef6194SJosé Roberto de Souza */ 252723ef6194SJosé Roberto de Souza 252823ef6194SJosé Roberto de Souza /* 2. PMdemand was already set */ 252923ef6194SJosé Roberto de Souza 253023ef6194SJosé Roberto de Souza /* 3. Select Thunderbolt */ 253123ef6194SJosé Roberto de Souza mtl_port_buf_ctl_io_selection(encoder); 253223ef6194SJosé Roberto de Souza 253323ef6194SJosé Roberto de Souza /* 4. Enable Panel Power if PPS is required */ 253423ef6194SJosé Roberto de Souza intel_pps_on(intel_dp); 253523ef6194SJosé Roberto de Souza 253623ef6194SJosé Roberto de Souza /* 5. Enable the port PLL */ 253723ef6194SJosé Roberto de Souza intel_ddi_enable_clock(encoder, crtc_state); 253823ef6194SJosé Roberto de Souza 253923ef6194SJosé Roberto de Souza /* 254023ef6194SJosé Roberto de Souza * 6.a Configure Transcoder Clock Select to direct the Port clock to the 254123ef6194SJosé Roberto de Souza * Transcoder. 254223ef6194SJosé Roberto de Souza */ 254323ef6194SJosé Roberto de Souza intel_ddi_enable_transcoder_clock(encoder, crtc_state); 254423ef6194SJosé Roberto de Souza 254523ef6194SJosé Roberto de Souza /* 254623ef6194SJosé Roberto de Souza * 6.b If DP v2.0/128b mode - Configure TRANS_DP2_CTL register settings. 254723ef6194SJosé Roberto de Souza */ 254823ef6194SJosé Roberto de Souza intel_ddi_config_transcoder_dp2(encoder, crtc_state); 254923ef6194SJosé Roberto de Souza 255023ef6194SJosé Roberto de Souza /* 255123ef6194SJosé Roberto de Souza * 6.c Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST 255223ef6194SJosé Roberto de Souza * Transport Select 255323ef6194SJosé Roberto de Souza */ 255423ef6194SJosé Roberto de Souza intel_ddi_config_transcoder_func(encoder, crtc_state); 255523ef6194SJosé Roberto de Souza 255623ef6194SJosé Roberto de Souza /* 255723ef6194SJosé Roberto de Souza * 6.e Program CoG/MSO configuration bits in DSS_CTL1 if selected. 255823ef6194SJosé Roberto de Souza */ 255923ef6194SJosé Roberto de Souza intel_ddi_mso_configure(crtc_state); 256023ef6194SJosé Roberto de Souza 256123ef6194SJosé Roberto de Souza if (!is_mst) 256223ef6194SJosé Roberto de Souza intel_dp_set_power(intel_dp, DP_SET_POWER_D0); 256323ef6194SJosé Roberto de Souza 256423ef6194SJosé Roberto de Souza intel_dp_configure_protocol_converter(intel_dp, crtc_state); 2565503611c8SImre Deak if (!is_mst) 25667c4631ffSImre Deak intel_dp_sink_enable_decompression(state, 25677c4631ffSImre Deak to_intel_connector(conn_state->connector), 25687c4631ffSImre Deak crtc_state); 2569503611c8SImre Deak 257023ef6194SJosé Roberto de Souza /* 257123ef6194SJosé Roberto de Souza * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit 257223ef6194SJosé Roberto de Souza * in the FEC_CONFIGURATION register to 1 before initiating link 257323ef6194SJosé Roberto de Souza * training 257423ef6194SJosé Roberto de Souza */ 25758ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true); 257623ef6194SJosé Roberto de Souza 257723ef6194SJosé Roberto de Souza intel_dp_check_frl_training(intel_dp); 257823ef6194SJosé Roberto de Souza intel_dp_pcon_dsc_configure(intel_dp, crtc_state); 257923ef6194SJosé Roberto de Souza 258023ef6194SJosé Roberto de Souza /* 258123ef6194SJosé Roberto de Souza * 6. The rest of the below are substeps under the bspec's "Enable and 258223ef6194SJosé Roberto de Souza * Train Display Port" step. Note that steps that are specific to 258323ef6194SJosé Roberto de Souza * MST will be handled by intel_mst_pre_enable_dp() before/after it 258423ef6194SJosé Roberto de Souza * calls into this function. Also intel_mst_pre_enable_dp() only calls 258523ef6194SJosé Roberto de Souza * us when active_mst_links==0, so any steps designated for "single 258623ef6194SJosé Roberto de Souza * stream or multi-stream master transcoder" can just be performed 258723ef6194SJosé Roberto de Souza * unconditionally here. 258823ef6194SJosé Roberto de Souza * 258923ef6194SJosé Roberto de Souza * mtl_ddi_prepare_link_retrain() that is called by 259023ef6194SJosé Roberto de Souza * intel_dp_start_link_train() will execute steps: 6.d, 6.f, 6.g, 6.h, 259123ef6194SJosé Roberto de Souza * 6.i and 6.j 259223ef6194SJosé Roberto de Souza * 259323ef6194SJosé Roberto de Souza * 6.k Follow DisplayPort specification training sequence (see notes for 259423ef6194SJosé Roberto de Souza * failure handling) 259523ef6194SJosé Roberto de Souza * 6.m If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle 259623ef6194SJosé Roberto de Souza * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent) 259723ef6194SJosé Roberto de Souza * (timeout after 800 us) 259823ef6194SJosé Roberto de Souza */ 2599*182c6be0SImre Deak intel_dp_start_link_train(state, intel_dp, crtc_state); 260023ef6194SJosé Roberto de Souza 260123ef6194SJosé Roberto de Souza /* 6.n Set DP_TP_CTL link training to Normal */ 260223ef6194SJosé Roberto de Souza if (!is_trans_port_sync_mode(crtc_state)) 260323ef6194SJosé Roberto de Souza intel_dp_stop_link_train(intel_dp, crtc_state); 260423ef6194SJosé Roberto de Souza 260523ef6194SJosé Roberto de Souza /* 6.o Configure and enable FEC if needed */ 260623ef6194SJosé Roberto de Souza intel_ddi_enable_fec(encoder, crtc_state); 260723ef6194SJosé Roberto de Souza 260853f468aaSImre Deak if (!is_mst) 260923ef6194SJosé Roberto de Souza intel_dsc_dp_pps_write(encoder, crtc_state); 261023ef6194SJosé Roberto de Souza } 261123ef6194SJosé Roberto de Souza 2612ede9771dSVille Syrjälä static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state, 2613ede9771dSVille Syrjälä struct intel_encoder *encoder, 261499389390SJosé Roberto de Souza const struct intel_crtc_state *crtc_state, 261599389390SJosé Roberto de Souza const struct drm_connector_state *conn_state) 261699389390SJosé Roberto de Souza { 2617b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 261899389390SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2619b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 262099389390SJosé Roberto de Souza bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); 262199389390SJosé Roberto de Souza 2622a621860aSVille Syrjälä intel_dp_set_link_params(intel_dp, 2623a621860aSVille Syrjälä crtc_state->port_clock, 2624a621860aSVille Syrjälä crtc_state->lane_count); 262599389390SJosé Roberto de Souza 26265e19c0b0SMatt Roper /* 26279f620f1dSVille Syrjälä * We only configure what the register value will be here. Actual 26289f620f1dSVille Syrjälä * enabling happens during link training farther down. 26299f620f1dSVille Syrjälä */ 26309f620f1dSVille Syrjälä intel_ddi_init_dp_buf_reg(encoder, crtc_state); 26319f620f1dSVille Syrjälä 26329f620f1dSVille Syrjälä /* 26335e19c0b0SMatt Roper * 1. Enable Power Wells 26345e19c0b0SMatt Roper * 26355e19c0b0SMatt Roper * This was handled at the beginning of intel_atomic_commit_tail(), 26365e19c0b0SMatt Roper * before we called down into this function. 26375e19c0b0SMatt Roper */ 263899389390SJosé Roberto de Souza 26395e19c0b0SMatt Roper /* 2. Enable Panel Power if PPS is required */ 2640eb46f498SJani Nikula intel_pps_on(intel_dp); 264199389390SJosé Roberto de Souza 264299389390SJosé Roberto de Souza /* 26435e19c0b0SMatt Roper * 3. For non-TBT Type-C ports, set FIA lane count 26445e19c0b0SMatt Roper * (DFLEXDPSP.DPX4TXLATC) 26455e19c0b0SMatt Roper * 26465e19c0b0SMatt Roper * This was done before tgl_ddi_pre_enable_dp by 26471e98f88cSLucas De Marchi * hsw_crtc_enable()->intel_encoders_pre_pll_enable(). 264899389390SJosé Roberto de Souza */ 264999389390SJosé Roberto de Souza 26505e19c0b0SMatt Roper /* 26515e19c0b0SMatt Roper * 4. Enable the port PLL. 26525e19c0b0SMatt Roper * 26535e19c0b0SMatt Roper * The PLL enabling itself was already done before this function by 26541e98f88cSLucas De Marchi * hsw_crtc_enable()->intel_enable_shared_dpll(). We need only 26555e19c0b0SMatt Roper * configure the PLL to port mapping here. 26565e19c0b0SMatt Roper */ 2657c133df69SVille Syrjälä intel_ddi_enable_clock(encoder, crtc_state); 26586171e58bSClinton A Taylor 26595e19c0b0SMatt Roper /* 5. If IO power is controlled through PWR_WELL_CTL, Enable IO Power */ 266011a89708SImre Deak if (!intel_tc_port_in_tbt_alt_mode(dig_port)) { 2661a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref); 2662a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv, 266399389390SJosé Roberto de Souza dig_port->ddi_io_power_domain); 2664a4550977SImre Deak } 266599389390SJosé Roberto de Souza 26665e19c0b0SMatt Roper /* 6. Program DP_MODE */ 26673b51be4eSClinton A Taylor icl_program_mg_dp_mode(dig_port, crtc_state); 266899389390SJosé Roberto de Souza 266999389390SJosé Roberto de Souza /* 26705e19c0b0SMatt Roper * 7. The rest of the below are substeps under the bspec's "Enable and 26715e19c0b0SMatt Roper * Train Display Port" step. Note that steps that are specific to 26725e19c0b0SMatt Roper * MST will be handled by intel_mst_pre_enable_dp() before/after it 26735e19c0b0SMatt Roper * calls into this function. Also intel_mst_pre_enable_dp() only calls 26745e19c0b0SMatt Roper * us when active_mst_links==0, so any steps designated for "single 26755e19c0b0SMatt Roper * stream or multi-stream master transcoder" can just be performed 26765e19c0b0SMatt Roper * unconditionally here. 26775e19c0b0SMatt Roper */ 26785e19c0b0SMatt Roper 26795e19c0b0SMatt Roper /* 26805e19c0b0SMatt Roper * 7.a Configure Transcoder Clock Select to direct the Port clock to the 26815e19c0b0SMatt Roper * Transcoder. 268299389390SJosé Roberto de Souza */ 268355a4679eSVille Syrjälä intel_ddi_enable_transcoder_clock(encoder, crtc_state); 268499389390SJosé Roberto de Souza 2685fe6959a6SVille Syrjälä if (HAS_DP20(dev_priv)) 2686fe6959a6SVille Syrjälä intel_ddi_config_transcoder_dp2(encoder, crtc_state); 2687fe6959a6SVille Syrjälä 26885e19c0b0SMatt Roper /* 26895e19c0b0SMatt Roper * 7.b Configure TRANS_DDI_FUNC_CTL DDI Select, DDI Mode Select & MST 26905e19c0b0SMatt Roper * Transport Select 26915e19c0b0SMatt Roper */ 2692eed22a46SVille Syrjälä intel_ddi_config_transcoder_func(encoder, crtc_state); 269399389390SJosé Roberto de Souza 26945e19c0b0SMatt Roper /* 26955e19c0b0SMatt Roper * 7.c Configure & enable DP_TP_CTL with link training pattern 1 26965e19c0b0SMatt Roper * selected 26975e19c0b0SMatt Roper * 26985e19c0b0SMatt Roper * This will be handled by the intel_dp_start_link_train() farther 26995e19c0b0SMatt Roper * down this function. 27005e19c0b0SMatt Roper */ 27015e19c0b0SMatt Roper 27025e19c0b0SMatt Roper /* 7.e Configure voltage swing and related IO settings */ 2703e722ab8bSVille Syrjälä encoder->set_signal_levels(encoder, crtc_state); 270499389390SJosé Roberto de Souza 27055e19c0b0SMatt Roper /* 27065e19c0b0SMatt Roper * 7.f Combo PHY: Configure PORT_CL_DW10 Static Power Down to power up 27075e19c0b0SMatt Roper * the used lanes of the DDI. 27085e19c0b0SMatt Roper */ 27095cdf706fSVille Syrjälä intel_ddi_power_up_lanes(encoder, crtc_state); 271099389390SJosé Roberto de Souza 27115e19c0b0SMatt Roper /* 2712bc71194eSJani Nikula * 7.g Program CoG/MSO configuration bits in DSS_CTL1 if selected. 2713bc71194eSJani Nikula */ 2714bc71194eSJani Nikula intel_ddi_mso_configure(crtc_state); 2715bc71194eSJani Nikula 271699389390SJosé Roberto de Souza if (!is_mst) 27170e634efdSVille Syrjälä intel_dp_set_power(intel_dp, DP_SET_POWER_D0); 271899389390SJosé Roberto de Souza 2719522508b6SAnkit Nautiyal intel_dp_configure_protocol_converter(intel_dp, crtc_state); 2720503611c8SImre Deak if (!is_mst) 27217c4631ffSImre Deak intel_dp_sink_enable_decompression(state, 27227c4631ffSImre Deak to_intel_connector(conn_state->connector), 27237c4631ffSImre Deak crtc_state); 272499389390SJosé Roberto de Souza /* 272599389390SJosé Roberto de Souza * DDI FEC: "anticipates enabling FEC encoding sets the FEC_READY bit 272699389390SJosé Roberto de Souza * in the FEC_CONFIGURATION register to 1 before initiating link 272799389390SJosé Roberto de Souza * training 272899389390SJosé Roberto de Souza */ 27298ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true); 27305e19c0b0SMatt Roper 27314f3dd47aSAnkit Nautiyal intel_dp_check_frl_training(intel_dp); 273210fec80bSAnkit Nautiyal intel_dp_pcon_dsc_configure(intel_dp, crtc_state); 27334f3dd47aSAnkit Nautiyal 27345e19c0b0SMatt Roper /* 27355e19c0b0SMatt Roper * 7.i Follow DisplayPort specification training sequence (see notes for 27365e19c0b0SMatt Roper * failure handling) 27375e19c0b0SMatt Roper * 7.j If DisplayPort multi-stream - Set DP_TP_CTL link training to Idle 27385e19c0b0SMatt Roper * Pattern, wait for 5 idle patterns (DP_TP_STATUS Min_Idles_Sent) 27395e19c0b0SMatt Roper * (timeout after 800 us) 27405e19c0b0SMatt Roper */ 2741*182c6be0SImre Deak intel_dp_start_link_train(state, intel_dp, crtc_state); 274299389390SJosé Roberto de Souza 27435e19c0b0SMatt Roper /* 7.k Set DP_TP_CTL link training to Normal */ 2744eadf6f91SManasi Navare if (!is_trans_port_sync_mode(crtc_state)) 2745a621860aSVille Syrjälä intel_dp_stop_link_train(intel_dp, crtc_state); 274699389390SJosé Roberto de Souza 27475e19c0b0SMatt Roper /* 7.l Configure and enable FEC if needed */ 274899389390SJosé Roberto de Souza intel_ddi_enable_fec(encoder, crtc_state); 27493126977dSVille Syrjälä 275053f468aaSImre Deak if (!is_mst) 27513126977dSVille Syrjälä intel_dsc_dp_pps_write(encoder, crtc_state); 275299389390SJosé Roberto de Souza } 275399389390SJosé Roberto de Souza 2754ede9771dSVille Syrjälä static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, 2755ede9771dSVille Syrjälä struct intel_encoder *encoder, 2756379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 2757379bc100SJani Nikula const struct drm_connector_state *conn_state) 2758379bc100SJani Nikula { 2759b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 2760379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2761379bc100SJani Nikula enum port port = encoder->port; 2762b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 2763379bc100SJani Nikula bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); 2764379bc100SJani Nikula 2765005e9537SMatt Roper if (DISPLAY_VER(dev_priv) < 11) 27661de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, 27671de143ccSPankaj Bharadiya is_mst && (port == PORT_A || port == PORT_E)); 2768542dfab5SJosé Roberto de Souza else 27691de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, is_mst && port == PORT_A); 2770379bc100SJani Nikula 2771a621860aSVille Syrjälä intel_dp_set_link_params(intel_dp, 2772a621860aSVille Syrjälä crtc_state->port_clock, 2773a621860aSVille Syrjälä crtc_state->lane_count); 2774379bc100SJani Nikula 27759f620f1dSVille Syrjälä /* 27769f620f1dSVille Syrjälä * We only configure what the register value will be here. Actual 27779f620f1dSVille Syrjälä * enabling happens during link training farther down. 27789f620f1dSVille Syrjälä */ 27799f620f1dSVille Syrjälä intel_ddi_init_dp_buf_reg(encoder, crtc_state); 27809f620f1dSVille Syrjälä 2781eb46f498SJani Nikula intel_pps_on(intel_dp); 2782379bc100SJani Nikula 2783c133df69SVille Syrjälä intel_ddi_enable_clock(encoder, crtc_state); 2784379bc100SJani Nikula 278511a89708SImre Deak if (!intel_tc_port_in_tbt_alt_mode(dig_port)) { 2786a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref); 2787a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv, 27883b2ed431SImre Deak dig_port->ddi_io_power_domain); 2789a4550977SImre Deak } 2790379bc100SJani Nikula 27913b51be4eSClinton A Taylor icl_program_mg_dp_mode(dig_port, crtc_state); 2792379bc100SJani Nikula 27935bafd85dSVille Syrjälä if (has_buf_trans_select(dev_priv)) 2794266152aeSVille Syrjälä hsw_prepare_dp_ddi_buffers(encoder, crtc_state); 2795379bc100SJani Nikula 2796e722ab8bSVille Syrjälä encoder->set_signal_levels(encoder, crtc_state); 2797e722ab8bSVille Syrjälä 27985cdf706fSVille Syrjälä intel_ddi_power_up_lanes(encoder, crtc_state); 2799379bc100SJani Nikula 2800379bc100SJani Nikula if (!is_mst) 28010e634efdSVille Syrjälä intel_dp_set_power(intel_dp, DP_SET_POWER_D0); 2802522508b6SAnkit Nautiyal intel_dp_configure_protocol_converter(intel_dp, crtc_state); 2803503611c8SImre Deak if (!is_mst) 28047c4631ffSImre Deak intel_dp_sink_enable_decompression(state, 28057c4631ffSImre Deak to_intel_connector(conn_state->connector), 28067c4631ffSImre Deak crtc_state); 28078ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, crtc_state, true); 2808*182c6be0SImre Deak intel_dp_start_link_train(state, intel_dp, crtc_state); 2809005e9537SMatt Roper if ((port != PORT_A || DISPLAY_VER(dev_priv) >= 9) && 2810eadf6f91SManasi Navare !is_trans_port_sync_mode(crtc_state)) 2811a621860aSVille Syrjälä intel_dp_stop_link_train(intel_dp, crtc_state); 2812379bc100SJani Nikula 2813379bc100SJani Nikula intel_ddi_enable_fec(encoder, crtc_state); 2814379bc100SJani Nikula 281553f468aaSImre Deak if (!is_mst) { 281655a4679eSVille Syrjälä intel_ddi_enable_transcoder_clock(encoder, crtc_state); 28173126977dSVille Syrjälä intel_dsc_dp_pps_write(encoder, crtc_state); 2818379bc100SJani Nikula } 281953f468aaSImre Deak } 2820379bc100SJani Nikula 2821ede9771dSVille Syrjälä static void intel_ddi_pre_enable_dp(struct intel_atomic_state *state, 2822ede9771dSVille Syrjälä struct intel_encoder *encoder, 282399389390SJosé Roberto de Souza const struct intel_crtc_state *crtc_state, 282499389390SJosé Roberto de Souza const struct drm_connector_state *conn_state) 282599389390SJosé Roberto de Souza { 282699389390SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 282799389390SJosé Roberto de Souza 282888ae6c65SJouni Högander if (HAS_DP20(dev_priv)) 28291a324a40SArun R Murthy intel_dp_128b132b_sdp_crc16(enc_to_intel_dp(encoder), 28301a324a40SArun R Murthy crtc_state); 283188ae6c65SJouni Högander 283288ae6c65SJouni Högander /* Panel replay has to be enabled in sink dpcd before link training. */ 28333257e55dSAnimesh Manna if (crtc_state->has_panel_replay) 283488ae6c65SJouni Högander intel_psr_enable_sink(enc_to_intel_dp(encoder), crtc_state); 28351a324a40SArun R Murthy 283623ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14) 283723ef6194SJosé Roberto de Souza mtl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state); 283823ef6194SJosé Roberto de Souza else if (DISPLAY_VER(dev_priv) >= 12) 2839ede9771dSVille Syrjälä tgl_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state); 284099389390SJosé Roberto de Souza else 2841ede9771dSVille Syrjälä hsw_ddi_pre_enable_dp(state, encoder, crtc_state, conn_state); 28420c06fa15SGwan-gyeong Mun 2843bd8c9ccaSGwan-gyeong Mun /* MST will call a setting of MSA after an allocating of Virtual Channel 2844bd8c9ccaSGwan-gyeong Mun * from MST encoder pre_enable callback. 2845bd8c9ccaSGwan-gyeong Mun */ 28468de5df3bSVille Syrjälä if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) 28470c06fa15SGwan-gyeong Mun intel_ddi_set_dp_msa(crtc_state, conn_state); 28481fc1e8d4SJosé Roberto de Souza } 284999389390SJosé Roberto de Souza 2850ede9771dSVille Syrjälä static void intel_ddi_pre_enable_hdmi(struct intel_atomic_state *state, 2851ede9771dSVille Syrjälä struct intel_encoder *encoder, 2852379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 2853379bc100SJani Nikula const struct drm_connector_state *conn_state) 2854379bc100SJani Nikula { 28550ba7ffeaSLucas De Marchi struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 28560ba7ffeaSLucas De Marchi struct intel_hdmi *intel_hdmi = &dig_port->hdmi; 2857379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2858379bc100SJani Nikula 2859379bc100SJani Nikula intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); 2860c133df69SVille Syrjälä intel_ddi_enable_clock(encoder, crtc_state); 2861379bc100SJani Nikula 2862a4550977SImre Deak drm_WARN_ON(&dev_priv->drm, dig_port->ddi_io_wakeref); 2863a4550977SImre Deak dig_port->ddi_io_wakeref = intel_display_power_get(dev_priv, 2864a4550977SImre Deak dig_port->ddi_io_power_domain); 2865379bc100SJani Nikula 28663b51be4eSClinton A Taylor icl_program_mg_dp_mode(dig_port, crtc_state); 2867379bc100SJani Nikula 286855a4679eSVille Syrjälä intel_ddi_enable_transcoder_clock(encoder, crtc_state); 2869379bc100SJani Nikula 28700ba7ffeaSLucas De Marchi dig_port->set_infoframes(encoder, 2871379bc100SJani Nikula crtc_state->has_infoframe, 2872379bc100SJani Nikula crtc_state, conn_state); 2873379bc100SJani Nikula } 2874379bc100SJani Nikula 2875ede9771dSVille Syrjälä static void intel_ddi_pre_enable(struct intel_atomic_state *state, 2876ede9771dSVille Syrjälä struct intel_encoder *encoder, 2877379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 2878379bc100SJani Nikula const struct drm_connector_state *conn_state) 2879379bc100SJani Nikula { 28802225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 2881379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2882379bc100SJani Nikula enum pipe pipe = crtc->pipe; 2883379bc100SJani Nikula 2884379bc100SJani Nikula /* 2885379bc100SJani Nikula * When called from DP MST code: 2886379bc100SJani Nikula * - conn_state will be NULL 2887379bc100SJani Nikula * - encoder will be the main encoder (ie. mst->primary) 2888379bc100SJani Nikula * - the main connector associated with this port 2889379bc100SJani Nikula * won't be active or linked to a crtc 2890379bc100SJani Nikula * - crtc_state will be the state of the first stream to 2891379bc100SJani Nikula * be activated on this port, and it may not be the same 2892379bc100SJani Nikula * stream that will be deactivated last, but each stream 2893379bc100SJani Nikula * should have a state that is identical when it comes to 2894379bc100SJani Nikula * the DP link parameteres 2895379bc100SJani Nikula */ 2896379bc100SJani Nikula 28971de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, crtc_state->has_pch_encoder); 2898379bc100SJani Nikula 2899379bc100SJani Nikula intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); 2900379bc100SJani Nikula 2901379bc100SJani Nikula if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) { 2902ede9771dSVille Syrjälä intel_ddi_pre_enable_hdmi(state, encoder, crtc_state, 2903ede9771dSVille Syrjälä conn_state); 2904379bc100SJani Nikula } else { 2905f7af425dSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 2906379bc100SJani Nikula 2907ede9771dSVille Syrjälä intel_ddi_pre_enable_dp(state, encoder, crtc_state, 2908ede9771dSVille Syrjälä conn_state); 2909379bc100SJani Nikula 2910f7af425dSVille Syrjälä /* FIXME precompute everything properly */ 29110ea02bb8SJosé Roberto de Souza /* FIXME how do we turn infoframes off again? */ 29127ffa2f27SJani Nikula if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp)) 2913379bc100SJani Nikula dig_port->set_infoframes(encoder, 2914379bc100SJani Nikula crtc_state->has_infoframe, 2915379bc100SJani Nikula crtc_state, conn_state); 2916379bc100SJani Nikula } 2917379bc100SJani Nikula } 2918379bc100SJani Nikula 291923ef6194SJosé Roberto de Souza static void 292023ef6194SJosé Roberto de Souza mtl_ddi_disable_d2d_link(struct intel_encoder *encoder) 292123ef6194SJosé Roberto de Souza { 292223ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 292323ef6194SJosé Roberto de Souza enum port port = encoder->port; 2924d5c7854bSLucas De Marchi i915_reg_t reg; 2925d5c7854bSLucas De Marchi u32 clr_bits, wait_bits; 292623ef6194SJosé Roberto de Souza 2927d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20) { 2928d5c7854bSLucas De Marchi reg = DDI_BUF_CTL(port); 2929d5c7854bSLucas De Marchi clr_bits = XE2LPD_DDI_BUF_D2D_LINK_ENABLE; 2930d5c7854bSLucas De Marchi wait_bits = XE2LPD_DDI_BUF_D2D_LINK_STATE; 2931d5c7854bSLucas De Marchi } else { 2932fe4c6ff5SLucas De Marchi reg = XELPDP_PORT_BUF_CTL1(dev_priv, port); 2933d5c7854bSLucas De Marchi clr_bits = XELPDP_PORT_BUF_D2D_LINK_ENABLE; 2934d5c7854bSLucas De Marchi wait_bits = XELPDP_PORT_BUF_D2D_LINK_STATE; 2935d5c7854bSLucas De Marchi } 293623ef6194SJosé Roberto de Souza 2937d5c7854bSLucas De Marchi intel_de_rmw(dev_priv, reg, clr_bits, 0); 2938d5c7854bSLucas De Marchi if (wait_for_us(!(intel_de_read(dev_priv, reg) & wait_bits), 100)) 2939d5c7854bSLucas De Marchi drm_err(&dev_priv->drm, "Timeout waiting for D2D Link disable for DDI/PORT_BUF_CTL %c\n", 294023ef6194SJosé Roberto de Souza port_name(port)); 294123ef6194SJosé Roberto de Souza } 294223ef6194SJosé Roberto de Souza 294323ef6194SJosé Roberto de Souza static void mtl_disable_ddi_buf(struct intel_encoder *encoder, 294423ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state) 294523ef6194SJosé Roberto de Souza { 294623ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 294723ef6194SJosé Roberto de Souza enum port port = encoder->port; 294823ef6194SJosé Roberto de Souza u32 val; 294923ef6194SJosé Roberto de Souza 295023ef6194SJosé Roberto de Souza /* 3.b Clear DDI_CTL_DE Enable to 0. */ 295123ef6194SJosé Roberto de Souza val = intel_de_read(dev_priv, DDI_BUF_CTL(port)); 295223ef6194SJosé Roberto de Souza if (val & DDI_BUF_CTL_ENABLE) { 295323ef6194SJosé Roberto de Souza val &= ~DDI_BUF_CTL_ENABLE; 295423ef6194SJosé Roberto de Souza intel_de_write(dev_priv, DDI_BUF_CTL(port), val); 295523ef6194SJosé Roberto de Souza 295623ef6194SJosé Roberto de Souza /* 3.c Poll for PORT_BUF_CTL Idle Status == 1, timeout after 100us */ 295723ef6194SJosé Roberto de Souza mtl_wait_ddi_buf_idle(dev_priv, port); 295823ef6194SJosé Roberto de Souza } 295923ef6194SJosé Roberto de Souza 296023ef6194SJosé Roberto de Souza /* 3.d Disable D2D Link */ 296123ef6194SJosé Roberto de Souza mtl_ddi_disable_d2d_link(encoder); 296223ef6194SJosé Roberto de Souza 296323ef6194SJosé Roberto de Souza /* 3.e Disable DP_TP_CTL */ 296423ef6194SJosé Roberto de Souza if (intel_crtc_has_dp_encoder(crtc_state)) { 296523ef6194SJosé Roberto de Souza intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), 296623ef6194SJosé Roberto de Souza DP_TP_CTL_ENABLE, 0); 296723ef6194SJosé Roberto de Souza } 296823ef6194SJosé Roberto de Souza } 296923ef6194SJosé Roberto de Souza 297023ef6194SJosé Roberto de Souza static void disable_ddi_buf(struct intel_encoder *encoder, 2971379bc100SJani Nikula const struct intel_crtc_state *crtc_state) 2972379bc100SJani Nikula { 2973379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2974379bc100SJani Nikula enum port port = encoder->port; 2975379bc100SJani Nikula bool wait = false; 2976379bc100SJani Nikula u32 val; 2977379bc100SJani Nikula 2978f7960e7fSJani Nikula val = intel_de_read(dev_priv, DDI_BUF_CTL(port)); 2979379bc100SJani Nikula if (val & DDI_BUF_CTL_ENABLE) { 2980379bc100SJani Nikula val &= ~DDI_BUF_CTL_ENABLE; 2981f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_CTL(port), val); 2982379bc100SJani Nikula wait = true; 2983379bc100SJani Nikula } 2984379bc100SJani Nikula 29858910d8b7SAndrzej Hajda if (intel_crtc_has_dp_encoder(crtc_state)) 29868910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), 29878c042949SVille Syrjälä DP_TP_CTL_ENABLE, 0); 2988379bc100SJani Nikula 29890cfdf662SImre Deak intel_ddi_disable_fec(encoder, crtc_state); 2990379bc100SJani Nikula 2991379bc100SJani Nikula if (wait) 2992379bc100SJani Nikula intel_wait_ddi_buf_idle(dev_priv, port); 2993379bc100SJani Nikula } 2994379bc100SJani Nikula 299523ef6194SJosé Roberto de Souza static void intel_disable_ddi_buf(struct intel_encoder *encoder, 299623ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state) 299723ef6194SJosé Roberto de Souza { 299823ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 299923ef6194SJosé Roberto de Souza 300023ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14) { 300123ef6194SJosé Roberto de Souza mtl_disable_ddi_buf(encoder, crtc_state); 300223ef6194SJosé Roberto de Souza 300323ef6194SJosé Roberto de Souza /* 3.f Disable DP_TP_CTL FEC Enable if it is needed */ 30040cfdf662SImre Deak intel_ddi_disable_fec(encoder, crtc_state); 300523ef6194SJosé Roberto de Souza } else { 300623ef6194SJosé Roberto de Souza disable_ddi_buf(encoder, crtc_state); 300723ef6194SJosé Roberto de Souza } 30086e916b35SImre Deak 30096e916b35SImre Deak intel_ddi_wait_for_fec_status(encoder, crtc_state, false); 301023ef6194SJosé Roberto de Souza } 301123ef6194SJosé Roberto de Souza 3012ede9771dSVille Syrjälä static void intel_ddi_post_disable_dp(struct intel_atomic_state *state, 3013ede9771dSVille Syrjälä struct intel_encoder *encoder, 3014379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state, 3015379bc100SJani Nikula const struct drm_connector_state *old_conn_state) 3016379bc100SJani Nikula { 3017379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3018b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3019379bc100SJani Nikula struct intel_dp *intel_dp = &dig_port->dp; 302023ef6194SJosé Roberto de Souza intel_wakeref_t wakeref; 3021379bc100SJani Nikula bool is_mst = intel_crtc_has_type(old_crtc_state, 3022379bc100SJani Nikula INTEL_OUTPUT_DP_MST); 3023379bc100SJani Nikula 3024c980216dSImre Deak if (!is_mst) 3025c980216dSImre Deak intel_dp_set_infoframes(encoder, false, 3026c980216dSImre Deak old_crtc_state, old_conn_state); 3027fa37a213SGwan-gyeong Mun 3028379bc100SJani Nikula /* 3029379bc100SJani Nikula * Power down sink before disabling the port, otherwise we end 3030379bc100SJani Nikula * up getting interrupts from the sink on detecting link loss. 3031379bc100SJani Nikula */ 30320e634efdSVille Syrjälä intel_dp_set_power(intel_dp, DP_SET_POWER_D3); 303378eaaba3SJosé Roberto de Souza 3034005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) { 3035c59053dcSJosé Roberto de Souza if (is_mst) { 3036c59053dcSJosé Roberto de Souza enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; 3037c59053dcSJosé Roberto de Souza 3038b092d6adSJani Nikula intel_de_rmw(dev_priv, 3039b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder), 30408910d8b7SAndrzej Hajda TGL_TRANS_DDI_PORT_MASK | TRANS_DDI_MODE_SELECT_MASK, 30418910d8b7SAndrzej Hajda 0); 3042c59053dcSJosé Roberto de Souza } 3043c59053dcSJosé Roberto de Souza } else { 3044c59053dcSJosé Roberto de Souza if (!is_mst) 304555a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state); 3046c59053dcSJosé Roberto de Souza } 3047379bc100SJani Nikula 3048379bc100SJani Nikula intel_disable_ddi_buf(encoder, old_crtc_state); 3049379bc100SJani Nikula 30508ab5a036SImre Deak intel_dp_sink_set_fec_ready(intel_dp, old_crtc_state, false); 30518ab5a036SImre Deak 30523ca8f191SJosé Roberto de Souza /* 30533ca8f191SJosé Roberto de Souza * From TGL spec: "If single stream or multi-stream master transcoder: 30543ca8f191SJosé Roberto de Souza * Configure Transcoder Clock select to direct no clock to the 30553ca8f191SJosé Roberto de Souza * transcoder" 30563ca8f191SJosé Roberto de Souza */ 3057005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 305855a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state); 30593ca8f191SJosé Roberto de Souza 3060eb46f498SJani Nikula intel_pps_vdd_on(intel_dp); 3061eb46f498SJani Nikula intel_pps_off(intel_dp); 3062379bc100SJani Nikula 306323ef6194SJosé Roberto de Souza wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref); 306423ef6194SJosé Roberto de Souza 306523ef6194SJosé Roberto de Souza if (wakeref) 3066a4550977SImre Deak intel_display_power_put(dev_priv, 3067a4550977SImre Deak dig_port->ddi_io_power_domain, 306823ef6194SJosé Roberto de Souza wakeref); 3069379bc100SJani Nikula 3070c133df69SVille Syrjälä intel_ddi_disable_clock(encoder); 307123ef6194SJosé Roberto de Souza 307223ef6194SJosé Roberto de Souza /* De-select Thunderbolt */ 307323ef6194SJosé Roberto de Souza if (DISPLAY_VER(dev_priv) >= 14) 3074fe4c6ff5SLucas De Marchi intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(dev_priv, encoder->port), 307523ef6194SJosé Roberto de Souza XELPDP_PORT_BUF_IO_SELECT_TBT, 0); 3076379bc100SJani Nikula } 3077379bc100SJani Nikula 3078ede9771dSVille Syrjälä static void intel_ddi_post_disable_hdmi(struct intel_atomic_state *state, 3079ede9771dSVille Syrjälä struct intel_encoder *encoder, 3080379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state, 3081379bc100SJani Nikula const struct drm_connector_state *old_conn_state) 3082379bc100SJani Nikula { 3083379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3084b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3085379bc100SJani Nikula struct intel_hdmi *intel_hdmi = &dig_port->hdmi; 308623ef6194SJosé Roberto de Souza intel_wakeref_t wakeref; 3087379bc100SJani Nikula 3088379bc100SJani Nikula dig_port->set_infoframes(encoder, false, 3089379bc100SJani Nikula old_crtc_state, old_conn_state); 3090379bc100SJani Nikula 3091c1949189SImre Deak if (DISPLAY_VER(dev_priv) < 12) 309255a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state); 3093379bc100SJani Nikula 3094379bc100SJani Nikula intel_disable_ddi_buf(encoder, old_crtc_state); 3095379bc100SJani Nikula 3096c1949189SImre Deak if (DISPLAY_VER(dev_priv) >= 12) 309755a4679eSVille Syrjälä intel_ddi_disable_transcoder_clock(old_crtc_state); 3098c1949189SImre Deak 309923ef6194SJosé Roberto de Souza wakeref = fetch_and_zero(&dig_port->ddi_io_wakeref); 310023ef6194SJosé Roberto de Souza if (wakeref) 3101a4550977SImre Deak intel_display_power_put(dev_priv, 3102a4550977SImre Deak dig_port->ddi_io_power_domain, 310323ef6194SJosé Roberto de Souza wakeref); 3104379bc100SJani Nikula 3105c133df69SVille Syrjälä intel_ddi_disable_clock(encoder); 3106379bc100SJani Nikula 3107379bc100SJani Nikula intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); 3108379bc100SJani Nikula } 3109379bc100SJani Nikula 3110f3b93eaeSVille Syrjälä static void intel_ddi_post_disable_hdmi_or_sst(struct intel_atomic_state *state, 3111ede9771dSVille Syrjälä struct intel_encoder *encoder, 3112379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state, 3113379bc100SJani Nikula const struct drm_connector_state *old_conn_state) 3114379bc100SJani Nikula { 3115379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3116b7ce2803SVille Syrjälä struct intel_crtc *pipe_crtc; 3117379bc100SJani Nikula 3118b7ce2803SVille Syrjälä for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, 3119b7ce2803SVille Syrjälä intel_crtc_joined_pipe_mask(old_crtc_state)) { 3120b7ce2803SVille Syrjälä const struct intel_crtc_state *old_pipe_crtc_state = 3121b7ce2803SVille Syrjälä intel_atomic_get_old_crtc_state(state, pipe_crtc); 3122b7ce2803SVille Syrjälä 3123b7ce2803SVille Syrjälä intel_crtc_vblank_off(old_pipe_crtc_state); 3124b7ce2803SVille Syrjälä } 3125773b4b54SVille Syrjälä 31260504d0acSVille Syrjälä intel_disable_transcoder(old_crtc_state); 31270504d0acSVille Syrjälä 3128773b4b54SVille Syrjälä intel_ddi_disable_transcoder_func(old_crtc_state); 3129773b4b54SVille Syrjälä 3130b7ce2803SVille Syrjälä for_each_intel_crtc_in_pipe_mask(&dev_priv->drm, pipe_crtc, 3131b7ce2803SVille Syrjälä intel_crtc_joined_pipe_mask(old_crtc_state)) { 3132b7ce2803SVille Syrjälä const struct intel_crtc_state *old_pipe_crtc_state = 3133b7ce2803SVille Syrjälä intel_atomic_get_old_crtc_state(state, pipe_crtc); 3134b7ce2803SVille Syrjälä 3135b7ce2803SVille Syrjälä intel_dsc_disable(old_pipe_crtc_state); 3136773b4b54SVille Syrjälä 3137005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 9) 3138b7ce2803SVille Syrjälä skl_scaler_disable(old_pipe_crtc_state); 3139773b4b54SVille Syrjälä else 3140b7ce2803SVille Syrjälä ilk_pfit_disable(old_pipe_crtc_state); 31414e3cdb45SManasi Navare } 3142f3b93eaeSVille Syrjälä } 3143f3b93eaeSVille Syrjälä 3144f3b93eaeSVille Syrjälä static void intel_ddi_post_disable(struct intel_atomic_state *state, 3145f3b93eaeSVille Syrjälä struct intel_encoder *encoder, 3146f3b93eaeSVille Syrjälä const struct intel_crtc_state *old_crtc_state, 3147f3b93eaeSVille Syrjälä const struct drm_connector_state *old_conn_state) 3148f3b93eaeSVille Syrjälä { 3149f3b93eaeSVille Syrjälä if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) 3150f3b93eaeSVille Syrjälä intel_ddi_post_disable_hdmi_or_sst(state, encoder, old_crtc_state, 3151f3b93eaeSVille Syrjälä old_conn_state); 31524e3cdb45SManasi Navare 3153379bc100SJani Nikula /* 3154379bc100SJani Nikula * When called from DP MST code: 3155379bc100SJani Nikula * - old_conn_state will be NULL 3156379bc100SJani Nikula * - encoder will be the main encoder (ie. mst->primary) 3157379bc100SJani Nikula * - the main connector associated with this port 3158379bc100SJani Nikula * won't be active or linked to a crtc 3159379bc100SJani Nikula * - old_crtc_state will be the state of the last stream to 3160379bc100SJani Nikula * be deactivated on this port, and it may not be the same 3161379bc100SJani Nikula * stream that was activated last, but each stream 3162379bc100SJani Nikula * should have a state that is identical when it comes to 3163379bc100SJani Nikula * the DP link parameteres 3164379bc100SJani Nikula */ 3165379bc100SJani Nikula 3166379bc100SJani Nikula if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) 3167ede9771dSVille Syrjälä intel_ddi_post_disable_hdmi(state, encoder, old_crtc_state, 3168ede9771dSVille Syrjälä old_conn_state); 3169379bc100SJani Nikula else 3170ede9771dSVille Syrjälä intel_ddi_post_disable_dp(state, encoder, old_crtc_state, 3171ede9771dSVille Syrjälä old_conn_state); 3172b108bdd0SImre Deak } 3173b108bdd0SImre Deak 3174b108bdd0SImre Deak static void intel_ddi_post_pll_disable(struct intel_atomic_state *state, 3175b108bdd0SImre Deak struct intel_encoder *encoder, 3176b108bdd0SImre Deak const struct intel_crtc_state *old_crtc_state, 3177b108bdd0SImre Deak const struct drm_connector_state *old_conn_state) 3178b108bdd0SImre Deak { 3179b108bdd0SImre Deak struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3180379bc100SJani Nikula 3181637c7aa2SImre Deak main_link_aux_power_domain_put(dig_port, old_crtc_state); 318217bef9baSVille Syrjälä 31837fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) 318417bef9baSVille Syrjälä intel_tc_port_put_link(dig_port); 3185379bc100SJani Nikula } 3186379bc100SJani Nikula 3187d82a855aSVille Syrjälä static void trans_port_sync_stop_link_train(struct intel_atomic_state *state, 3188d82a855aSVille Syrjälä struct intel_encoder *encoder, 3189d82a855aSVille Syrjälä const struct intel_crtc_state *crtc_state) 3190d82a855aSVille Syrjälä { 3191d82a855aSVille Syrjälä const struct drm_connector_state *conn_state; 3192d82a855aSVille Syrjälä struct drm_connector *conn; 3193d82a855aSVille Syrjälä int i; 3194d82a855aSVille Syrjälä 3195d82a855aSVille Syrjälä if (!crtc_state->sync_mode_slaves_mask) 3196d82a855aSVille Syrjälä return; 3197d82a855aSVille Syrjälä 3198d82a855aSVille Syrjälä for_each_new_connector_in_state(&state->base, conn, conn_state, i) { 3199d82a855aSVille Syrjälä struct intel_encoder *slave_encoder = 3200d82a855aSVille Syrjälä to_intel_encoder(conn_state->best_encoder); 3201d82a855aSVille Syrjälä struct intel_crtc *slave_crtc = to_intel_crtc(conn_state->crtc); 3202d82a855aSVille Syrjälä const struct intel_crtc_state *slave_crtc_state; 3203d82a855aSVille Syrjälä 3204d82a855aSVille Syrjälä if (!slave_crtc) 3205d82a855aSVille Syrjälä continue; 3206d82a855aSVille Syrjälä 3207d82a855aSVille Syrjälä slave_crtc_state = 3208d82a855aSVille Syrjälä intel_atomic_get_new_crtc_state(state, slave_crtc); 3209d82a855aSVille Syrjälä 3210d82a855aSVille Syrjälä if (slave_crtc_state->master_transcoder != 3211d82a855aSVille Syrjälä crtc_state->cpu_transcoder) 3212d82a855aSVille Syrjälä continue; 3213d82a855aSVille Syrjälä 3214a621860aSVille Syrjälä intel_dp_stop_link_train(enc_to_intel_dp(slave_encoder), 3215a621860aSVille Syrjälä slave_crtc_state); 3216d82a855aSVille Syrjälä } 3217d82a855aSVille Syrjälä 3218d82a855aSVille Syrjälä usleep_range(200, 400); 3219d82a855aSVille Syrjälä 3220a621860aSVille Syrjälä intel_dp_stop_link_train(enc_to_intel_dp(encoder), 3221a621860aSVille Syrjälä crtc_state); 3222d82a855aSVille Syrjälä } 3223d82a855aSVille Syrjälä 3224ede9771dSVille Syrjälä static void intel_enable_ddi_dp(struct intel_atomic_state *state, 3225ede9771dSVille Syrjälä struct intel_encoder *encoder, 3226379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 3227379bc100SJani Nikula const struct drm_connector_state *conn_state) 3228379bc100SJani Nikula { 3229379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3230b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 3231998cc864SUma Shankar struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3232379bc100SJani Nikula enum port port = encoder->port; 3233379bc100SJani Nikula 3234005e9537SMatt Roper if (port == PORT_A && DISPLAY_VER(dev_priv) < 9) 3235a621860aSVille Syrjälä intel_dp_stop_link_train(intel_dp, crtc_state); 3236379bc100SJani Nikula 32376306d8dbSHans de Goede drm_connector_update_privacy_screen(conn_state); 3238379bc100SJani Nikula intel_edp_backlight_on(crtc_state, conn_state); 3239998cc864SUma Shankar 32407ffa2f27SJani Nikula if (!dig_port->lspcon.active || intel_dp_has_hdmi_sink(&dig_port->dp)) 32411bf3657cSGwan-gyeong Mun intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); 3242998cc864SUma Shankar 3243d82a855aSVille Syrjälä trans_port_sync_stop_link_train(state, encoder, crtc_state); 3244379bc100SJani Nikula } 3245379bc100SJani Nikula 3246a379bf3dSVille Syrjälä /* FIXME bad home for this function */ 3247a379bf3dSVille Syrjälä i915_reg_t hsw_chicken_trans_reg(struct drm_i915_private *i915, 3248a379bf3dSVille Syrjälä enum transcoder cpu_transcoder) 3249a379bf3dSVille Syrjälä { 3250a379bf3dSVille Syrjälä return DISPLAY_VER(i915) >= 14 ? 3251a379bf3dSVille Syrjälä MTL_CHICKEN_TRANS(cpu_transcoder) : 3252a379bf3dSVille Syrjälä CHICKEN_TRANS(cpu_transcoder); 3253a379bf3dSVille Syrjälä } 3254a379bf3dSVille Syrjälä 3255379bc100SJani Nikula static i915_reg_t 3256379bc100SJani Nikula gen9_chicken_trans_reg_by_port(struct drm_i915_private *dev_priv, 3257379bc100SJani Nikula enum port port) 3258379bc100SJani Nikula { 325912c4d4c1SVille Syrjälä static const enum transcoder trans[] = { 326012c4d4c1SVille Syrjälä [PORT_A] = TRANSCODER_EDP, 326112c4d4c1SVille Syrjälä [PORT_B] = TRANSCODER_A, 326212c4d4c1SVille Syrjälä [PORT_C] = TRANSCODER_B, 326312c4d4c1SVille Syrjälä [PORT_D] = TRANSCODER_C, 326412c4d4c1SVille Syrjälä [PORT_E] = TRANSCODER_A, 3265379bc100SJani Nikula }; 3266379bc100SJani Nikula 3267005e9537SMatt Roper drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) < 9); 3268379bc100SJani Nikula 32691de143ccSPankaj Bharadiya if (drm_WARN_ON(&dev_priv->drm, port < PORT_A || port > PORT_E)) 3270379bc100SJani Nikula port = PORT_A; 3271379bc100SJani Nikula 327212c4d4c1SVille Syrjälä return CHICKEN_TRANS(trans[port]); 3273379bc100SJani Nikula } 3274379bc100SJani Nikula 3275ede9771dSVille Syrjälä static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, 3276ede9771dSVille Syrjälä struct intel_encoder *encoder, 3277379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 3278379bc100SJani Nikula const struct drm_connector_state *conn_state) 3279379bc100SJani Nikula { 3280379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3281b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3282379bc100SJani Nikula struct drm_connector *connector = conn_state->connector; 3283379bc100SJani Nikula enum port port = encoder->port; 3284e99ba962SImre Deak u32 buf_ctl; 3285379bc100SJani Nikula 3286379bc100SJani Nikula if (!intel_hdmi_handle_sink_scrambling(encoder, connector, 3287379bc100SJani Nikula crtc_state->hdmi_high_tmds_clock_ratio, 3288379bc100SJani Nikula crtc_state->hdmi_scrambling)) 328947bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm, 329047bdb1caSJani Nikula "[CONNECTOR:%d:%s] Failed to configure sink scrambling/TMDS bit clock ratio\n", 3291379bc100SJani Nikula connector->base.id, connector->name); 3292379bc100SJani Nikula 32935bafd85dSVille Syrjälä if (has_buf_trans_select(dev_priv)) 3294e722ab8bSVille Syrjälä hsw_prepare_hdmi_ddi_buffers(encoder, crtc_state); 3295c9b69041SVille Syrjälä 3296b66a8abaSAnkit Nautiyal /* e. Enable D2D Link for C10/C20 Phy */ 3297b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14) 3298b66a8abaSAnkit Nautiyal mtl_ddi_enable_d2d(encoder); 3299b66a8abaSAnkit Nautiyal 3300e722ab8bSVille Syrjälä encoder->set_signal_levels(encoder, crtc_state); 3301c9b69041SVille Syrjälä 3302379bc100SJani Nikula /* Display WA #1143: skl,kbl,cfl */ 330393e7e61eSLucas De Marchi if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) { 3304379bc100SJani Nikula /* 3305379bc100SJani Nikula * For some reason these chicken bits have been 3306379bc100SJani Nikula * stuffed into a transcoder register, event though 3307379bc100SJani Nikula * the bits affect a specific DDI port rather than 3308379bc100SJani Nikula * a specific transcoder. 3309379bc100SJani Nikula */ 3310379bc100SJani Nikula i915_reg_t reg = gen9_chicken_trans_reg_by_port(dev_priv, port); 3311379bc100SJani Nikula u32 val; 3312379bc100SJani Nikula 3313f7960e7fSJani Nikula val = intel_de_read(dev_priv, reg); 3314379bc100SJani Nikula 3315379bc100SJani Nikula if (port == PORT_E) 3316379bc100SJani Nikula val |= DDIE_TRAINING_OVERRIDE_ENABLE | 3317379bc100SJani Nikula DDIE_TRAINING_OVERRIDE_VALUE; 3318379bc100SJani Nikula else 3319379bc100SJani Nikula val |= DDI_TRAINING_OVERRIDE_ENABLE | 3320379bc100SJani Nikula DDI_TRAINING_OVERRIDE_VALUE; 3321379bc100SJani Nikula 3322f7960e7fSJani Nikula intel_de_write(dev_priv, reg, val); 3323f7960e7fSJani Nikula intel_de_posting_read(dev_priv, reg); 3324379bc100SJani Nikula 3325379bc100SJani Nikula udelay(1); 3326379bc100SJani Nikula 3327379bc100SJani Nikula if (port == PORT_E) 3328379bc100SJani Nikula val &= ~(DDIE_TRAINING_OVERRIDE_ENABLE | 3329379bc100SJani Nikula DDIE_TRAINING_OVERRIDE_VALUE); 3330379bc100SJani Nikula else 3331379bc100SJani Nikula val &= ~(DDI_TRAINING_OVERRIDE_ENABLE | 3332379bc100SJani Nikula DDI_TRAINING_OVERRIDE_VALUE); 3333379bc100SJani Nikula 3334f7960e7fSJani Nikula intel_de_write(dev_priv, reg, val); 3335379bc100SJani Nikula } 3336379bc100SJani Nikula 33371e0cb7beSVille Syrjälä intel_ddi_power_up_lanes(encoder, crtc_state); 33381e0cb7beSVille Syrjälä 3339379bc100SJani Nikula /* In HDMI/DVI mode, the port width, and swing/emphasis values 3340379bc100SJani Nikula * are ignored so nothing special needs to be done besides 3341379bc100SJani Nikula * enabling the port. 3342414002f1SImre Deak * 3343414002f1SImre Deak * On ADL_P the PHY link rate and lane count must be programmed but 3344414002f1SImre Deak * these are both 0 for HDMI. 3345b66a8abaSAnkit Nautiyal * 3346b66a8abaSAnkit Nautiyal * But MTL onwards HDMI2.1 is supported and in TMDS mode this 3347b66a8abaSAnkit Nautiyal * is filled with lane count, already set in the crtc_state. 3348b66a8abaSAnkit Nautiyal * The same is required to be filled in PORT_BUF_CTL for C10/20 Phy. 3349379bc100SJani Nikula */ 3350e99ba962SImre Deak buf_ctl = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE; 3351b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14) { 3352b66a8abaSAnkit Nautiyal u8 lane_count = mtl_get_port_width(crtc_state->lane_count); 3353b66a8abaSAnkit Nautiyal u32 port_buf = 0; 3354b66a8abaSAnkit Nautiyal 3355b66a8abaSAnkit Nautiyal port_buf |= XELPDP_PORT_WIDTH(lane_count); 3356b66a8abaSAnkit Nautiyal 3357b66a8abaSAnkit Nautiyal if (dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL) 3358b66a8abaSAnkit Nautiyal port_buf |= XELPDP_PORT_REVERSAL; 3359b66a8abaSAnkit Nautiyal 3360fe4c6ff5SLucas De Marchi intel_de_rmw(dev_priv, XELPDP_PORT_BUF_CTL1(dev_priv, port), 3361b66a8abaSAnkit Nautiyal XELPDP_PORT_WIDTH_MASK | XELPDP_PORT_REVERSAL, port_buf); 3362b66a8abaSAnkit Nautiyal 3363b66a8abaSAnkit Nautiyal buf_ctl |= DDI_PORT_WIDTH(lane_count); 3364d5c7854bSLucas De Marchi 3365d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20) 3366d5c7854bSLucas De Marchi buf_ctl |= XE2LPD_DDI_BUF_D2D_LINK_ENABLE; 33677fcf7558SJani Nikula } else if (IS_ALDERLAKE_P(dev_priv) && intel_encoder_is_tc(encoder)) { 3368e99ba962SImre Deak drm_WARN_ON(&dev_priv->drm, !intel_tc_port_in_legacy_mode(dig_port)); 3369e99ba962SImre Deak buf_ctl |= DDI_BUF_CTL_TC_PHY_OWNERSHIP; 3370e99ba962SImre Deak } 3371b66a8abaSAnkit Nautiyal 3372e99ba962SImre Deak intel_de_write(dev_priv, DDI_BUF_CTL(port), buf_ctl); 3373379bc100SJani Nikula 3374684a37a6SJani Nikula intel_wait_ddi_buf_active(encoder); 3375379bc100SJani Nikula } 3376379bc100SJani Nikula 3377ede9771dSVille Syrjälä static void intel_enable_ddi(struct intel_atomic_state *state, 3378ede9771dSVille Syrjälä struct intel_encoder *encoder, 3379379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 3380379bc100SJani Nikula const struct drm_connector_state *conn_state) 3381379bc100SJani Nikula { 33823607b308SStanislav Lisovskiy struct drm_i915_private *i915 = to_i915(encoder->base.dev); 33833607b308SStanislav Lisovskiy struct intel_crtc *pipe_crtc; 338421fd23acSJani Nikula 3385eed22a46SVille Syrjälä intel_ddi_enable_transcoder_func(encoder, crtc_state); 33867c2fedd7SVille Syrjälä 33878853750dSVinod Govindapillai /* Enable/Disable DP2.0 SDP split config before transcoder */ 33882f092c0cSVinod Govindapillai intel_audio_sdp_split_update(crtc_state); 33898853750dSVinod Govindapillai 33908c66081bSVille Syrjälä intel_enable_transcoder(crtc_state); 339121fd23acSJani Nikula 33926e916b35SImre Deak intel_ddi_wait_for_fec_status(encoder, crtc_state, true); 33936e916b35SImre Deak 33943607b308SStanislav Lisovskiy for_each_intel_crtc_in_pipe_mask_reverse(&i915->drm, pipe_crtc, 33953607b308SStanislav Lisovskiy intel_crtc_joined_pipe_mask(crtc_state)) { 33963607b308SStanislav Lisovskiy const struct intel_crtc_state *pipe_crtc_state = 33973607b308SStanislav Lisovskiy intel_atomic_get_new_crtc_state(state, pipe_crtc); 33983607b308SStanislav Lisovskiy 33993607b308SStanislav Lisovskiy intel_crtc_vblank_on(pipe_crtc_state); 34003607b308SStanislav Lisovskiy } 340121fd23acSJani Nikula 3402379bc100SJani Nikula if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 3403ede9771dSVille Syrjälä intel_enable_ddi_hdmi(state, encoder, crtc_state, conn_state); 3404379bc100SJani Nikula else 3405ede9771dSVille Syrjälä intel_enable_ddi_dp(state, encoder, crtc_state, conn_state); 3406379bc100SJani Nikula 34074c4279a8SSuraj Kandpal intel_hdcp_enable(state, encoder, crtc_state, conn_state); 34087966a93aSVille Syrjälä 3409379bc100SJani Nikula } 3410379bc100SJani Nikula 3411ede9771dSVille Syrjälä static void intel_disable_ddi_dp(struct intel_atomic_state *state, 3412ede9771dSVille Syrjälä struct intel_encoder *encoder, 3413379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state, 3414379bc100SJani Nikula const struct drm_connector_state *old_conn_state) 3415379bc100SJani Nikula { 3416b7d02c3aSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 34177c4631ffSImre Deak struct intel_connector *connector = 34187c4631ffSImre Deak to_intel_connector(old_conn_state->connector); 3419379bc100SJani Nikula 3420379bc100SJani Nikula intel_dp->link_trained = false; 3421379bc100SJani Nikula 3422f28c5950SVille Syrjälä intel_psr_disable(intel_dp, old_crtc_state); 3423379bc100SJani Nikula intel_edp_backlight_off(old_conn_state); 3424379bc100SJani Nikula /* Disable the decompression in DP Sink */ 34257c4631ffSImre Deak intel_dp_sink_disable_decompression(state, 34267c4631ffSImre Deak connector, old_crtc_state); 34271639406aSManasi Navare /* Disable Ignore_MSA bit in DP Sink */ 34281639406aSManasi Navare intel_dp_sink_set_msa_timing_par_ignore_state(intel_dp, old_crtc_state, 34291639406aSManasi Navare false); 3430379bc100SJani Nikula } 3431379bc100SJani Nikula 3432ede9771dSVille Syrjälä static void intel_disable_ddi_hdmi(struct intel_atomic_state *state, 3433ede9771dSVille Syrjälä struct intel_encoder *encoder, 3434379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state, 3435379bc100SJani Nikula const struct drm_connector_state *old_conn_state) 3436379bc100SJani Nikula { 343747bdb1caSJani Nikula struct drm_i915_private *i915 = to_i915(encoder->base.dev); 3438379bc100SJani Nikula struct drm_connector *connector = old_conn_state->connector; 3439379bc100SJani Nikula 3440379bc100SJani Nikula if (!intel_hdmi_handle_sink_scrambling(encoder, connector, 3441379bc100SJani Nikula false, false)) 344247bdb1caSJani Nikula drm_dbg_kms(&i915->drm, 344347bdb1caSJani Nikula "[CONNECTOR:%d:%s] Failed to reset sink scrambling/TMDS bit clock ratio\n", 3444379bc100SJani Nikula connector->base.id, connector->name); 3445379bc100SJani Nikula } 3446379bc100SJani Nikula 3447ede9771dSVille Syrjälä static void intel_disable_ddi(struct intel_atomic_state *state, 3448ede9771dSVille Syrjälä struct intel_encoder *encoder, 3449379bc100SJani Nikula const struct intel_crtc_state *old_crtc_state, 3450379bc100SJani Nikula const struct drm_connector_state *old_conn_state) 3451379bc100SJani Nikula { 3452c598c335SImre Deak intel_tc_port_link_cancel_reset_work(enc_to_dig_port(encoder)); 3453c598c335SImre Deak 3454379bc100SJani Nikula intel_hdcp_disable(to_intel_connector(old_conn_state->connector)); 3455379bc100SJani Nikula 3456379bc100SJani Nikula if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) 3457ede9771dSVille Syrjälä intel_disable_ddi_hdmi(state, encoder, old_crtc_state, 3458ede9771dSVille Syrjälä old_conn_state); 3459379bc100SJani Nikula else 3460ede9771dSVille Syrjälä intel_disable_ddi_dp(state, encoder, old_crtc_state, 3461ede9771dSVille Syrjälä old_conn_state); 3462379bc100SJani Nikula } 3463379bc100SJani Nikula 3464ede9771dSVille Syrjälä static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, 3465ede9771dSVille Syrjälä struct intel_encoder *encoder, 3466379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 3467379bc100SJani Nikula const struct drm_connector_state *conn_state) 3468379bc100SJani Nikula { 34690c06fa15SGwan-gyeong Mun intel_ddi_set_dp_msa(crtc_state, conn_state); 3470379bc100SJani Nikula 347176d45d06SGwan-gyeong Mun intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); 3472379bc100SJani Nikula 3473c0a52f8bSJani Nikula intel_backlight_update(state, encoder, crtc_state, conn_state); 34746306d8dbSHans de Goede drm_connector_update_privacy_screen(conn_state); 3475379bc100SJani Nikula } 3476379bc100SJani Nikula 3477f1c7a36bSSean Paul void intel_ddi_update_pipe(struct intel_atomic_state *state, 3478ede9771dSVille Syrjälä struct intel_encoder *encoder, 3479379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 3480379bc100SJani Nikula const struct drm_connector_state *conn_state) 3481379bc100SJani Nikula { 3482d456512cSRamalingam C 3483f1c7a36bSSean Paul if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && 3484f1c7a36bSSean Paul !intel_encoder_is_mst(encoder)) 3485ede9771dSVille Syrjälä intel_ddi_update_pipe_dp(state, encoder, crtc_state, 3486ede9771dSVille Syrjälä conn_state); 3487379bc100SJani Nikula 3488ede9771dSVille Syrjälä intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state); 3489379bc100SJani Nikula } 3490379bc100SJani Nikula 349127ac123bSImre Deak void intel_ddi_update_active_dpll(struct intel_atomic_state *state, 349227ac123bSImre Deak struct intel_encoder *encoder, 349327ac123bSImre Deak struct intel_crtc *crtc) 349427ac123bSImre Deak { 349527ac123bSImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev); 34962b8ad19dSVille Syrjälä const struct intel_crtc_state *crtc_state = 349727ac123bSImre Deak intel_atomic_get_new_crtc_state(state, crtc); 34982b8ad19dSVille Syrjälä struct intel_crtc *pipe_crtc; 349927ac123bSImre Deak 350062618c7fSMika Kahola /* FIXME: Add MTL pll_mgr */ 35017fcf7558SJani Nikula if (DISPLAY_VER(i915) >= 14 || !intel_encoder_is_tc(encoder)) 350227ac123bSImre Deak return; 350327ac123bSImre Deak 35042b8ad19dSVille Syrjälä for_each_intel_crtc_in_pipe_mask(&i915->drm, pipe_crtc, 35052b8ad19dSVille Syrjälä intel_crtc_joined_pipe_mask(crtc_state)) 35062b8ad19dSVille Syrjälä intel_update_active_dpll(state, pipe_crtc, encoder); 350727ac123bSImre Deak } 350827ac123bSImre Deak 3509379bc100SJani Nikula static void 3510ede9771dSVille Syrjälä intel_ddi_pre_pll_enable(struct intel_atomic_state *state, 3511ede9771dSVille Syrjälä struct intel_encoder *encoder, 3512379bc100SJani Nikula const struct intel_crtc_state *crtc_state, 3513379bc100SJani Nikula const struct drm_connector_state *conn_state) 3514379bc100SJani Nikula { 3515379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3516b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 35177fcf7558SJani Nikula bool is_tc_port = intel_encoder_is_tc(encoder); 3518379bc100SJani Nikula 35190f752b21SImre Deak if (is_tc_port) { 3520da8c3cdbSStanislav Lisovskiy struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 35210f752b21SImre Deak 352224a7bfe0SImre Deak intel_tc_port_get_link(dig_port, crtc_state->lane_count); 3523da8c3cdbSStanislav Lisovskiy intel_ddi_update_active_dpll(state, encoder, crtc); 35240f752b21SImre Deak } 35250f752b21SImre Deak 3526637c7aa2SImre Deak main_link_aux_power_domain_get(dig_port, crtc_state); 3527379bc100SJani Nikula 352811a89708SImre Deak if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port)) 35299d44dcb9SLucas De Marchi /* 35309d44dcb9SLucas De Marchi * Program the lane count for static/dynamic connections on 35319d44dcb9SLucas De Marchi * Type-C ports. Skip this step for TBT. 35329d44dcb9SLucas De Marchi */ 35339d44dcb9SLucas De Marchi intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count); 35342446e1d6SMatt Roper else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 3535ba07c3edSVille Syrjälä bxt_dpio_phy_set_lane_optim_mask(encoder, 3536379bc100SJani Nikula crtc_state->lane_lat_optim_mask); 3537379bc100SJani Nikula } 3538379bc100SJani Nikula 353955223c3bSImre Deak static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder) 354055223c3bSImre Deak { 354155223c3bSImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev); 35427fcf7558SJani Nikula enum tc_port tc_port = intel_encoder_to_tc(encoder); 354355223c3bSImre Deak int ln; 354455223c3bSImre Deak 354589cb0ba4SImre Deak for (ln = 0; ln < 2; ln++) 3546b8ed5533SImre Deak intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0); 354755223c3bSImre Deak } 354855223c3bSImre Deak 354923ef6194SJosé Roberto de Souza static void mtl_ddi_prepare_link_retrain(struct intel_dp *intel_dp, 355023ef6194SJosé Roberto de Souza const struct intel_crtc_state *crtc_state) 355123ef6194SJosé Roberto de Souza { 355223ef6194SJosé Roberto de Souza struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); 355323ef6194SJosé Roberto de Souza struct intel_encoder *encoder = &dig_port->base; 355423ef6194SJosé Roberto de Souza struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 355523ef6194SJosé Roberto de Souza enum port port = encoder->port; 355623ef6194SJosé Roberto de Souza u32 dp_tp_ctl; 355723ef6194SJosé Roberto de Souza 355823ef6194SJosé Roberto de Souza /* 355923ef6194SJosé Roberto de Souza * TODO: To train with only a different voltage swing entry is not 356023ef6194SJosé Roberto de Souza * necessary disable and enable port 356123ef6194SJosé Roberto de Souza */ 356223ef6194SJosé Roberto de Souza dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 356323ef6194SJosé Roberto de Souza if (dp_tp_ctl & DP_TP_CTL_ENABLE) 356423ef6194SJosé Roberto de Souza mtl_disable_ddi_buf(encoder, crtc_state); 356523ef6194SJosé Roberto de Souza 356623ef6194SJosé Roberto de Souza /* 6.d Configure and enable DP_TP_CTL with link training pattern 1 selected */ 356723ef6194SJosé Roberto de Souza dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1; 356823ef6194SJosé Roberto de Souza if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) { 356923ef6194SJosé Roberto de Souza dp_tp_ctl |= DP_TP_CTL_MODE_MST; 357023ef6194SJosé Roberto de Souza } else { 357123ef6194SJosé Roberto de Souza dp_tp_ctl |= DP_TP_CTL_MODE_SST; 35723072a24cSVille Syrjälä if (crtc_state->enhanced_framing) 357323ef6194SJosé Roberto de Souza dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; 357423ef6194SJosé Roberto de Souza } 357523ef6194SJosé Roberto de Souza intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl); 357623ef6194SJosé Roberto de Souza intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 357723ef6194SJosé Roberto de Souza 357823ef6194SJosé Roberto de Souza /* 6.f Enable D2D Link */ 357923ef6194SJosé Roberto de Souza mtl_ddi_enable_d2d(encoder); 358023ef6194SJosé Roberto de Souza 358123ef6194SJosé Roberto de Souza /* 6.g Configure voltage swing and related IO settings */ 358223ef6194SJosé Roberto de Souza encoder->set_signal_levels(encoder, crtc_state); 358323ef6194SJosé Roberto de Souza 358423ef6194SJosé Roberto de Souza /* 6.h Configure PORT_BUF_CTL1 */ 358523ef6194SJosé Roberto de Souza mtl_port_buf_ctl_program(encoder, crtc_state); 358623ef6194SJosé Roberto de Souza 358723ef6194SJosé Roberto de Souza /* 6.i Configure and enable DDI_CTL_DE to start sending valid data to port slice */ 358823ef6194SJosé Roberto de Souza intel_dp->DP |= DDI_BUF_CTL_ENABLE; 3589d5c7854bSLucas De Marchi if (DISPLAY_VER(dev_priv) >= 20) 3590d5c7854bSLucas De Marchi intel_dp->DP |= XE2LPD_DDI_BUF_D2D_LINK_ENABLE; 3591d5c7854bSLucas De Marchi 359223ef6194SJosé Roberto de Souza intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); 359323ef6194SJosé Roberto de Souza intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); 359423ef6194SJosé Roberto de Souza 359523ef6194SJosé Roberto de Souza /* 6.j Poll for PORT_BUF_CTL Idle Status == 0, timeout after 100 us */ 3596684a37a6SJani Nikula intel_wait_ddi_buf_active(encoder); 359723ef6194SJosé Roberto de Souza } 359823ef6194SJosé Roberto de Souza 3599a621860aSVille Syrjälä static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, 3600a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state) 3601379bc100SJani Nikula { 360255223c3bSImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); 360355223c3bSImre Deak struct intel_encoder *encoder = &dig_port->base; 3604ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3605ef79fafeSVille Syrjälä enum port port = encoder->port; 360635ac28a8SLucas De Marchi u32 dp_tp_ctl, ddi_buf_ctl; 3607379bc100SJani Nikula bool wait = false; 3608379bc100SJani Nikula 3609ef79fafeSVille Syrjälä dp_tp_ctl = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 361035ac28a8SLucas De Marchi 361135ac28a8SLucas De Marchi if (dp_tp_ctl & DP_TP_CTL_ENABLE) { 3612f7960e7fSJani Nikula ddi_buf_ctl = intel_de_read(dev_priv, DDI_BUF_CTL(port)); 361335ac28a8SLucas De Marchi if (ddi_buf_ctl & DDI_BUF_CTL_ENABLE) { 3614f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_CTL(port), 361535ac28a8SLucas De Marchi ddi_buf_ctl & ~DDI_BUF_CTL_ENABLE); 3616379bc100SJani Nikula wait = true; 3617379bc100SJani Nikula } 3618379bc100SJani Nikula 36198c042949SVille Syrjälä dp_tp_ctl &= ~DP_TP_CTL_ENABLE; 3620ef79fafeSVille Syrjälä intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl); 3621ef79fafeSVille Syrjälä intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 3622379bc100SJani Nikula 3623379bc100SJani Nikula if (wait) 3624379bc100SJani Nikula intel_wait_ddi_buf_idle(dev_priv, port); 3625379bc100SJani Nikula } 3626379bc100SJani Nikula 3627963501bdSImre Deak dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1; 3628a621860aSVille Syrjälä if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) { 362935ac28a8SLucas De Marchi dp_tp_ctl |= DP_TP_CTL_MODE_MST; 3630a621860aSVille Syrjälä } else { 363135ac28a8SLucas De Marchi dp_tp_ctl |= DP_TP_CTL_MODE_SST; 36323072a24cSVille Syrjälä if (crtc_state->enhanced_framing) 363335ac28a8SLucas De Marchi dp_tp_ctl |= DP_TP_CTL_ENHANCED_FRAME_ENABLE; 3634379bc100SJani Nikula } 3635ef79fafeSVille Syrjälä intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), dp_tp_ctl); 3636ef79fafeSVille Syrjälä intel_de_posting_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 3637379bc100SJani Nikula 363855223c3bSImre Deak if (IS_ALDERLAKE_P(dev_priv) && 363955223c3bSImre Deak (intel_tc_port_in_dp_alt_mode(dig_port) || intel_tc_port_in_legacy_mode(dig_port))) 364055223c3bSImre Deak adlp_tbt_to_dp_alt_switch_wa(encoder); 364155223c3bSImre Deak 3642379bc100SJani Nikula intel_dp->DP |= DDI_BUF_CTL_ENABLE; 3643f7960e7fSJani Nikula intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); 3644f7960e7fSJani Nikula intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); 3645379bc100SJani Nikula 3646684a37a6SJani Nikula intel_wait_ddi_buf_active(encoder); 3647379bc100SJani Nikula } 3648379bc100SJani Nikula 3649eee3f911SVille Syrjälä static void intel_ddi_set_link_train(struct intel_dp *intel_dp, 3650a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state, 3651eee3f911SVille Syrjälä u8 dp_train_pat) 3652eee3f911SVille Syrjälä { 3653ef79fafeSVille Syrjälä struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; 3654ef79fafeSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3655eee3f911SVille Syrjälä u32 temp; 3656eee3f911SVille Syrjälä 3657ef79fafeSVille Syrjälä temp = intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, crtc_state)); 3658eee3f911SVille Syrjälä 3659eee3f911SVille Syrjälä temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; 36606777a855SImre Deak switch (intel_dp_training_pattern_symbol(dp_train_pat)) { 3661eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_DISABLE: 3662eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_NORMAL; 3663eee3f911SVille Syrjälä break; 3664eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_1: 3665eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT1; 3666eee3f911SVille Syrjälä break; 3667eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_2: 3668eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT2; 3669eee3f911SVille Syrjälä break; 3670eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_3: 3671eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT3; 3672eee3f911SVille Syrjälä break; 3673eee3f911SVille Syrjälä case DP_TRAINING_PATTERN_4: 3674eee3f911SVille Syrjälä temp |= DP_TP_CTL_LINK_TRAIN_PAT4; 3675eee3f911SVille Syrjälä break; 3676eee3f911SVille Syrjälä } 3677eee3f911SVille Syrjälä 3678ef79fafeSVille Syrjälä intel_de_write(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), temp); 3679eee3f911SVille Syrjälä } 3680eee3f911SVille Syrjälä 3681a621860aSVille Syrjälä static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp, 3682a621860aSVille Syrjälä const struct intel_crtc_state *crtc_state) 36838fdda385SVille Syrjälä { 36848fdda385SVille Syrjälä struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; 36858fdda385SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 36868fdda385SVille Syrjälä enum port port = encoder->port; 36878fdda385SVille Syrjälä 36888910d8b7SAndrzej Hajda intel_de_rmw(dev_priv, dp_tp_ctl_reg(encoder, crtc_state), 36898910d8b7SAndrzej Hajda DP_TP_CTL_LINK_TRAIN_MASK, DP_TP_CTL_LINK_TRAIN_IDLE); 36908fdda385SVille Syrjälä 36918fdda385SVille Syrjälä /* 36928fdda385SVille Syrjälä * Until TGL on PORT_A we can have only eDP in SST mode. There the only 36938fdda385SVille Syrjälä * reason we need to set idle transmission mode is to work around a HW 36948fdda385SVille Syrjälä * issue where we enable the pipe while not in idle link-training mode. 36958fdda385SVille Syrjälä * In this case there is requirement to wait for a minimum number of 36968fdda385SVille Syrjälä * idle patterns to be sent. 36978fdda385SVille Syrjälä */ 3698005e9537SMatt Roper if (port == PORT_A && DISPLAY_VER(dev_priv) < 12) 36998fdda385SVille Syrjälä return; 37008fdda385SVille Syrjälä 3701ef79fafeSVille Syrjälä if (intel_de_wait_for_set(dev_priv, 3702ef79fafeSVille Syrjälä dp_tp_status_reg(encoder, crtc_state), 37032c215a93SShekhar Chauhan DP_TP_STATUS_IDLE_DONE, 2)) 37048fdda385SVille Syrjälä drm_err(&dev_priv->drm, 37058fdda385SVille Syrjälä "Timed out waiting for DP idle patterns\n"); 37068fdda385SVille Syrjälä } 37078fdda385SVille Syrjälä 3708379bc100SJani Nikula static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv, 3709379bc100SJani Nikula enum transcoder cpu_transcoder) 3710379bc100SJani Nikula { 3711379bc100SJani Nikula if (cpu_transcoder == TRANSCODER_EDP) 3712379bc100SJani Nikula return false; 3713379bc100SJani Nikula 3714615a7724SAnshuman Gupta if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_AUDIO_MMIO)) 3715379bc100SJani Nikula return false; 3716379bc100SJani Nikula 3717f7960e7fSJani Nikula return intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD) & 3718379bc100SJani Nikula AUDIO_OUTPUT_ENABLE(cpu_transcoder); 3719379bc100SJani Nikula } 3720379bc100SJani Nikula 372146bdb77dSVille Syrjälä static int tgl_ddi_min_voltage_level(const struct intel_crtc_state *crtc_state) 372246bdb77dSVille Syrjälä { 372346bdb77dSVille Syrjälä if (crtc_state->port_clock > 594000) 372446bdb77dSVille Syrjälä return 2; 372546bdb77dSVille Syrjälä else 372646bdb77dSVille Syrjälä return 0; 372746bdb77dSVille Syrjälä } 372846bdb77dSVille Syrjälä 372946bdb77dSVille Syrjälä static int jsl_ddi_min_voltage_level(const struct intel_crtc_state *crtc_state) 373046bdb77dSVille Syrjälä { 373146bdb77dSVille Syrjälä if (crtc_state->port_clock > 594000) 373246bdb77dSVille Syrjälä return 3; 373346bdb77dSVille Syrjälä else 373446bdb77dSVille Syrjälä return 0; 373546bdb77dSVille Syrjälä } 373646bdb77dSVille Syrjälä 373746bdb77dSVille Syrjälä static int icl_ddi_min_voltage_level(const struct intel_crtc_state *crtc_state) 373846bdb77dSVille Syrjälä { 373946bdb77dSVille Syrjälä if (crtc_state->port_clock > 594000) 374046bdb77dSVille Syrjälä return 1; 374146bdb77dSVille Syrjälä else 374246bdb77dSVille Syrjälä return 0; 374346bdb77dSVille Syrjälä } 374446bdb77dSVille Syrjälä 37458cd53c6bSVille Syrjälä void intel_ddi_compute_min_voltage_level(struct intel_crtc_state *crtc_state) 3746379bc100SJani Nikula { 37478cd53c6bSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 37488cd53c6bSVille Syrjälä 37490656afabSVille Syrjälä if (DISPLAY_VER(dev_priv) >= 14) 37500656afabSVille Syrjälä crtc_state->min_voltage_level = icl_ddi_min_voltage_level(crtc_state); 37510656afabSVille Syrjälä else if (DISPLAY_VER(dev_priv) >= 12) 375246bdb77dSVille Syrjälä crtc_state->min_voltage_level = tgl_ddi_min_voltage_level(crtc_state); 375346bdb77dSVille Syrjälä else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) 375446bdb77dSVille Syrjälä crtc_state->min_voltage_level = jsl_ddi_min_voltage_level(crtc_state); 375546bdb77dSVille Syrjälä else if (DISPLAY_VER(dev_priv) >= 11) 375646bdb77dSVille Syrjälä crtc_state->min_voltage_level = icl_ddi_min_voltage_level(crtc_state); 3757379bc100SJani Nikula } 3758379bc100SJani Nikula 3759dc5b8ed5SVille Syrjälä static enum transcoder bdw_transcoder_master_readout(struct drm_i915_private *dev_priv, 376002d8ea47SVille Syrjälä enum transcoder cpu_transcoder) 376102d8ea47SVille Syrjälä { 3762dc5b8ed5SVille Syrjälä u32 master_select; 376302d8ea47SVille Syrjälä 3764005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 376576f1b2b1SJani Nikula u32 ctl2 = intel_de_read(dev_priv, 376676f1b2b1SJani Nikula TRANS_DDI_FUNC_CTL2(dev_priv, cpu_transcoder)); 376702d8ea47SVille Syrjälä 376802d8ea47SVille Syrjälä if ((ctl2 & PORT_SYNC_MODE_ENABLE) == 0) 376902d8ea47SVille Syrjälä return INVALID_TRANSCODER; 377002d8ea47SVille Syrjälä 3771d4d7d9caSVille Syrjälä master_select = REG_FIELD_GET(PORT_SYNC_MODE_MASTER_SELECT_MASK, ctl2); 3772dc5b8ed5SVille Syrjälä } else { 3773b092d6adSJani Nikula u32 ctl = intel_de_read(dev_priv, 3774b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); 3775dc5b8ed5SVille Syrjälä 3776dc5b8ed5SVille Syrjälä if ((ctl & TRANS_DDI_PORT_SYNC_ENABLE) == 0) 3777dc5b8ed5SVille Syrjälä return INVALID_TRANSCODER; 3778dc5b8ed5SVille Syrjälä 3779dc5b8ed5SVille Syrjälä master_select = REG_FIELD_GET(TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK, ctl); 3780dc5b8ed5SVille Syrjälä } 378102d8ea47SVille Syrjälä 378202d8ea47SVille Syrjälä if (master_select == 0) 378302d8ea47SVille Syrjälä return TRANSCODER_EDP; 378402d8ea47SVille Syrjälä else 378502d8ea47SVille Syrjälä return master_select - 1; 378602d8ea47SVille Syrjälä } 378702d8ea47SVille Syrjälä 3788dc5b8ed5SVille Syrjälä static void bdw_get_trans_port_sync_config(struct intel_crtc_state *crtc_state) 378902d8ea47SVille Syrjälä { 379002d8ea47SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 379102d8ea47SVille Syrjälä u32 transcoders = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | 379202d8ea47SVille Syrjälä BIT(TRANSCODER_C) | BIT(TRANSCODER_D); 379302d8ea47SVille Syrjälä enum transcoder cpu_transcoder; 379402d8ea47SVille Syrjälä 379502d8ea47SVille Syrjälä crtc_state->master_transcoder = 3796dc5b8ed5SVille Syrjälä bdw_transcoder_master_readout(dev_priv, crtc_state->cpu_transcoder); 379702d8ea47SVille Syrjälä 379802d8ea47SVille Syrjälä for_each_cpu_transcoder_masked(dev_priv, cpu_transcoder, transcoders) { 379902d8ea47SVille Syrjälä enum intel_display_power_domain power_domain; 380002d8ea47SVille Syrjälä intel_wakeref_t trans_wakeref; 380102d8ea47SVille Syrjälä 380202d8ea47SVille Syrjälä power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder); 380302d8ea47SVille Syrjälä trans_wakeref = intel_display_power_get_if_enabled(dev_priv, 380402d8ea47SVille Syrjälä power_domain); 380502d8ea47SVille Syrjälä 380602d8ea47SVille Syrjälä if (!trans_wakeref) 380702d8ea47SVille Syrjälä continue; 380802d8ea47SVille Syrjälä 3809dc5b8ed5SVille Syrjälä if (bdw_transcoder_master_readout(dev_priv, cpu_transcoder) == 381002d8ea47SVille Syrjälä crtc_state->cpu_transcoder) 381102d8ea47SVille Syrjälä crtc_state->sync_mode_slaves_mask |= BIT(cpu_transcoder); 381202d8ea47SVille Syrjälä 381302d8ea47SVille Syrjälä intel_display_power_put(dev_priv, power_domain, trans_wakeref); 381402d8ea47SVille Syrjälä } 381502d8ea47SVille Syrjälä 381602d8ea47SVille Syrjälä drm_WARN_ON(&dev_priv->drm, 381702d8ea47SVille Syrjälä crtc_state->master_transcoder != INVALID_TRANSCODER && 381802d8ea47SVille Syrjälä crtc_state->sync_mode_slaves_mask); 381902d8ea47SVille Syrjälä } 382002d8ea47SVille Syrjälä 38210385eceaSManasi Navare static void intel_ddi_read_func_ctl(struct intel_encoder *encoder, 3822379bc100SJani Nikula struct intel_crtc_state *pipe_config) 3823379bc100SJani Nikula { 3824379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 3825f15f01a7SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); 3826379bc100SJani Nikula enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; 3827a44289b9SUma Shankar struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 3828379bc100SJani Nikula u32 temp, flags = 0; 3829379bc100SJani Nikula 3830b092d6adSJani Nikula temp = intel_de_read(dev_priv, 3831b092d6adSJani Nikula TRANS_DDI_FUNC_CTL(dev_priv, cpu_transcoder)); 3832379bc100SJani Nikula if (temp & TRANS_DDI_PHSYNC) 3833379bc100SJani Nikula flags |= DRM_MODE_FLAG_PHSYNC; 3834379bc100SJani Nikula else 3835379bc100SJani Nikula flags |= DRM_MODE_FLAG_NHSYNC; 3836379bc100SJani Nikula if (temp & TRANS_DDI_PVSYNC) 3837379bc100SJani Nikula flags |= DRM_MODE_FLAG_PVSYNC; 3838379bc100SJani Nikula else 3839379bc100SJani Nikula flags |= DRM_MODE_FLAG_NVSYNC; 3840379bc100SJani Nikula 38411326a92cSMaarten Lankhorst pipe_config->hw.adjusted_mode.flags |= flags; 3842379bc100SJani Nikula 3843379bc100SJani Nikula switch (temp & TRANS_DDI_BPC_MASK) { 3844379bc100SJani Nikula case TRANS_DDI_BPC_6: 3845379bc100SJani Nikula pipe_config->pipe_bpp = 18; 3846379bc100SJani Nikula break; 3847379bc100SJani Nikula case TRANS_DDI_BPC_8: 3848379bc100SJani Nikula pipe_config->pipe_bpp = 24; 3849379bc100SJani Nikula break; 3850379bc100SJani Nikula case TRANS_DDI_BPC_10: 3851379bc100SJani Nikula pipe_config->pipe_bpp = 30; 3852379bc100SJani Nikula break; 3853379bc100SJani Nikula case TRANS_DDI_BPC_12: 3854379bc100SJani Nikula pipe_config->pipe_bpp = 36; 3855379bc100SJani Nikula break; 3856379bc100SJani Nikula default: 3857379bc100SJani Nikula break; 3858379bc100SJani Nikula } 3859379bc100SJani Nikula 3860379bc100SJani Nikula switch (temp & TRANS_DDI_MODE_SELECT_MASK) { 3861379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_HDMI: 3862379bc100SJani Nikula pipe_config->has_hdmi_sink = true; 3863379bc100SJani Nikula 3864379bc100SJani Nikula pipe_config->infoframes.enable |= 3865379bc100SJani Nikula intel_hdmi_infoframes_enabled(encoder, pipe_config); 3866379bc100SJani Nikula 3867379bc100SJani Nikula if (pipe_config->infoframes.enable) 3868379bc100SJani Nikula pipe_config->has_infoframe = true; 3869379bc100SJani Nikula 3870379bc100SJani Nikula if (temp & TRANS_DDI_HDMI_SCRAMBLING) 3871379bc100SJani Nikula pipe_config->hdmi_scrambling = true; 3872379bc100SJani Nikula if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE) 3873379bc100SJani Nikula pipe_config->hdmi_high_tmds_clock_ratio = true; 3874df561f66SGustavo A. R. Silva fallthrough; 3875379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DVI: 3876379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI); 3877b66a8abaSAnkit Nautiyal if (DISPLAY_VER(dev_priv) >= 14) 3878b66a8abaSAnkit Nautiyal pipe_config->lane_count = 3879b66a8abaSAnkit Nautiyal ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; 3880b66a8abaSAnkit Nautiyal else 3881379bc100SJani Nikula pipe_config->lane_count = 4; 3882379bc100SJani Nikula break; 3883379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DP_SST: 3884379bc100SJani Nikula if (encoder->type == INTEL_OUTPUT_EDP) 3885379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_EDP); 3886379bc100SJani Nikula else 3887379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_DP); 3888379bc100SJani Nikula pipe_config->lane_count = 3889379bc100SJani Nikula ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; 38906149cb68SVille Syrjälä 38915cd06644SVille Syrjälä intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, 38925cd06644SVille Syrjälä &pipe_config->dp_m_n); 38935cd06644SVille Syrjälä intel_cpu_transcoder_get_m2_n2(crtc, cpu_transcoder, 38946149cb68SVille Syrjälä &pipe_config->dp_m2_n2); 38958aa940c8SMaarten Lankhorst 38963072a24cSVille Syrjälä pipe_config->enhanced_framing = 38973072a24cSVille Syrjälä intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) & 38983072a24cSVille Syrjälä DP_TP_CTL_ENHANCED_FRAME_ENABLE; 38993072a24cSVille Syrjälä 39003dfeb80bSVille Syrjälä if (DISPLAY_VER(dev_priv) >= 11) 39018aa940c8SMaarten Lankhorst pipe_config->fec_enable = 39023dfeb80bSVille Syrjälä intel_de_read(dev_priv, 39033dfeb80bSVille Syrjälä dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE; 39048aa940c8SMaarten Lankhorst 39057ffa2f27SJani Nikula if (dig_port->lspcon.active && intel_dp_has_hdmi_sink(&dig_port->dp)) 3906a44289b9SUma Shankar pipe_config->infoframes.enable |= 3907a44289b9SUma Shankar intel_lspcon_infoframes_enabled(encoder, pipe_config); 3908a44289b9SUma Shankar else 3909dee66f3eSGwan-gyeong Mun pipe_config->infoframes.enable |= 3910dee66f3eSGwan-gyeong Mun intel_hdmi_infoframes_enabled(encoder, pipe_config); 3911379bc100SJani Nikula break; 391265213594SJani Nikula case TRANS_DDI_MODE_SELECT_FDI_OR_128B132B: 391365213594SJani Nikula if (!HAS_DP20(dev_priv)) { 391465213594SJani Nikula /* FDI */ 391565213594SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_ANALOG); 39163072a24cSVille Syrjälä pipe_config->enhanced_framing = 39173072a24cSVille Syrjälä intel_de_read(dev_priv, dp_tp_ctl_reg(encoder, pipe_config)) & 39183072a24cSVille Syrjälä DP_TP_CTL_ENHANCED_FRAME_ENABLE; 391965213594SJani Nikula break; 392065213594SJani Nikula } 392165213594SJani Nikula fallthrough; /* 128b/132b */ 3922379bc100SJani Nikula case TRANS_DDI_MODE_SELECT_DP_MST: 3923379bc100SJani Nikula pipe_config->output_types |= BIT(INTEL_OUTPUT_DP_MST); 3924379bc100SJani Nikula pipe_config->lane_count = 3925379bc100SJani Nikula ((temp & DDI_PORT_WIDTH_MASK) >> DDI_PORT_WIDTH_SHIFT) + 1; 39266671c367SJosé Roberto de Souza 3927005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 12) 39286671c367SJosé Roberto de Souza pipe_config->mst_master_transcoder = 39296671c367SJosé Roberto de Souza REG_FIELD_GET(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, temp); 39306671c367SJosé Roberto de Souza 39315cd06644SVille Syrjälä intel_cpu_transcoder_get_m1_n1(crtc, cpu_transcoder, 39325cd06644SVille Syrjälä &pipe_config->dp_m_n); 3933dee66f3eSGwan-gyeong Mun 3934cbbfe915SVille Syrjälä if (DISPLAY_VER(dev_priv) >= 11) 3935cbbfe915SVille Syrjälä pipe_config->fec_enable = 3936cbbfe915SVille Syrjälä intel_de_read(dev_priv, 3937cbbfe915SVille Syrjälä dp_tp_ctl_reg(encoder, pipe_config)) & DP_TP_CTL_FEC_ENABLE; 3938cbbfe915SVille Syrjälä 3939dee66f3eSGwan-gyeong Mun pipe_config->infoframes.enable |= 3940dee66f3eSGwan-gyeong Mun intel_hdmi_infoframes_enabled(encoder, pipe_config); 3941379bc100SJani Nikula break; 3942379bc100SJani Nikula default: 3943379bc100SJani Nikula break; 3944379bc100SJani Nikula } 39450385eceaSManasi Navare } 39460385eceaSManasi Navare 3947351221ffSVille Syrjälä static void intel_ddi_get_config(struct intel_encoder *encoder, 39480385eceaSManasi Navare struct intel_crtc_state *pipe_config) 39490385eceaSManasi Navare { 39500385eceaSManasi Navare struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 39510385eceaSManasi Navare enum transcoder cpu_transcoder = pipe_config->cpu_transcoder; 39520385eceaSManasi Navare 39530385eceaSManasi Navare /* XXX: DSI transcoder paranoia */ 39540385eceaSManasi Navare if (drm_WARN_ON(&dev_priv->drm, transcoder_is_dsi(cpu_transcoder))) 39550385eceaSManasi Navare return; 39560385eceaSManasi Navare 39570385eceaSManasi Navare intel_ddi_read_func_ctl(encoder, pipe_config); 3958379bc100SJani Nikula 39595b616a29SJani Nikula intel_ddi_mso_get_config(encoder, pipe_config); 39605b616a29SJani Nikula 3961379bc100SJani Nikula pipe_config->has_audio = 3962379bc100SJani Nikula intel_ddi_is_audio_enabled(dev_priv, cpu_transcoder); 3963379bc100SJani Nikula 3964822e5ae7SVille Syrjälä if (encoder->type == INTEL_OUTPUT_EDP) 3965822e5ae7SVille Syrjälä intel_edp_fixup_vbt_bpp(encoder, pipe_config->pipe_bpp); 3966379bc100SJani Nikula 3967351221ffSVille Syrjälä ddi_dotclock_get(pipe_config); 3968379bc100SJani Nikula 39692446e1d6SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 3970379bc100SJani Nikula pipe_config->lane_lat_optim_mask = 3971ba07c3edSVille Syrjälä bxt_dpio_phy_get_lane_lat_optim_mask(encoder); 3972379bc100SJani Nikula 39738cd53c6bSVille Syrjälä intel_ddi_compute_min_voltage_level(pipe_config); 3974379bc100SJani Nikula 3975379bc100SJani Nikula intel_hdmi_read_gcp_infoframe(encoder, pipe_config); 3976379bc100SJani Nikula 3977379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config, 3978379bc100SJani Nikula HDMI_INFOFRAME_TYPE_AVI, 3979379bc100SJani Nikula &pipe_config->infoframes.avi); 3980379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config, 3981379bc100SJani Nikula HDMI_INFOFRAME_TYPE_SPD, 3982379bc100SJani Nikula &pipe_config->infoframes.spd); 3983379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config, 3984379bc100SJani Nikula HDMI_INFOFRAME_TYPE_VENDOR, 3985379bc100SJani Nikula &pipe_config->infoframes.hdmi); 3986379bc100SJani Nikula intel_read_infoframe(encoder, pipe_config, 3987379bc100SJani Nikula HDMI_INFOFRAME_TYPE_DRM, 3988379bc100SJani Nikula &pipe_config->infoframes.drm); 398902d8ea47SVille Syrjälä 3990005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 8) 3991dc5b8ed5SVille Syrjälä bdw_get_trans_port_sync_config(pipe_config); 3992dee66f3eSGwan-gyeong Mun 399316448cf4SJouni Högander intel_psr_get_config(encoder, pipe_config); 399416448cf4SJouni Högander 3995dee66f3eSGwan-gyeong Mun intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA); 39962c3928e4SGwan-gyeong Mun intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); 39978845021bSMitul Golani intel_read_dp_sdp(encoder, pipe_config, DP_SDP_ADAPTIVE_SYNC); 399878b772e1SJosé Roberto de Souza 399961a60df6SVille Syrjälä intel_audio_codec_get_config(encoder, pipe_config); 4000379bc100SJani Nikula } 4001379bc100SJani Nikula 4002351221ffSVille Syrjälä void intel_ddi_get_clock(struct intel_encoder *encoder, 4003351221ffSVille Syrjälä struct intel_crtc_state *crtc_state, 4004351221ffSVille Syrjälä struct intel_shared_dpll *pll) 4005351221ffSVille Syrjälä { 4006351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 4007351221ffSVille Syrjälä enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; 4008351221ffSVille Syrjälä struct icl_port_dpll *port_dpll = &crtc_state->icl_port_dplls[port_dpll_id]; 4009351221ffSVille Syrjälä bool pll_active; 4010351221ffSVille Syrjälä 4011086877a1SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll)) 4012086877a1SVille Syrjälä return; 4013086877a1SVille Syrjälä 4014351221ffSVille Syrjälä port_dpll->pll = pll; 4015351221ffSVille Syrjälä pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state); 4016351221ffSVille Syrjälä drm_WARN_ON(&i915->drm, !pll_active); 4017351221ffSVille Syrjälä 4018351221ffSVille Syrjälä icl_set_active_port_dpll(crtc_state, port_dpll_id); 4019351221ffSVille Syrjälä 4020351221ffSVille Syrjälä crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll, 4021351221ffSVille Syrjälä &crtc_state->dpll_hw_state); 4022351221ffSVille Syrjälä } 4023351221ffSVille Syrjälä 402451390cc0SRadhakrishna Sripada static void mtl_ddi_get_config(struct intel_encoder *encoder, 402551390cc0SRadhakrishna Sripada struct intel_crtc_state *crtc_state) 402651390cc0SRadhakrishna Sripada { 40277dee06bcSMika Kahola struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 402851390cc0SRadhakrishna Sripada 40297dee06bcSMika Kahola if (intel_tc_port_in_tbt_alt_mode(dig_port)) { 40307dee06bcSMika Kahola crtc_state->port_clock = intel_mtl_tbt_calc_port_clock(encoder); 4031929f527aSMika Kahola } else { 40324bbb8932SVille Syrjälä intel_cx0pll_readout_hw_state(encoder, &crtc_state->dpll_hw_state.cx0pll); 40334bbb8932SVille Syrjälä crtc_state->port_clock = intel_cx0pll_calc_port_clock(encoder, &crtc_state->dpll_hw_state.cx0pll); 4034929f527aSMika Kahola } 4035929f527aSMika Kahola 403651390cc0SRadhakrishna Sripada intel_ddi_get_config(encoder, crtc_state); 403751390cc0SRadhakrishna Sripada } 403851390cc0SRadhakrishna Sripada 4039865b73eaSMatt Roper static void dg2_ddi_get_config(struct intel_encoder *encoder, 4040865b73eaSMatt Roper struct intel_crtc_state *crtc_state) 4041865b73eaSMatt Roper { 40424bbb8932SVille Syrjälä intel_mpllb_readout_hw_state(encoder, &crtc_state->dpll_hw_state.mpllb); 40434bbb8932SVille Syrjälä crtc_state->port_clock = intel_mpllb_calc_port_clock(encoder, &crtc_state->dpll_hw_state.mpllb); 4044865b73eaSMatt Roper 4045865b73eaSMatt Roper intel_ddi_get_config(encoder, crtc_state); 4046865b73eaSMatt Roper } 4047865b73eaSMatt Roper 4048351221ffSVille Syrjälä static void adls_ddi_get_config(struct intel_encoder *encoder, 4049351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4050351221ffSVille Syrjälä { 4051351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, adls_ddi_get_pll(encoder)); 4052351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4053351221ffSVille Syrjälä } 4054351221ffSVille Syrjälä 4055351221ffSVille Syrjälä static void rkl_ddi_get_config(struct intel_encoder *encoder, 4056351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4057351221ffSVille Syrjälä { 4058351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, rkl_ddi_get_pll(encoder)); 4059351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4060351221ffSVille Syrjälä } 4061351221ffSVille Syrjälä 4062351221ffSVille Syrjälä static void dg1_ddi_get_config(struct intel_encoder *encoder, 4063351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4064351221ffSVille Syrjälä { 4065351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, dg1_ddi_get_pll(encoder)); 4066351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4067351221ffSVille Syrjälä } 4068351221ffSVille Syrjälä 4069351221ffSVille Syrjälä static void icl_ddi_combo_get_config(struct intel_encoder *encoder, 4070351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4071351221ffSVille Syrjälä { 4072351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, icl_ddi_combo_get_pll(encoder)); 4073351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4074351221ffSVille Syrjälä } 4075351221ffSVille Syrjälä 40767c1da068SImre Deak static bool icl_ddi_tc_pll_is_tbt(const struct intel_shared_dpll *pll) 40777c1da068SImre Deak { 40787c1da068SImre Deak return pll->info->id == DPLL_ID_ICL_TBTPLL; 40797c1da068SImre Deak } 40807c1da068SImre Deak 40817c1da068SImre Deak static enum icl_port_dpll_id 40827c1da068SImre Deak icl_ddi_tc_port_pll_type(struct intel_encoder *encoder, 40837c1da068SImre Deak const struct intel_crtc_state *crtc_state) 40847c1da068SImre Deak { 40857c1da068SImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev); 40867c1da068SImre Deak const struct intel_shared_dpll *pll = crtc_state->shared_dpll; 40877c1da068SImre Deak 40887c1da068SImre Deak if (drm_WARN_ON(&i915->drm, !pll)) 40897c1da068SImre Deak return ICL_PORT_DPLL_DEFAULT; 40907c1da068SImre Deak 40917c1da068SImre Deak if (icl_ddi_tc_pll_is_tbt(pll)) 40927c1da068SImre Deak return ICL_PORT_DPLL_DEFAULT; 40937c1da068SImre Deak else 40947c1da068SImre Deak return ICL_PORT_DPLL_MG_PHY; 40957c1da068SImre Deak } 40967c1da068SImre Deak 40977c1da068SImre Deak enum icl_port_dpll_id 40987c1da068SImre Deak intel_ddi_port_pll_type(struct intel_encoder *encoder, 40997c1da068SImre Deak const struct intel_crtc_state *crtc_state) 41007c1da068SImre Deak { 41017c1da068SImre Deak if (!encoder->port_pll_type) 41027c1da068SImre Deak return ICL_PORT_DPLL_DEFAULT; 41037c1da068SImre Deak 41047c1da068SImre Deak return encoder->port_pll_type(encoder, crtc_state); 41057c1da068SImre Deak } 41067c1da068SImre Deak 4107086877a1SVille Syrjälä static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, 4108086877a1SVille Syrjälä struct intel_crtc_state *crtc_state, 4109086877a1SVille Syrjälä struct intel_shared_dpll *pll) 4110351221ffSVille Syrjälä { 4111351221ffSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 4112351221ffSVille Syrjälä enum icl_port_dpll_id port_dpll_id; 4113351221ffSVille Syrjälä struct icl_port_dpll *port_dpll; 4114351221ffSVille Syrjälä bool pll_active; 4115351221ffSVille Syrjälä 4116086877a1SVille Syrjälä if (drm_WARN_ON(&i915->drm, !pll)) 4117086877a1SVille Syrjälä return; 4118351221ffSVille Syrjälä 41197c1da068SImre Deak if (icl_ddi_tc_pll_is_tbt(pll)) 4120351221ffSVille Syrjälä port_dpll_id = ICL_PORT_DPLL_DEFAULT; 4121351221ffSVille Syrjälä else 4122351221ffSVille Syrjälä port_dpll_id = ICL_PORT_DPLL_MG_PHY; 4123351221ffSVille Syrjälä 4124351221ffSVille Syrjälä port_dpll = &crtc_state->icl_port_dplls[port_dpll_id]; 4125351221ffSVille Syrjälä 4126351221ffSVille Syrjälä port_dpll->pll = pll; 4127351221ffSVille Syrjälä pll_active = intel_dpll_get_hw_state(i915, pll, &port_dpll->hw_state); 4128351221ffSVille Syrjälä drm_WARN_ON(&i915->drm, !pll_active); 4129351221ffSVille Syrjälä 4130351221ffSVille Syrjälä icl_set_active_port_dpll(crtc_state, port_dpll_id); 4131351221ffSVille Syrjälä 41327c1da068SImre Deak if (icl_ddi_tc_pll_is_tbt(crtc_state->shared_dpll)) 4133351221ffSVille Syrjälä crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port); 4134351221ffSVille Syrjälä else 4135351221ffSVille Syrjälä crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll, 4136351221ffSVille Syrjälä &crtc_state->dpll_hw_state); 4137086877a1SVille Syrjälä } 4138351221ffSVille Syrjälä 4139086877a1SVille Syrjälä static void icl_ddi_tc_get_config(struct intel_encoder *encoder, 4140086877a1SVille Syrjälä struct intel_crtc_state *crtc_state) 4141086877a1SVille Syrjälä { 4142086877a1SVille Syrjälä icl_ddi_tc_get_clock(encoder, crtc_state, icl_ddi_tc_get_pll(encoder)); 4143351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4144351221ffSVille Syrjälä } 4145351221ffSVille Syrjälä 4146351221ffSVille Syrjälä static void bxt_ddi_get_config(struct intel_encoder *encoder, 4147351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4148351221ffSVille Syrjälä { 4149351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, bxt_ddi_get_pll(encoder)); 4150351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4151351221ffSVille Syrjälä } 4152351221ffSVille Syrjälä 4153351221ffSVille Syrjälä static void skl_ddi_get_config(struct intel_encoder *encoder, 4154351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4155351221ffSVille Syrjälä { 4156351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, skl_ddi_get_pll(encoder)); 4157351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4158351221ffSVille Syrjälä } 4159351221ffSVille Syrjälä 4160351221ffSVille Syrjälä void hsw_ddi_get_config(struct intel_encoder *encoder, 4161351221ffSVille Syrjälä struct intel_crtc_state *crtc_state) 4162351221ffSVille Syrjälä { 4163351221ffSVille Syrjälä intel_ddi_get_clock(encoder, crtc_state, hsw_ddi_get_pll(encoder)); 4164351221ffSVille Syrjälä intel_ddi_get_config(encoder, crtc_state); 4165351221ffSVille Syrjälä } 4166351221ffSVille Syrjälä 4167f9e76a6eSImre Deak static void intel_ddi_sync_state(struct intel_encoder *encoder, 4168f9e76a6eSImre Deak const struct intel_crtc_state *crtc_state) 4169f9e76a6eSImre Deak { 41707fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) 41712a4d292fSImre Deak intel_tc_port_sanitize_mode(enc_to_dig_port(encoder), 41722a4d292fSImre Deak crtc_state); 41737194dc99SImre Deak 41747605d0e8SImre Deak if (intel_encoder_is_dp(encoder)) 4175f9e76a6eSImre Deak intel_dp_sync_state(encoder, crtc_state); 4176f9e76a6eSImre Deak } 4177f9e76a6eSImre Deak 4178b671d6efSImre Deak static bool intel_ddi_initial_fastset_check(struct intel_encoder *encoder, 4179b671d6efSImre Deak struct intel_crtc_state *crtc_state) 4180b671d6efSImre Deak { 4181eddb4afcSVille Syrjälä struct drm_i915_private *i915 = to_i915(encoder->base.dev); 4182eddb4afcSVille Syrjälä bool fastset = true; 4183b671d6efSImre Deak 41847fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) { 4185eddb4afcSVille Syrjälä drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute TC port DPLLs\n", 4186eddb4afcSVille Syrjälä encoder->base.base.id, encoder->base.name); 4187eddb4afcSVille Syrjälä crtc_state->uapi.mode_changed = true; 4188eddb4afcSVille Syrjälä fastset = false; 4189eddb4afcSVille Syrjälä } 4190eddb4afcSVille Syrjälä 4191eddb4afcSVille Syrjälä if (intel_crtc_has_dp_encoder(crtc_state) && 4192eddb4afcSVille Syrjälä !intel_dp_initial_fastset_check(encoder, crtc_state)) 4193eddb4afcSVille Syrjälä fastset = false; 4194eddb4afcSVille Syrjälä 4195eddb4afcSVille Syrjälä return fastset; 4196b671d6efSImre Deak } 4197b671d6efSImre Deak 4198379bc100SJani Nikula static enum intel_output_type 4199379bc100SJani Nikula intel_ddi_compute_output_type(struct intel_encoder *encoder, 4200379bc100SJani Nikula struct intel_crtc_state *crtc_state, 4201379bc100SJani Nikula struct drm_connector_state *conn_state) 4202379bc100SJani Nikula { 4203379bc100SJani Nikula switch (conn_state->connector->connector_type) { 4204379bc100SJani Nikula case DRM_MODE_CONNECTOR_HDMIA: 4205379bc100SJani Nikula return INTEL_OUTPUT_HDMI; 4206379bc100SJani Nikula case DRM_MODE_CONNECTOR_eDP: 4207379bc100SJani Nikula return INTEL_OUTPUT_EDP; 4208379bc100SJani Nikula case DRM_MODE_CONNECTOR_DisplayPort: 4209379bc100SJani Nikula return INTEL_OUTPUT_DP; 4210379bc100SJani Nikula default: 4211379bc100SJani Nikula MISSING_CASE(conn_state->connector->connector_type); 4212379bc100SJani Nikula return INTEL_OUTPUT_UNUSED; 4213379bc100SJani Nikula } 4214379bc100SJani Nikula } 4215379bc100SJani Nikula 4216379bc100SJani Nikula static int intel_ddi_compute_config(struct intel_encoder *encoder, 4217379bc100SJani Nikula struct intel_crtc_state *pipe_config, 4218379bc100SJani Nikula struct drm_connector_state *conn_state) 4219379bc100SJani Nikula { 42202225f3c6SMaarten Lankhorst struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); 4221379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 4222379bc100SJani Nikula enum port port = encoder->port; 4223379bc100SJani Nikula int ret; 4224379bc100SJani Nikula 422510cf8e75SVille Syrjälä if (HAS_TRANSCODER(dev_priv, TRANSCODER_EDP) && port == PORT_A) 4226379bc100SJani Nikula pipe_config->cpu_transcoder = TRANSCODER_EDP; 4227379bc100SJani Nikula 4228bdacf087SAnshuman Gupta if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_HDMI)) { 422934682d60SVille Syrjälä pipe_config->has_hdmi_sink = 423034682d60SVille Syrjälä intel_hdmi_compute_has_hdmi_sink(encoder, pipe_config, conn_state); 423134682d60SVille Syrjälä 4232379bc100SJani Nikula ret = intel_hdmi_compute_config(encoder, pipe_config, conn_state); 4233bdacf087SAnshuman Gupta } else { 4234379bc100SJani Nikula ret = intel_dp_compute_config(encoder, pipe_config, conn_state); 4235bdacf087SAnshuman Gupta } 4236bdacf087SAnshuman Gupta 4237379bc100SJani Nikula if (ret) 4238379bc100SJani Nikula return ret; 4239379bc100SJani Nikula 4240379bc100SJani Nikula if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A && 4241379bc100SJani Nikula pipe_config->cpu_transcoder == TRANSCODER_EDP) 4242379bc100SJani Nikula pipe_config->pch_pfit.force_thru = 4243379bc100SJani Nikula pipe_config->pch_pfit.enabled || 4244379bc100SJani Nikula pipe_config->crc_enabled; 4245379bc100SJani Nikula 42462446e1d6SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 4247379bc100SJani Nikula pipe_config->lane_lat_optim_mask = 4248ba07c3edSVille Syrjälä bxt_dpio_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); 4249379bc100SJani Nikula 42508cd53c6bSVille Syrjälä intel_ddi_compute_min_voltage_level(pipe_config); 4251379bc100SJani Nikula 4252379bc100SJani Nikula return 0; 4253379bc100SJani Nikula } 4254379bc100SJani Nikula 4255b50a1aa6SManasi Navare static bool mode_equal(const struct drm_display_mode *mode1, 4256b50a1aa6SManasi Navare const struct drm_display_mode *mode2) 4257b50a1aa6SManasi Navare { 4258b50a1aa6SManasi Navare return drm_mode_match(mode1, mode2, 4259b50a1aa6SManasi Navare DRM_MODE_MATCH_TIMINGS | 4260b50a1aa6SManasi Navare DRM_MODE_MATCH_FLAGS | 4261b50a1aa6SManasi Navare DRM_MODE_MATCH_3D_FLAGS) && 4262b50a1aa6SManasi Navare mode1->clock == mode2->clock; /* we want an exact match */ 4263b50a1aa6SManasi Navare } 4264b50a1aa6SManasi Navare 4265b50a1aa6SManasi Navare static bool m_n_equal(const struct intel_link_m_n *m_n_1, 4266b50a1aa6SManasi Navare const struct intel_link_m_n *m_n_2) 4267b50a1aa6SManasi Navare { 4268b50a1aa6SManasi Navare return m_n_1->tu == m_n_2->tu && 42695f721a5dSVille Syrjälä m_n_1->data_m == m_n_2->data_m && 42705f721a5dSVille Syrjälä m_n_1->data_n == m_n_2->data_n && 4271b50a1aa6SManasi Navare m_n_1->link_m == m_n_2->link_m && 4272b50a1aa6SManasi Navare m_n_1->link_n == m_n_2->link_n; 4273b50a1aa6SManasi Navare } 4274b50a1aa6SManasi Navare 4275b50a1aa6SManasi Navare static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1, 4276b50a1aa6SManasi Navare const struct intel_crtc_state *crtc_state2) 4277b50a1aa6SManasi Navare { 4278b37e1347SVille Syrjälä /* 4279b37e1347SVille Syrjälä * FIXME the modeset sequence is currently wrong and 4280fb494357SStanislav Lisovskiy * can't deal with joiner + port sync at the same time. 4281b37e1347SVille Syrjälä */ 4282b50a1aa6SManasi Navare return crtc_state1->hw.active && crtc_state2->hw.active && 4283fb494357SStanislav Lisovskiy !crtc_state1->joiner_pipes && !crtc_state2->joiner_pipes && 4284b50a1aa6SManasi Navare crtc_state1->output_types == crtc_state2->output_types && 4285b50a1aa6SManasi Navare crtc_state1->output_format == crtc_state2->output_format && 4286b50a1aa6SManasi Navare crtc_state1->lane_count == crtc_state2->lane_count && 4287b50a1aa6SManasi Navare crtc_state1->port_clock == crtc_state2->port_clock && 4288b50a1aa6SManasi Navare mode_equal(&crtc_state1->hw.adjusted_mode, 4289b50a1aa6SManasi Navare &crtc_state2->hw.adjusted_mode) && 4290b50a1aa6SManasi Navare m_n_equal(&crtc_state1->dp_m_n, &crtc_state2->dp_m_n); 4291b50a1aa6SManasi Navare } 4292b50a1aa6SManasi Navare 4293b50a1aa6SManasi Navare static u8 4294b50a1aa6SManasi Navare intel_ddi_port_sync_transcoders(const struct intel_crtc_state *ref_crtc_state, 4295b50a1aa6SManasi Navare int tile_group_id) 4296b50a1aa6SManasi Navare { 4297b50a1aa6SManasi Navare struct drm_connector *connector; 4298b50a1aa6SManasi Navare const struct drm_connector_state *conn_state; 4299b50a1aa6SManasi Navare struct drm_i915_private *dev_priv = to_i915(ref_crtc_state->uapi.crtc->dev); 4300b50a1aa6SManasi Navare struct intel_atomic_state *state = 4301b50a1aa6SManasi Navare to_intel_atomic_state(ref_crtc_state->uapi.state); 4302b50a1aa6SManasi Navare u8 transcoders = 0; 4303b50a1aa6SManasi Navare int i; 4304b50a1aa6SManasi Navare 4305dc5b8ed5SVille Syrjälä /* 4306dc5b8ed5SVille Syrjälä * We don't enable port sync on BDW due to missing w/as and 4307dc5b8ed5SVille Syrjälä * due to not having adjusted the modeset sequence appropriately. 4308dc5b8ed5SVille Syrjälä */ 4309005e9537SMatt Roper if (DISPLAY_VER(dev_priv) < 9) 4310b50a1aa6SManasi Navare return 0; 4311b50a1aa6SManasi Navare 4312b50a1aa6SManasi Navare if (!intel_crtc_has_type(ref_crtc_state, INTEL_OUTPUT_DP)) 4313b50a1aa6SManasi Navare return 0; 4314b50a1aa6SManasi Navare 4315b50a1aa6SManasi Navare for_each_new_connector_in_state(&state->base, connector, conn_state, i) { 4316b50a1aa6SManasi Navare struct intel_crtc *crtc = to_intel_crtc(conn_state->crtc); 4317b50a1aa6SManasi Navare const struct intel_crtc_state *crtc_state; 4318b50a1aa6SManasi Navare 4319b50a1aa6SManasi Navare if (!crtc) 4320b50a1aa6SManasi Navare continue; 4321b50a1aa6SManasi Navare 4322b50a1aa6SManasi Navare if (!connector->has_tile || 4323b50a1aa6SManasi Navare connector->tile_group->id != 4324b50a1aa6SManasi Navare tile_group_id) 4325b50a1aa6SManasi Navare continue; 4326b50a1aa6SManasi Navare crtc_state = intel_atomic_get_new_crtc_state(state, 4327b50a1aa6SManasi Navare crtc); 4328b50a1aa6SManasi Navare if (!crtcs_port_sync_compatible(ref_crtc_state, 4329b50a1aa6SManasi Navare crtc_state)) 4330b50a1aa6SManasi Navare continue; 4331b50a1aa6SManasi Navare transcoders |= BIT(crtc_state->cpu_transcoder); 4332b50a1aa6SManasi Navare } 4333b50a1aa6SManasi Navare 4334b50a1aa6SManasi Navare return transcoders; 4335b50a1aa6SManasi Navare } 4336b50a1aa6SManasi Navare 4337b50a1aa6SManasi Navare static int intel_ddi_compute_config_late(struct intel_encoder *encoder, 4338b50a1aa6SManasi Navare struct intel_crtc_state *crtc_state, 4339b50a1aa6SManasi Navare struct drm_connector_state *conn_state) 4340b50a1aa6SManasi Navare { 434147bdb1caSJani Nikula struct drm_i915_private *i915 = to_i915(encoder->base.dev); 4342b50a1aa6SManasi Navare struct drm_connector *connector = conn_state->connector; 4343b50a1aa6SManasi Navare u8 port_sync_transcoders = 0; 4344b50a1aa6SManasi Navare 434518367034SJim Cromie drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] [CRTC:%d:%s]\n", 4346b50a1aa6SManasi Navare encoder->base.base.id, encoder->base.name, 4347b50a1aa6SManasi Navare crtc_state->uapi.crtc->base.id, crtc_state->uapi.crtc->name); 4348b50a1aa6SManasi Navare 4349b50a1aa6SManasi Navare if (connector->has_tile) 4350b50a1aa6SManasi Navare port_sync_transcoders = intel_ddi_port_sync_transcoders(crtc_state, 4351b50a1aa6SManasi Navare connector->tile_group->id); 4352b50a1aa6SManasi Navare 4353b50a1aa6SManasi Navare /* 4354b50a1aa6SManasi Navare * EDP Transcoders cannot be ensalved 4355b50a1aa6SManasi Navare * make them a master always when present 4356b50a1aa6SManasi Navare */ 4357b50a1aa6SManasi Navare if (port_sync_transcoders & BIT(TRANSCODER_EDP)) 4358b50a1aa6SManasi Navare crtc_state->master_transcoder = TRANSCODER_EDP; 4359b50a1aa6SManasi Navare else 4360b50a1aa6SManasi Navare crtc_state->master_transcoder = ffs(port_sync_transcoders) - 1; 4361b50a1aa6SManasi Navare 4362b50a1aa6SManasi Navare if (crtc_state->master_transcoder == crtc_state->cpu_transcoder) { 4363b50a1aa6SManasi Navare crtc_state->master_transcoder = INVALID_TRANSCODER; 4364b50a1aa6SManasi Navare crtc_state->sync_mode_slaves_mask = 4365b50a1aa6SManasi Navare port_sync_transcoders & ~BIT(crtc_state->cpu_transcoder); 4366b50a1aa6SManasi Navare } 4367b50a1aa6SManasi Navare 4368b50a1aa6SManasi Navare return 0; 4369b50a1aa6SManasi Navare } 4370b50a1aa6SManasi Navare 4371379bc100SJani Nikula static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) 4372379bc100SJani Nikula { 43734a300e65SImre Deak struct drm_i915_private *i915 = to_i915(encoder->dev); 4374b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); 4375379bc100SJani Nikula 4376379bc100SJani Nikula intel_dp_encoder_flush_work(encoder); 43777fcf7558SJani Nikula if (intel_encoder_is_tc(&dig_port->base)) 4378c5879999SImre Deak intel_tc_port_cleanup(dig_port); 43794a300e65SImre Deak intel_display_power_flush_work(i915); 4380379bc100SJani Nikula 4381379bc100SJani Nikula drm_encoder_cleanup(encoder); 4382a6c6eac9SAnshuman Gupta kfree(dig_port->hdcp_port_data.streams); 4383379bc100SJani Nikula kfree(dig_port); 4384379bc100SJani Nikula } 4385379bc100SJani Nikula 4386764f6729SVille Syrjälä static void intel_ddi_encoder_reset(struct drm_encoder *encoder) 4387764f6729SVille Syrjälä { 4388764f6729SVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder)); 4389a82796a2SImre Deak struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); 4390764f6729SVille Syrjälä 4391764f6729SVille Syrjälä intel_dp->reset_link_params = true; 4392764f6729SVille Syrjälä 4393764f6729SVille Syrjälä intel_pps_encoder_reset(intel_dp); 4394a82796a2SImre Deak 43957fcf7558SJani Nikula if (intel_encoder_is_tc(&dig_port->base)) 4396a82796a2SImre Deak intel_tc_port_init_mode(dig_port); 4397764f6729SVille Syrjälä } 4398764f6729SVille Syrjälä 4399c598c335SImre Deak static int intel_ddi_encoder_late_register(struct drm_encoder *_encoder) 4400c598c335SImre Deak { 4401c598c335SImre Deak struct intel_encoder *encoder = to_intel_encoder(_encoder); 4402c598c335SImre Deak 4403c598c335SImre Deak intel_tc_port_link_reset(enc_to_dig_port(encoder)); 4404c598c335SImre Deak 4405c598c335SImre Deak return 0; 4406c598c335SImre Deak } 4407c598c335SImre Deak 4408379bc100SJani Nikula static const struct drm_encoder_funcs intel_ddi_funcs = { 4409764f6729SVille Syrjälä .reset = intel_ddi_encoder_reset, 4410379bc100SJani Nikula .destroy = intel_ddi_encoder_destroy, 4411c598c335SImre Deak .late_register = intel_ddi_encoder_late_register, 4412379bc100SJani Nikula }; 4413379bc100SJani Nikula 4414379bc100SJani Nikula static struct intel_connector * 44157801f3b7SLucas De Marchi intel_ddi_init_dp_connector(struct intel_digital_port *dig_port) 4416379bc100SJani Nikula { 441723ef6194SJosé Roberto de Souza struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); 4418379bc100SJani Nikula struct intel_connector *connector; 44197801f3b7SLucas De Marchi enum port port = dig_port->base.port; 4420379bc100SJani Nikula 4421379bc100SJani Nikula connector = intel_connector_alloc(); 4422379bc100SJani Nikula if (!connector) 4423379bc100SJani Nikula return NULL; 4424379bc100SJani Nikula 44257801f3b7SLucas De Marchi dig_port->dp.output_reg = DDI_BUF_CTL(port); 442623ef6194SJosé Roberto de Souza if (DISPLAY_VER(i915) >= 14) 442723ef6194SJosé Roberto de Souza dig_port->dp.prepare_link_retrain = mtl_ddi_prepare_link_retrain; 442823ef6194SJosé Roberto de Souza else 44297801f3b7SLucas De Marchi dig_port->dp.prepare_link_retrain = intel_ddi_prepare_link_retrain; 44307801f3b7SLucas De Marchi dig_port->dp.set_link_train = intel_ddi_set_link_train; 44317801f3b7SLucas De Marchi dig_port->dp.set_idle_link_train = intel_ddi_set_idle_link_train; 4432eee3f911SVille Syrjälä 44337801f3b7SLucas De Marchi dig_port->dp.voltage_max = intel_ddi_dp_voltage_max; 44347801f3b7SLucas De Marchi dig_port->dp.preemph_max = intel_ddi_dp_preemph_max; 443553de0a20SVille Syrjälä 44367801f3b7SLucas De Marchi if (!intel_dp_init_connector(dig_port, connector)) { 4437379bc100SJani Nikula kfree(connector); 4438379bc100SJani Nikula return NULL; 4439379bc100SJani Nikula } 4440379bc100SJani Nikula 44416306d8dbSHans de Goede if (dig_port->base.type == INTEL_OUTPUT_EDP) { 44426306d8dbSHans de Goede struct drm_device *dev = dig_port->base.base.dev; 44436306d8dbSHans de Goede struct drm_privacy_screen *privacy_screen; 44446306d8dbSHans de Goede 44456306d8dbSHans de Goede privacy_screen = drm_privacy_screen_get(dev->dev, NULL); 44466306d8dbSHans de Goede if (!IS_ERR(privacy_screen)) { 44476306d8dbSHans de Goede drm_connector_attach_privacy_screen_provider(&connector->base, 44486306d8dbSHans de Goede privacy_screen); 44496306d8dbSHans de Goede } else if (PTR_ERR(privacy_screen) != -ENODEV) { 44506306d8dbSHans de Goede drm_warn(dev, "Error getting privacy-screen\n"); 44516306d8dbSHans de Goede } 44526306d8dbSHans de Goede } 44536306d8dbSHans de Goede 4454379bc100SJani Nikula return connector; 4455379bc100SJani Nikula } 4456379bc100SJani Nikula 4457379bc100SJani Nikula static int intel_hdmi_reset_link(struct intel_encoder *encoder, 4458379bc100SJani Nikula struct drm_modeset_acquire_ctx *ctx) 4459379bc100SJani Nikula { 4460379bc100SJani Nikula struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 4461b7d02c3aSVille Syrjälä struct intel_hdmi *hdmi = enc_to_intel_hdmi(encoder); 4462379bc100SJani Nikula struct intel_connector *connector = hdmi->attached_connector; 4463e046d156SVille Syrjälä struct i2c_adapter *ddc = connector->base.ddc; 4464379bc100SJani Nikula struct drm_connector_state *conn_state; 4465379bc100SJani Nikula struct intel_crtc_state *crtc_state; 4466379bc100SJani Nikula struct intel_crtc *crtc; 4467379bc100SJani Nikula u8 config; 4468379bc100SJani Nikula int ret; 4469379bc100SJani Nikula 44703385375bSSuraj Kandpal if (connector->base.status != connector_status_connected) 4471379bc100SJani Nikula return 0; 4472379bc100SJani Nikula 4473379bc100SJani Nikula ret = drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, 4474379bc100SJani Nikula ctx); 4475379bc100SJani Nikula if (ret) 4476379bc100SJani Nikula return ret; 4477379bc100SJani Nikula 4478379bc100SJani Nikula conn_state = connector->base.state; 4479379bc100SJani Nikula 4480379bc100SJani Nikula crtc = to_intel_crtc(conn_state->crtc); 4481379bc100SJani Nikula if (!crtc) 4482379bc100SJani Nikula return 0; 4483379bc100SJani Nikula 4484379bc100SJani Nikula ret = drm_modeset_lock(&crtc->base.mutex, ctx); 4485379bc100SJani Nikula if (ret) 4486379bc100SJani Nikula return ret; 4487379bc100SJani Nikula 4488379bc100SJani Nikula crtc_state = to_intel_crtc_state(crtc->base.state); 4489379bc100SJani Nikula 44901de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, 44911de143ccSPankaj Bharadiya !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)); 4492379bc100SJani Nikula 44931326a92cSMaarten Lankhorst if (!crtc_state->hw.active) 4494379bc100SJani Nikula return 0; 4495379bc100SJani Nikula 4496379bc100SJani Nikula if (!crtc_state->hdmi_high_tmds_clock_ratio && 4497379bc100SJani Nikula !crtc_state->hdmi_scrambling) 4498379bc100SJani Nikula return 0; 4499379bc100SJani Nikula 4500379bc100SJani Nikula if (conn_state->commit && 4501379bc100SJani Nikula !try_wait_for_completion(&conn_state->commit->hw_done)) 4502379bc100SJani Nikula return 0; 4503379bc100SJani Nikula 450430b98ecbSVille Syrjälä ret = drm_scdc_readb(ddc, SCDC_TMDS_CONFIG, &config); 4505379bc100SJani Nikula if (ret < 0) { 45065d844091SVille Syrjälä drm_err(&dev_priv->drm, "[CONNECTOR:%d:%s] Failed to read TMDS config: %d\n", 45075d844091SVille Syrjälä connector->base.base.id, connector->base.name, ret); 4508379bc100SJani Nikula return 0; 4509379bc100SJani Nikula } 4510379bc100SJani Nikula 4511379bc100SJani Nikula if (!!(config & SCDC_TMDS_BIT_CLOCK_RATIO_BY_40) == 4512379bc100SJani Nikula crtc_state->hdmi_high_tmds_clock_ratio && 4513379bc100SJani Nikula !!(config & SCDC_SCRAMBLING_ENABLE) == 4514379bc100SJani Nikula crtc_state->hdmi_scrambling) 4515379bc100SJani Nikula return 0; 4516379bc100SJani Nikula 4517379bc100SJani Nikula /* 4518379bc100SJani Nikula * HDMI 2.0 says that one should not send scrambled data 4519379bc100SJani Nikula * prior to configuring the sink scrambling, and that 4520379bc100SJani Nikula * TMDS clock/data transmission should be suspended when 4521379bc100SJani Nikula * changing the TMDS clock rate in the sink. So let's 4522379bc100SJani Nikula * just do a full modeset here, even though some sinks 4523379bc100SJani Nikula * would be perfectly happy if were to just reconfigure 4524379bc100SJani Nikula * the SCDC settings on the fly. 4525379bc100SJani Nikula */ 4526e5bf189aSImre Deak return intel_modeset_commit_pipes(dev_priv, BIT(crtc->pipe), ctx); 4527379bc100SJani Nikula } 4528379bc100SJani Nikula 45293b3be899SImre Deak static void intel_ddi_link_check(struct intel_encoder *encoder) 45303b3be899SImre Deak { 45313b3be899SImre Deak struct drm_i915_private *i915 = to_i915(encoder->base.dev); 45323b3be899SImre Deak struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 45333b3be899SImre Deak 45343b3be899SImre Deak /* TODO: Move checking the HDMI link state here as well. */ 45353b3be899SImre Deak drm_WARN_ON(&i915->drm, !dig_port->dp.attached_connector); 45363b3be899SImre Deak 45373b3be899SImre Deak intel_dp_link_check(encoder); 45383b3be899SImre Deak } 45393b3be899SImre Deak 45403944709dSImre Deak static enum intel_hotplug_state 45413944709dSImre Deak intel_ddi_hotplug(struct intel_encoder *encoder, 45428c8919c7SImre Deak struct intel_connector *connector) 4543379bc100SJani Nikula { 4544b7d02c3aSVille Syrjälä struct intel_digital_port *dig_port = enc_to_dig_port(encoder); 4545699390f7SVille Syrjälä struct intel_dp *intel_dp = &dig_port->dp; 45467fcf7558SJani Nikula bool is_tc = intel_encoder_is_tc(encoder); 4547379bc100SJani Nikula struct drm_modeset_acquire_ctx ctx; 45483944709dSImre Deak enum intel_hotplug_state state; 4549379bc100SJani Nikula int ret; 4550379bc100SJani Nikula 4551699390f7SVille Syrjälä if (intel_dp->compliance.test_active && 4552699390f7SVille Syrjälä intel_dp->compliance.test_type == DP_TEST_LINK_PHY_TEST_PATTERN) { 4553699390f7SVille Syrjälä intel_dp_phy_test(encoder); 4554699390f7SVille Syrjälä /* just do the PHY test and nothing else */ 4555699390f7SVille Syrjälä return INTEL_HOTPLUG_UNCHANGED; 4556699390f7SVille Syrjälä } 4557699390f7SVille Syrjälä 45588c8919c7SImre Deak state = intel_encoder_hotplug(encoder, connector); 4559379bc100SJani Nikula 4560c598c335SImre Deak if (!intel_tc_port_link_reset(dig_port)) { 456160ded7ccSImre Deak intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) { 4562379bc100SJani Nikula if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) 4563379bc100SJani Nikula ret = intel_hdmi_reset_link(encoder, &ctx); 4564379bc100SJani Nikula else 4565379bc100SJani Nikula ret = intel_dp_retrain_link(encoder, &ctx); 4566379bc100SJani Nikula } 4567379bc100SJani Nikula 456860ded7ccSImre Deak drm_WARN_ON(encoder->base.dev, ret); 4569c598c335SImre Deak } 4570379bc100SJani Nikula 4571bb80c925SJosé Roberto de Souza /* 4572bb80c925SJosé Roberto de Souza * Unpowered type-c dongles can take some time to boot and be 4573bb80c925SJosé Roberto de Souza * responsible, so here giving some time to those dongles to power up 4574bb80c925SJosé Roberto de Souza * and then retrying the probe. 4575bb80c925SJosé Roberto de Souza * 4576bb80c925SJosé Roberto de Souza * On many platforms the HDMI live state signal is known to be 4577bb80c925SJosé Roberto de Souza * unreliable, so we can't use it to detect if a sink is connected or 4578bb80c925SJosé Roberto de Souza * not. Instead we detect if it's connected based on whether we can 4579bb80c925SJosé Roberto de Souza * read the EDID or not. That in turn has a problem during disconnect, 4580bb80c925SJosé Roberto de Souza * since the HPD interrupt may be raised before the DDC lines get 4581bb80c925SJosé Roberto de Souza * disconnected (due to how the required length of DDC vs. HPD 4582bb80c925SJosé Roberto de Souza * connector pins are specified) and so we'll still be able to get a 4583bb80c925SJosé Roberto de Souza * valid EDID. To solve this schedule another detection cycle if this 4584bb80c925SJosé Roberto de Souza * time around we didn't detect any change in the sink's connection 4585bb80c925SJosé Roberto de Souza * status. 4586b4df5405SImre Deak * 4587b4df5405SImre Deak * Type-c connectors which get their HPD signal deasserted then 4588b4df5405SImre Deak * reasserted, without unplugging/replugging the sink from the 4589b4df5405SImre Deak * connector, introduce a delay until the AUX channel communication 4590b4df5405SImre Deak * becomes functional. Retry the detection for 5 seconds on type-c 4591b4df5405SImre Deak * connectors to account for this delay. 4592bb80c925SJosé Roberto de Souza */ 4593b4df5405SImre Deak if (state == INTEL_HOTPLUG_UNCHANGED && 4594b4df5405SImre Deak connector->hotplug_retries < (is_tc ? 5 : 1) && 4595bb80c925SJosé Roberto de Souza !dig_port->dp.is_mst) 4596bb80c925SJosé Roberto de Souza state = INTEL_HOTPLUG_RETRY; 4597bb80c925SJosé Roberto de Souza 45983944709dSImre Deak return state; 4599379bc100SJani Nikula } 4600379bc100SJani Nikula 4601edc0e09cSVille Syrjälä static bool lpt_digital_port_connected(struct intel_encoder *encoder) 4602edc0e09cSVille Syrjälä { 4603edc0e09cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 46045a4dd6f0SJani Nikula u32 bit = dev_priv->display.hotplug.pch_hpd[encoder->hpd_pin]; 4605edc0e09cSVille Syrjälä 4606edc0e09cSVille Syrjälä return intel_de_read(dev_priv, SDEISR) & bit; 4607edc0e09cSVille Syrjälä } 4608edc0e09cSVille Syrjälä 4609edc0e09cSVille Syrjälä static bool hsw_digital_port_connected(struct intel_encoder *encoder) 4610edc0e09cSVille Syrjälä { 4611edc0e09cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 46125a4dd6f0SJani Nikula u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin]; 4613edc0e09cSVille Syrjälä 4614c7e8a3d6SVille Syrjälä return intel_de_read(dev_priv, DEISR) & bit; 4615edc0e09cSVille Syrjälä } 4616edc0e09cSVille Syrjälä 4617edc0e09cSVille Syrjälä static bool bdw_digital_port_connected(struct intel_encoder *encoder) 4618edc0e09cSVille Syrjälä { 4619edc0e09cSVille Syrjälä struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 46205a4dd6f0SJani Nikula u32 bit = dev_priv->display.hotplug.hpd[encoder->hpd_pin]; 4621edc0e09cSVille Syrjälä 4622edc0e09cSVille Syrjälä return intel_de_read(dev_priv, GEN8_DE_PORT_ISR) & bit; 4623edc0e09cSVille Syrjälä } 4624edc0e09cSVille Syrjälä 4625379bc100SJani Nikula static struct intel_connector * 46267801f3b7SLucas De Marchi intel_ddi_init_hdmi_connector(struct intel_digital_port *dig_port) 4627379bc100SJani Nikula { 4628379bc100SJani Nikula struct intel_connector *connector; 46297801f3b7SLucas De Marchi enum port port = dig_port->base.port; 4630379bc100SJani Nikula 4631379bc100SJani Nikula connector = intel_connector_alloc(); 4632379bc100SJani Nikula if (!connector) 4633379bc100SJani Nikula return NULL; 4634379bc100SJani Nikula 46357801f3b7SLucas De Marchi dig_port->hdmi.hdmi_reg = DDI_BUF_CTL(port); 46367801f3b7SLucas De Marchi intel_hdmi_init_connector(dig_port, connector); 4637379bc100SJani Nikula 4638379bc100SJani Nikula return connector; 4639379bc100SJani Nikula } 4640379bc100SJani Nikula 46417801f3b7SLucas De Marchi static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port) 4642379bc100SJani Nikula { 46437801f3b7SLucas De Marchi struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); 4644379bc100SJani Nikula 46457801f3b7SLucas De Marchi if (dig_port->base.port != PORT_A) 4646379bc100SJani Nikula return false; 4647379bc100SJani Nikula 46487801f3b7SLucas De Marchi if (dig_port->saved_port_bits & DDI_A_4_LANES) 4649379bc100SJani Nikula return false; 4650379bc100SJani Nikula 4651379bc100SJani Nikula /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only 4652379bc100SJani Nikula * supported configuration 4653379bc100SJani Nikula */ 46542446e1d6SMatt Roper if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 4655379bc100SJani Nikula return true; 4656379bc100SJani Nikula 4657379bc100SJani Nikula return false; 4658379bc100SJani Nikula } 4659379bc100SJani Nikula 4660379bc100SJani Nikula static int 46617801f3b7SLucas De Marchi intel_ddi_max_lanes(struct intel_digital_port *dig_port) 4662379bc100SJani Nikula { 46637801f3b7SLucas De Marchi struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); 46647801f3b7SLucas De Marchi enum port port = dig_port->base.port; 4665379bc100SJani Nikula int max_lanes = 4; 4666379bc100SJani Nikula 4667005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) 4668379bc100SJani Nikula return max_lanes; 4669379bc100SJani Nikula 4670379bc100SJani Nikula if (port == PORT_A || port == PORT_E) { 4671f7960e7fSJani Nikula if (intel_de_read(dev_priv, DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) 4672379bc100SJani Nikula max_lanes = port == PORT_A ? 4 : 0; 4673379bc100SJani Nikula else 4674379bc100SJani Nikula /* Both A and E share 2 lanes */ 4675379bc100SJani Nikula max_lanes = 2; 4676379bc100SJani Nikula } 4677379bc100SJani Nikula 4678379bc100SJani Nikula /* 4679379bc100SJani Nikula * Some BIOS might fail to set this bit on port A if eDP 4680379bc100SJani Nikula * wasn't lit up at boot. Force this bit set when needed 4681379bc100SJani Nikula * so we use the proper lane count for our calculations. 4682379bc100SJani Nikula */ 46837801f3b7SLucas De Marchi if (intel_ddi_a_force_4_lanes(dig_port)) { 468447bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm, 468547bdb1caSJani Nikula "Forcing DDI_A_4_LANES for port A\n"); 46867801f3b7SLucas De Marchi dig_port->saved_port_bits |= DDI_A_4_LANES; 4687379bc100SJani Nikula max_lanes = 4; 4688379bc100SJani Nikula } 4689379bc100SJani Nikula 4690379bc100SJani Nikula return max_lanes; 4691379bc100SJani Nikula } 4692379bc100SJani Nikula 4693ed2615a8SMatt Roper static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv, 4694ed2615a8SMatt Roper enum port port) 4695ed2615a8SMatt Roper { 4696ed2615a8SMatt Roper if (port >= PORT_D_XELPD) 4697ed2615a8SMatt Roper return HPD_PORT_D + port - PORT_D_XELPD; 4698ed2615a8SMatt Roper else if (port >= PORT_TC1) 4699ed2615a8SMatt Roper return HPD_PORT_TC1 + port - PORT_TC1; 4700ed2615a8SMatt Roper else 4701ed2615a8SMatt Roper return HPD_PORT_A + port - PORT_A; 4702ed2615a8SMatt Roper } 4703ed2615a8SMatt Roper 4704229f31e2SLucas De Marchi static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv, 4705229f31e2SLucas De Marchi enum port port) 4706229f31e2SLucas De Marchi { 47071d8ca002SVille Syrjälä if (port >= PORT_TC1) 47081d8ca002SVille Syrjälä return HPD_PORT_C + port - PORT_TC1; 4709229f31e2SLucas De Marchi else 4710229f31e2SLucas De Marchi return HPD_PORT_A + port - PORT_A; 4711229f31e2SLucas De Marchi } 4712229f31e2SLucas De Marchi 4713da51e4baSVille Syrjälä static enum hpd_pin tgl_hpd_pin(struct drm_i915_private *dev_priv, 4714da51e4baSVille Syrjälä enum port port) 4715da51e4baSVille Syrjälä { 47161d8ca002SVille Syrjälä if (port >= PORT_TC1) 47171d8ca002SVille Syrjälä return HPD_PORT_TC1 + port - PORT_TC1; 4718da51e4baSVille Syrjälä else 4719da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A; 4720da51e4baSVille Syrjälä } 4721da51e4baSVille Syrjälä 4722da51e4baSVille Syrjälä static enum hpd_pin rkl_hpd_pin(struct drm_i915_private *dev_priv, 4723da51e4baSVille Syrjälä enum port port) 4724da51e4baSVille Syrjälä { 4725da51e4baSVille Syrjälä if (HAS_PCH_TGP(dev_priv)) 4726da51e4baSVille Syrjälä return tgl_hpd_pin(dev_priv, port); 4727da51e4baSVille Syrjälä 47281d8ca002SVille Syrjälä if (port >= PORT_TC1) 47291d8ca002SVille Syrjälä return HPD_PORT_C + port - PORT_TC1; 4730da51e4baSVille Syrjälä else 4731da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A; 4732da51e4baSVille Syrjälä } 4733da51e4baSVille Syrjälä 4734da51e4baSVille Syrjälä static enum hpd_pin icl_hpd_pin(struct drm_i915_private *dev_priv, 4735da51e4baSVille Syrjälä enum port port) 4736da51e4baSVille Syrjälä { 4737da51e4baSVille Syrjälä if (port >= PORT_C) 4738da51e4baSVille Syrjälä return HPD_PORT_TC1 + port - PORT_C; 4739da51e4baSVille Syrjälä else 4740da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A; 4741da51e4baSVille Syrjälä } 4742da51e4baSVille Syrjälä 4743da51e4baSVille Syrjälä static enum hpd_pin ehl_hpd_pin(struct drm_i915_private *dev_priv, 4744da51e4baSVille Syrjälä enum port port) 4745da51e4baSVille Syrjälä { 4746da51e4baSVille Syrjälä if (port == PORT_D) 4747da51e4baSVille Syrjälä return HPD_PORT_A; 4748da51e4baSVille Syrjälä 4749f24d1d45SVille Syrjälä if (HAS_PCH_TGP(dev_priv)) 4750da51e4baSVille Syrjälä return icl_hpd_pin(dev_priv, port); 4751da51e4baSVille Syrjälä 4752da51e4baSVille Syrjälä return HPD_PORT_A + port - PORT_A; 4753da51e4baSVille Syrjälä } 4754da51e4baSVille Syrjälä 4755c8455098SLyude Paul static enum hpd_pin skl_hpd_pin(struct drm_i915_private *dev_priv, enum port port) 4756c8455098SLyude Paul { 4757c8455098SLyude Paul if (HAS_PCH_TGP(dev_priv)) 4758c8455098SLyude Paul return icl_hpd_pin(dev_priv, port); 4759c8455098SLyude Paul 4760c8455098SLyude Paul return HPD_PORT_A + port - PORT_A; 4761c8455098SLyude Paul } 4762c8455098SLyude Paul 476336ecb0ecSVille Syrjälä static bool intel_ddi_is_tc(struct drm_i915_private *i915, enum port port) 476436ecb0ecSVille Syrjälä { 4765005e9537SMatt Roper if (DISPLAY_VER(i915) >= 12) 476636ecb0ecSVille Syrjälä return port >= PORT_TC1; 4767005e9537SMatt Roper else if (DISPLAY_VER(i915) >= 11) 476836ecb0ecSVille Syrjälä return port >= PORT_C; 476936ecb0ecSVille Syrjälä else 477036ecb0ecSVille Syrjälä return false; 477136ecb0ecSVille Syrjälä } 477236ecb0ecSVille Syrjälä 4773151ec347SImre Deak static void intel_ddi_encoder_suspend(struct intel_encoder *encoder) 4774151ec347SImre Deak { 4775151ec347SImre Deak intel_dp_encoder_suspend(encoder); 4776b61fad5fSImre Deak } 4777151ec347SImre Deak 4778b61fad5fSImre Deak static void intel_ddi_tc_encoder_suspend_complete(struct intel_encoder *encoder) 4779b61fad5fSImre Deak { 4780b61fad5fSImre Deak struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 4781b61fad5fSImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); 4782151ec347SImre Deak 47833b3be899SImre Deak /* 47843b3be899SImre Deak * TODO: Move this to intel_dp_encoder_suspend(), 47853b3be899SImre Deak * once modeset locking around that is removed. 47863b3be899SImre Deak */ 47873b3be899SImre Deak intel_encoder_link_check_flush_work(encoder); 4788c598c335SImre Deak intel_tc_port_suspend(dig_port); 4789151ec347SImre Deak } 4790151ec347SImre Deak 4791151ec347SImre Deak static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) 4792151ec347SImre Deak { 4793151ec347SImre Deak intel_dp_encoder_shutdown(encoder); 479449c55f7bSVille Syrjälä intel_hdmi_encoder_shutdown(encoder); 4795b61fad5fSImre Deak } 4796151ec347SImre Deak 4797b61fad5fSImre Deak static void intel_ddi_tc_encoder_shutdown_complete(struct intel_encoder *encoder) 4798b61fad5fSImre Deak { 4799b61fad5fSImre Deak struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 4800b61fad5fSImre Deak struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); 4801151ec347SImre Deak 4802c5879999SImre Deak intel_tc_port_cleanup(dig_port); 4803151ec347SImre Deak } 4804151ec347SImre Deak 480583566d13SVille Syrjälä #define port_tc_name(port) ((port) - PORT_TC1 + '1') 480683566d13SVille Syrjälä #define tc_port_name(tc_port) ((tc_port) - TC_PORT_1 + '1') 480783566d13SVille Syrjälä 4808d77721c1SVille Syrjälä static bool port_strap_detected(struct drm_i915_private *i915, enum port port) 4809d77721c1SVille Syrjälä { 4810d77721c1SVille Syrjälä /* straps not used on skl+ */ 4811d77721c1SVille Syrjälä if (DISPLAY_VER(i915) >= 9) 4812d77721c1SVille Syrjälä return true; 4813d77721c1SVille Syrjälä 4814d77721c1SVille Syrjälä switch (port) { 4815d77721c1SVille Syrjälä case PORT_A: 4816d77721c1SVille Syrjälä return intel_de_read(i915, DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; 4817d77721c1SVille Syrjälä case PORT_B: 4818d77721c1SVille Syrjälä return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDIB_DETECTED; 4819d77721c1SVille Syrjälä case PORT_C: 4820d77721c1SVille Syrjälä return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDIC_DETECTED; 4821d77721c1SVille Syrjälä case PORT_D: 4822d77721c1SVille Syrjälä return intel_de_read(i915, SFUSE_STRAP) & SFUSE_STRAP_DDID_DETECTED; 4823d77721c1SVille Syrjälä case PORT_E: 4824d77721c1SVille Syrjälä return true; /* no strap for DDI-E */ 4825d77721c1SVille Syrjälä default: 4826d77721c1SVille Syrjälä MISSING_CASE(port); 4827d77721c1SVille Syrjälä return false; 4828d77721c1SVille Syrjälä } 4829d77721c1SVille Syrjälä } 4830d77721c1SVille Syrjälä 48319856308cSVille Syrjälä static bool need_aux_ch(struct intel_encoder *encoder, bool init_dp) 48329856308cSVille Syrjälä { 48337fcf7558SJani Nikula return init_dp || intel_encoder_is_tc(encoder); 48349856308cSVille Syrjälä } 48359856308cSVille Syrjälä 4836021a62a5SVille Syrjälä static bool assert_has_icl_dsi(struct drm_i915_private *i915) 4837021a62a5SVille Syrjälä { 4838021a62a5SVille Syrjälä return !drm_WARN(&i915->drm, !IS_ALDERLAKE_P(i915) && 4839021a62a5SVille Syrjälä !IS_TIGERLAKE(i915) && DISPLAY_VER(i915) != 11, 4840021a62a5SVille Syrjälä "Platform does not support DSI\n"); 4841021a62a5SVille Syrjälä } 4842021a62a5SVille Syrjälä 4843021a62a5SVille Syrjälä static bool port_in_use(struct drm_i915_private *i915, enum port port) 4844021a62a5SVille Syrjälä { 4845021a62a5SVille Syrjälä struct intel_encoder *encoder; 4846021a62a5SVille Syrjälä 4847021a62a5SVille Syrjälä for_each_intel_encoder(&i915->drm, encoder) { 4848021a62a5SVille Syrjälä /* FIXME what about second port for dual link DSI? */ 4849021a62a5SVille Syrjälä if (encoder->port == port) 4850021a62a5SVille Syrjälä return true; 4851021a62a5SVille Syrjälä } 4852021a62a5SVille Syrjälä 4853021a62a5SVille Syrjälä return false; 4854021a62a5SVille Syrjälä } 4855021a62a5SVille Syrjälä 4856021a62a5SVille Syrjälä void intel_ddi_init(struct drm_i915_private *dev_priv, 4857021a62a5SVille Syrjälä const struct intel_bios_encoder_data *devdata) 4858379bc100SJani Nikula { 48597801f3b7SLucas De Marchi struct intel_digital_port *dig_port; 486070dfbc29SLucas De Marchi struct intel_encoder *encoder; 4861f542d671SKai-Heng Feng bool init_hdmi, init_dp; 4862021a62a5SVille Syrjälä enum port port; 4863021a62a5SVille Syrjälä enum phy phy; 4864021a62a5SVille Syrjälä 4865021a62a5SVille Syrjälä port = intel_bios_encoder_port(devdata); 4866021a62a5SVille Syrjälä if (port == PORT_NONE) 4867021a62a5SVille Syrjälä return; 4868379bc100SJani Nikula 4869d77721c1SVille Syrjälä if (!port_strap_detected(dev_priv, port)) { 4870d77721c1SVille Syrjälä drm_dbg_kms(&dev_priv->drm, 4871d77721c1SVille Syrjälä "Port %c strap not detected\n", port_name(port)); 4872d77721c1SVille Syrjälä return; 4873d77721c1SVille Syrjälä } 4874d77721c1SVille Syrjälä 4875679df6f1SVille Syrjälä if (!assert_port_valid(dev_priv, port)) 4876679df6f1SVille Syrjälä return; 4877679df6f1SVille Syrjälä 4878021a62a5SVille Syrjälä if (port_in_use(dev_priv, port)) { 4879021a62a5SVille Syrjälä drm_dbg_kms(&dev_priv->drm, 4880021a62a5SVille Syrjälä "Port %c already claimed\n", port_name(port)); 4881021a62a5SVille Syrjälä return; 4882021a62a5SVille Syrjälä } 4883021a62a5SVille Syrjälä 4884021a62a5SVille Syrjälä if (intel_bios_encoder_supports_dsi(devdata)) { 4885021a62a5SVille Syrjälä /* BXT/GLK handled elsewhere, for now at least */ 4886021a62a5SVille Syrjälä if (!assert_has_icl_dsi(dev_priv)) 4887021a62a5SVille Syrjälä return; 4888021a62a5SVille Syrjälä 4889021a62a5SVille Syrjälä icl_dsi_init(dev_priv, devdata); 4890021a62a5SVille Syrjälä return; 4891021a62a5SVille Syrjälä } 4892021a62a5SVille Syrjälä 4893021a62a5SVille Syrjälä phy = intel_port_to_phy(dev_priv, port); 4894021a62a5SVille Syrjälä 4895ddff9a60SMatt Roper /* 4896ddff9a60SMatt Roper * On platforms with HTI (aka HDPORT), if it's enabled at boot it may 4897ddff9a60SMatt Roper * have taken over some of the PHYs and made them unavailable to the 4898ddff9a60SMatt Roper * driver. In that case we should skip initializing the corresponding 4899ddff9a60SMatt Roper * outputs. 4900ddff9a60SMatt Roper */ 490103120fefSJani Nikula if (intel_hti_uses_phy(dev_priv, phy)) { 4902ddff9a60SMatt Roper drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n", 4903ddff9a60SMatt Roper port_name(port), phy_name(phy)); 4904ddff9a60SMatt Roper return; 4905ddff9a60SMatt Roper } 4906ddff9a60SMatt Roper 490745c0673aSJani Nikula init_hdmi = intel_bios_encoder_supports_dvi(devdata) || 490845c0673aSJani Nikula intel_bios_encoder_supports_hdmi(devdata); 490945c0673aSJani Nikula init_dp = intel_bios_encoder_supports_dp(devdata); 4910379bc100SJani Nikula 4911db5d650fSVille Syrjälä if (intel_bios_encoder_is_lspcon(devdata)) { 4912379bc100SJani Nikula /* 4913379bc100SJani Nikula * Lspcon device needs to be driven with DP connector 4914379bc100SJani Nikula * with special detection sequence. So make sure DP 4915379bc100SJani Nikula * is initialized before lspcon. 4916379bc100SJani Nikula */ 4917379bc100SJani Nikula init_dp = true; 4918379bc100SJani Nikula init_hdmi = false; 491947bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm, "VBT says port %c has lspcon\n", 492047bdb1caSJani Nikula port_name(port)); 4921379bc100SJani Nikula } 4922379bc100SJani Nikula 4923379bc100SJani Nikula if (!init_dp && !init_hdmi) { 492447bdb1caSJani Nikula drm_dbg_kms(&dev_priv->drm, 492547bdb1caSJani Nikula "VBT says port %c is not DVI/HDMI/DP compatible, respect it\n", 4926379bc100SJani Nikula port_name(port)); 4927379bc100SJani Nikula return; 4928379bc100SJani Nikula } 4929379bc100SJani Nikula 4930b4eb76d8SMatt Roper if (intel_phy_is_snps(dev_priv, phy) && 49313a7e2d58SJani Nikula dev_priv->display.snps.phy_failed_calibration & BIT(phy)) { 4932b4eb76d8SMatt Roper drm_dbg_kms(&dev_priv->drm, 493382c362f2SLucas De Marchi "SNPS PHY %c failed to calibrate, proceeding anyway\n", 4934b4eb76d8SMatt Roper phy_name(phy)); 4935b4eb76d8SMatt Roper } 4936b4eb76d8SMatt Roper 49377801f3b7SLucas De Marchi dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); 49387801f3b7SLucas De Marchi if (!dig_port) 4939379bc100SJani Nikula return; 4940379bc100SJani Nikula 49414cca9676SVille Syrjälä dig_port->aux_ch = AUX_CH_NONE; 49424cca9676SVille Syrjälä 49437801f3b7SLucas De Marchi encoder = &dig_port->base; 4944c0a950d1SJani Nikula encoder->devdata = devdata; 4945379bc100SJani Nikula 4946ed2615a8SMatt Roper if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) { 4947ed2615a8SMatt Roper drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, 4948ed2615a8SMatt Roper DRM_MODE_ENCODER_TMDS, 4949ed2615a8SMatt Roper "DDI %c/PHY %c", 4950ed2615a8SMatt Roper port_name(port - PORT_D_XELPD + PORT_D), 4951ed2615a8SMatt Roper phy_name(phy)); 4952ed2615a8SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 12) { 49532d709a5aSVille Syrjälä enum tc_port tc_port = intel_port_to_tc(dev_priv, port); 49542d709a5aSVille Syrjälä 495570dfbc29SLucas De Marchi drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, 49562d709a5aSVille Syrjälä DRM_MODE_ENCODER_TMDS, 49572d709a5aSVille Syrjälä "DDI %s%c/PHY %s%c", 49582d709a5aSVille Syrjälä port >= PORT_TC1 ? "TC" : "", 495983566d13SVille Syrjälä port >= PORT_TC1 ? port_tc_name(port) : port_name(port), 49602d709a5aSVille Syrjälä tc_port != TC_PORT_NONE ? "TC" : "", 496183566d13SVille Syrjälä tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy)); 4962005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 11) { 49632d709a5aSVille Syrjälä enum tc_port tc_port = intel_port_to_tc(dev_priv, port); 49642d709a5aSVille Syrjälä 49652d709a5aSVille Syrjälä drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, 49662d709a5aSVille Syrjälä DRM_MODE_ENCODER_TMDS, 49672d709a5aSVille Syrjälä "DDI %c%s/PHY %s%c", 49682d709a5aSVille Syrjälä port_name(port), 49692d709a5aSVille Syrjälä port >= PORT_C ? " (TC)" : "", 49702d709a5aSVille Syrjälä tc_port != TC_PORT_NONE ? "TC" : "", 497183566d13SVille Syrjälä tc_port != TC_PORT_NONE ? tc_port_name(tc_port) : phy_name(phy)); 49722d709a5aSVille Syrjälä } else { 49732d709a5aSVille Syrjälä drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, 49742d709a5aSVille Syrjälä DRM_MODE_ENCODER_TMDS, 49752d709a5aSVille Syrjälä "DDI %c/PHY %c", port_name(port), phy_name(phy)); 49762d709a5aSVille Syrjälä } 4977379bc100SJani Nikula 49783b3be899SImre Deak intel_encoder_link_check_init(encoder, intel_ddi_link_check); 49793b3be899SImre Deak 498036e5e704SSean Paul mutex_init(&dig_port->hdcp_mutex); 498136e5e704SSean Paul dig_port->num_hdcp_streams = 0; 498236e5e704SSean Paul 498370dfbc29SLucas De Marchi encoder->hotplug = intel_ddi_hotplug; 498470dfbc29SLucas De Marchi encoder->compute_output_type = intel_ddi_compute_output_type; 498570dfbc29SLucas De Marchi encoder->compute_config = intel_ddi_compute_config; 4986b50a1aa6SManasi Navare encoder->compute_config_late = intel_ddi_compute_config_late; 498770dfbc29SLucas De Marchi encoder->enable = intel_enable_ddi; 498870dfbc29SLucas De Marchi encoder->pre_pll_enable = intel_ddi_pre_pll_enable; 498970dfbc29SLucas De Marchi encoder->pre_enable = intel_ddi_pre_enable; 499070dfbc29SLucas De Marchi encoder->disable = intel_disable_ddi; 4991b108bdd0SImre Deak encoder->post_pll_disable = intel_ddi_post_pll_disable; 499270dfbc29SLucas De Marchi encoder->post_disable = intel_ddi_post_disable; 499370dfbc29SLucas De Marchi encoder->update_pipe = intel_ddi_update_pipe; 49943654a48aSVille Syrjälä encoder->audio_enable = intel_audio_codec_enable; 49953654a48aSVille Syrjälä encoder->audio_disable = intel_audio_codec_disable; 499670dfbc29SLucas De Marchi encoder->get_hw_state = intel_ddi_get_hw_state; 4997f9e76a6eSImre Deak encoder->sync_state = intel_ddi_sync_state; 4998b671d6efSImre Deak encoder->initial_fastset_check = intel_ddi_initial_fastset_check; 4999151ec347SImre Deak encoder->suspend = intel_ddi_encoder_suspend; 5000151ec347SImre Deak encoder->shutdown = intel_ddi_encoder_shutdown; 500170dfbc29SLucas De Marchi encoder->get_power_domains = intel_ddi_get_power_domains; 500270dfbc29SLucas De Marchi 500370dfbc29SLucas De Marchi encoder->type = INTEL_OUTPUT_DDI; 5004979e1b32SImre Deak encoder->power_domain = intel_display_power_ddi_lanes_domain(dev_priv, port); 500570dfbc29SLucas De Marchi encoder->port = port; 500670dfbc29SLucas De Marchi encoder->cloneable = 0; 500770dfbc29SLucas De Marchi encoder->pipe_mask = ~0; 5008da51e4baSVille Syrjälä 500951390cc0SRadhakrishna Sripada if (DISPLAY_VER(dev_priv) >= 14) { 501073fc3abcSMika Kahola encoder->enable_clock = intel_mtl_pll_enable; 501173fc3abcSMika Kahola encoder->disable_clock = intel_mtl_pll_disable; 50126f0423b0SMika Kahola encoder->port_pll_type = intel_mtl_port_pll_type; 501351390cc0SRadhakrishna Sripada encoder->get_config = mtl_ddi_get_config; 501451390cc0SRadhakrishna Sripada } else if (IS_DG2(dev_priv)) { 5015f82f2563SMatt Roper encoder->enable_clock = intel_mpllb_enable; 5016f82f2563SMatt Roper encoder->disable_clock = intel_mpllb_disable; 5017865b73eaSMatt Roper encoder->get_config = dg2_ddi_get_config; 5018865b73eaSMatt Roper } else if (IS_ALDERLAKE_S(dev_priv)) { 501940b316d4SVille Syrjälä encoder->enable_clock = adls_ddi_enable_clock; 502040b316d4SVille Syrjälä encoder->disable_clock = adls_ddi_disable_clock; 50210fbd8694SVille Syrjälä encoder->is_clock_enabled = adls_ddi_is_clock_enabled; 5022351221ffSVille Syrjälä encoder->get_config = adls_ddi_get_config; 502340b316d4SVille Syrjälä } else if (IS_ROCKETLAKE(dev_priv)) { 502440b316d4SVille Syrjälä encoder->enable_clock = rkl_ddi_enable_clock; 502540b316d4SVille Syrjälä encoder->disable_clock = rkl_ddi_disable_clock; 50260fbd8694SVille Syrjälä encoder->is_clock_enabled = rkl_ddi_is_clock_enabled; 5027351221ffSVille Syrjälä encoder->get_config = rkl_ddi_get_config; 502836ecb0ecSVille Syrjälä } else if (IS_DG1(dev_priv)) { 502935bb6b1aSVille Syrjälä encoder->enable_clock = dg1_ddi_enable_clock; 503035bb6b1aSVille Syrjälä encoder->disable_clock = dg1_ddi_disable_clock; 50310fbd8694SVille Syrjälä encoder->is_clock_enabled = dg1_ddi_is_clock_enabled; 5032351221ffSVille Syrjälä encoder->get_config = dg1_ddi_get_config; 50330c65dc06SDnyaneshwar Bhadane } else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) { 503436ecb0ecSVille Syrjälä if (intel_ddi_is_tc(dev_priv, port)) { 503536ecb0ecSVille Syrjälä encoder->enable_clock = jsl_ddi_tc_enable_clock; 503636ecb0ecSVille Syrjälä encoder->disable_clock = jsl_ddi_tc_disable_clock; 50370fbd8694SVille Syrjälä encoder->is_clock_enabled = jsl_ddi_tc_is_clock_enabled; 50387c1da068SImre Deak encoder->port_pll_type = icl_ddi_tc_port_pll_type; 5039351221ffSVille Syrjälä encoder->get_config = icl_ddi_combo_get_config; 504036ecb0ecSVille Syrjälä } else { 504136ecb0ecSVille Syrjälä encoder->enable_clock = icl_ddi_combo_enable_clock; 504236ecb0ecSVille Syrjälä encoder->disable_clock = icl_ddi_combo_disable_clock; 50430fbd8694SVille Syrjälä encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled; 5044351221ffSVille Syrjälä encoder->get_config = icl_ddi_combo_get_config; 504536ecb0ecSVille Syrjälä } 5046005e9537SMatt Roper } else if (DISPLAY_VER(dev_priv) >= 11) { 504736ecb0ecSVille Syrjälä if (intel_ddi_is_tc(dev_priv, port)) { 504836ecb0ecSVille Syrjälä encoder->enable_clock = icl_ddi_tc_enable_clock; 504936ecb0ecSVille Syrjälä encoder->disable_clock = icl_ddi_tc_disable_clock; 50500fbd8694SVille Syrjälä encoder->is_clock_enabled = icl_ddi_tc_is_clock_enabled; 50517c1da068SImre Deak encoder->port_pll_type = icl_ddi_tc_port_pll_type; 5052351221ffSVille Syrjälä encoder->get_config = icl_ddi_tc_get_config; 505336ecb0ecSVille Syrjälä } else { 505436ecb0ecSVille Syrjälä encoder->enable_clock = icl_ddi_combo_enable_clock; 505536ecb0ecSVille Syrjälä encoder->disable_clock = icl_ddi_combo_disable_clock; 50560fbd8694SVille Syrjälä encoder->is_clock_enabled = icl_ddi_combo_is_clock_enabled; 5057351221ffSVille Syrjälä encoder->get_config = icl_ddi_combo_get_config; 505836ecb0ecSVille Syrjälä } 50592446e1d6SMatt Roper } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 5060351221ffSVille Syrjälä /* BXT/GLK have fixed PLL->port mapping */ 5061351221ffSVille Syrjälä encoder->get_config = bxt_ddi_get_config; 506293e7e61eSLucas De Marchi } else if (DISPLAY_VER(dev_priv) == 9) { 506338e31f1aSVille Syrjälä encoder->enable_clock = skl_ddi_enable_clock; 506438e31f1aSVille Syrjälä encoder->disable_clock = skl_ddi_disable_clock; 50650fbd8694SVille Syrjälä encoder->is_clock_enabled = skl_ddi_is_clock_enabled; 5066351221ffSVille Syrjälä encoder->get_config = skl_ddi_get_config; 506738e31f1aSVille Syrjälä } else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { 5068d135368dSVille Syrjälä encoder->enable_clock = hsw_ddi_enable_clock; 5069d135368dSVille Syrjälä encoder->disable_clock = hsw_ddi_disable_clock; 50700fbd8694SVille Syrjälä encoder->is_clock_enabled = hsw_ddi_is_clock_enabled; 5071351221ffSVille Syrjälä encoder->get_config = hsw_ddi_get_config; 5072d135368dSVille Syrjälä } 5073d135368dSVille Syrjälä 5074ea8af87aSMika Kahola if (DISPLAY_VER(dev_priv) >= 14) { 5075ea8af87aSMika Kahola encoder->set_signal_levels = intel_cx0_phy_set_signal_levels; 5076ea8af87aSMika Kahola } else if (IS_DG2(dev_priv)) { 5077193299adSVille Syrjälä encoder->set_signal_levels = intel_snps_phy_set_signal_levels; 5078193299adSVille Syrjälä } else if (DISPLAY_VER(dev_priv) >= 12) { 50797fcf7558SJani Nikula if (intel_encoder_is_combo(encoder)) 5080193299adSVille Syrjälä encoder->set_signal_levels = icl_combo_phy_set_signal_levels; 5081e722ab8bSVille Syrjälä else 5082193299adSVille Syrjälä encoder->set_signal_levels = tgl_dkl_phy_set_signal_levels; 5083193299adSVille Syrjälä } else if (DISPLAY_VER(dev_priv) >= 11) { 50847fcf7558SJani Nikula if (intel_encoder_is_combo(encoder)) 5085193299adSVille Syrjälä encoder->set_signal_levels = icl_combo_phy_set_signal_levels; 5086193299adSVille Syrjälä else 5087193299adSVille Syrjälä encoder->set_signal_levels = icl_mg_phy_set_signal_levels; 5088193299adSVille Syrjälä } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 5089ba07c3edSVille Syrjälä encoder->set_signal_levels = bxt_dpio_phy_set_signal_levels; 5090193299adSVille Syrjälä } else { 5091e722ab8bSVille Syrjälä encoder->set_signal_levels = hsw_set_signal_levels; 5092193299adSVille Syrjälä } 5093e722ab8bSVille Syrjälä 5094c40a253bSVille Syrjälä intel_ddi_buf_trans_init(encoder); 5095c40a253bSVille Syrjälä 5096ed2615a8SMatt Roper if (DISPLAY_VER(dev_priv) >= 13) 5097ed2615a8SMatt Roper encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port); 5098ed2615a8SMatt Roper else if (IS_DG1(dev_priv)) 5099229f31e2SLucas De Marchi encoder->hpd_pin = dg1_hpd_pin(dev_priv, port); 5100229f31e2SLucas De Marchi else if (IS_ROCKETLAKE(dev_priv)) 5101da51e4baSVille Syrjälä encoder->hpd_pin = rkl_hpd_pin(dev_priv, port); 5102005e9537SMatt Roper else if (DISPLAY_VER(dev_priv) >= 12) 5103da51e4baSVille Syrjälä encoder->hpd_pin = tgl_hpd_pin(dev_priv, port); 51040c65dc06SDnyaneshwar Bhadane else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) 5105da51e4baSVille Syrjälä encoder->hpd_pin = ehl_hpd_pin(dev_priv, port); 510693e7e61eSLucas De Marchi else if (DISPLAY_VER(dev_priv) == 11) 5107da51e4baSVille Syrjälä encoder->hpd_pin = icl_hpd_pin(dev_priv, port); 510893e7e61eSLucas De Marchi else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) 5109c8455098SLyude Paul encoder->hpd_pin = skl_hpd_pin(dev_priv, port); 5110da51e4baSVille Syrjälä else 511103c7e4f1SVille Syrjälä encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); 5112379bc100SJani Nikula 5113005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) 51147801f3b7SLucas De Marchi dig_port->saved_port_bits = 51157801f3b7SLucas De Marchi intel_de_read(dev_priv, DDI_BUF_CTL(port)) 51167801f3b7SLucas De Marchi & DDI_BUF_PORT_REVERSAL; 5117379bc100SJani Nikula else 51187801f3b7SLucas De Marchi dig_port->saved_port_bits = 51197801f3b7SLucas De Marchi intel_de_read(dev_priv, DDI_BUF_CTL(port)) 51207801f3b7SLucas De Marchi & (DDI_BUF_PORT_REVERSAL | DDI_A_4_LANES); 512170dfbc29SLucas De Marchi 51225f42196dSVille Syrjälä if (intel_bios_encoder_lane_reversal(devdata)) 5123aaab24bbSUma Shankar dig_port->saved_port_bits |= DDI_BUF_PORT_REVERSAL; 5124aaab24bbSUma Shankar 51257801f3b7SLucas De Marchi dig_port->dp.output_reg = INVALID_MMIO_REG; 51267801f3b7SLucas De Marchi dig_port->max_lanes = intel_ddi_max_lanes(dig_port); 51279856308cSVille Syrjälä 5128b8a13e87SVille Syrjälä if (need_aux_ch(encoder, init_dp)) { 5129bb45217fSVille Syrjälä dig_port->aux_ch = intel_dp_aux_ch(encoder); 5130b8a13e87SVille Syrjälä if (dig_port->aux_ch == AUX_CH_NONE) 5131b8a13e87SVille Syrjälä goto err; 5132b8a13e87SVille Syrjälä } 5133379bc100SJani Nikula 51347fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) { 5135c5faae5aSJani Nikula bool is_legacy = 5136f08fbe6aSJani Nikula !intel_bios_encoder_supports_typec_usb(devdata) && 5137f08fbe6aSJani Nikula !intel_bios_encoder_supports_tbt(devdata); 5138379bc100SJani Nikula 513940a55b84SImre Deak if (!is_legacy && init_hdmi) { 514040a55b84SImre Deak is_legacy = !init_dp; 514140a55b84SImre Deak 514240a55b84SImre Deak drm_dbg_kms(&dev_priv->drm, 514340a55b84SImre Deak "VBT says port %c is non-legacy TC and has HDMI (with DP: %s), assume it's %s\n", 514440a55b84SImre Deak port_name(port), 514540a55b84SImre Deak str_yes_no(init_dp), 514640a55b84SImre Deak is_legacy ? "legacy" : "non-legacy"); 514740a55b84SImre Deak } 514840a55b84SImre Deak 5149b61fad5fSImre Deak encoder->suspend_complete = intel_ddi_tc_encoder_suspend_complete; 5150b61fad5fSImre Deak encoder->shutdown_complete = intel_ddi_tc_encoder_shutdown_complete; 5151b61fad5fSImre Deak 51529210e94aSImre Deak dig_port->lock = intel_tc_port_lock; 51539210e94aSImre Deak dig_port->unlock = intel_tc_port_unlock; 51549210e94aSImre Deak 5155c5879999SImre Deak if (intel_tc_port_init(dig_port, is_legacy) < 0) 5156c5879999SImre Deak goto err; 5157ab7bc4e1SImre Deak } 5158ab7bc4e1SImre Deak 51591de143ccSPankaj Bharadiya drm_WARN_ON(&dev_priv->drm, port > PORT_I); 5160979e1b32SImre Deak dig_port->ddi_io_power_domain = intel_display_power_ddi_io_domain(dev_priv, port); 5161379bc100SJani Nikula 5162005e9537SMatt Roper if (DISPLAY_VER(dev_priv) >= 11) { 51637fcf7558SJani Nikula if (intel_encoder_is_tc(encoder)) 51647801f3b7SLucas De Marchi dig_port->connected = intel_tc_port_connected; 5165edc0e09cSVille Syrjälä else 51667801f3b7SLucas De Marchi dig_port->connected = lpt_digital_port_connected; 5167dded35acSVille Syrjälä } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { 5168dded35acSVille Syrjälä dig_port->connected = bdw_digital_port_connected; 5169dded35acSVille Syrjälä } else if (DISPLAY_VER(dev_priv) == 9) { 5170dded35acSVille Syrjälä dig_port->connected = lpt_digital_port_connected; 5171dded35acSVille Syrjälä } else if (IS_BROADWELL(dev_priv)) { 5172dded35acSVille Syrjälä if (port == PORT_A) 51737801f3b7SLucas De Marchi dig_port->connected = bdw_digital_port_connected; 5174edc0e09cSVille Syrjälä else 51757801f3b7SLucas De Marchi dig_port->connected = lpt_digital_port_connected; 5176dded35acSVille Syrjälä } else if (IS_HASWELL(dev_priv)) { 5177c7e8a3d6SVille Syrjälä if (port == PORT_A) 51787801f3b7SLucas De Marchi dig_port->connected = hsw_digital_port_connected; 5179edc0e09cSVille Syrjälä else 51807801f3b7SLucas De Marchi dig_port->connected = lpt_digital_port_connected; 5181edc0e09cSVille Syrjälä } 5182edc0e09cSVille Syrjälä 51837801f3b7SLucas De Marchi intel_infoframe_init(dig_port); 5184379bc100SJani Nikula 5185a98ffd6eSVille Syrjälä if (init_dp) { 5186a98ffd6eSVille Syrjälä if (!intel_ddi_init_dp_connector(dig_port)) 5187a98ffd6eSVille Syrjälä goto err; 5188a98ffd6eSVille Syrjälä 5189a98ffd6eSVille Syrjälä dig_port->hpd_pulse = intel_dp_hpd_pulse; 5190a98ffd6eSVille Syrjälä 5191a98ffd6eSVille Syrjälä if (dig_port->dp.mso_link_count) 5192a98ffd6eSVille Syrjälä encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv); 5193a98ffd6eSVille Syrjälä } 5194a98ffd6eSVille Syrjälä 5195a98ffd6eSVille Syrjälä /* 5196a98ffd6eSVille Syrjälä * In theory we don't need the encoder->type check, 5197a98ffd6eSVille Syrjälä * but leave it just in case we have some really bad VBTs... 5198a98ffd6eSVille Syrjälä */ 5199a98ffd6eSVille Syrjälä if (encoder->type != INTEL_OUTPUT_EDP && init_hdmi) { 5200a98ffd6eSVille Syrjälä if (!intel_ddi_init_hdmi_connector(dig_port)) 5201a98ffd6eSVille Syrjälä goto err; 5202a98ffd6eSVille Syrjälä } 5203a98ffd6eSVille Syrjälä 5204379bc100SJani Nikula return; 5205379bc100SJani Nikula 5206379bc100SJani Nikula err: 520770dfbc29SLucas De Marchi drm_encoder_cleanup(&encoder->base); 52087801f3b7SLucas De Marchi kfree(dig_port); 5209379bc100SJani Nikula } 5210