diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_ddi.c | 162 |
1 files changed, 121 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 953de42e277c..390869bd6b63 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -31,8 +31,10 @@ #include "intel_audio.h" #include "intel_combo_phy.h" #include "intel_connector.h" +#include "intel_crtc.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" +#include "intel_de.h" #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dp_link_training.h" @@ -113,7 +115,8 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder, &n_entries); /* If we're boosting the current, set bit 31 of trans1 */ - if (IS_GEN9_BC(dev_priv) && intel_bios_encoder_dp_boost_level(encoder->devdata)) + if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv) && + intel_bios_encoder_dp_boost_level(encoder->devdata)) iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; for (i = 0; i < n_entries; i++) { @@ -146,7 +149,8 @@ static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder, level = n_entries - 1; /* If we're boosting the current, set bit 31 of trans1 */ - if (IS_GEN9_BC(dev_priv) && intel_bios_encoder_hdmi_boost_level(encoder->devdata)) + if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv) && + intel_bios_encoder_hdmi_boost_level(encoder->devdata)) iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; /* Entry 9 is for HDMI: */ @@ -174,7 +178,7 @@ static void intel_wait_ddi_buf_active(struct drm_i915_private *dev_priv, enum port port) { /* Wait > 518 usecs for DDI_BUF_CTL to be non idle */ - if (DISPLAY_VER(dev_priv) < 10 && !IS_GEMINILAKE(dev_priv)) { + if (DISPLAY_VER(dev_priv) < 10) { usleep_range(518, 1000); return; } @@ -245,15 +249,48 @@ static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder, } } +static u32 ddi_buf_phy_link_rate(int port_clock) +{ + switch (port_clock) { + case 162000: + return DDI_BUF_PHY_LINK_RATE(0); + case 216000: + return DDI_BUF_PHY_LINK_RATE(4); + case 243000: + return DDI_BUF_PHY_LINK_RATE(5); + case 270000: + return DDI_BUF_PHY_LINK_RATE(1); + case 324000: + return DDI_BUF_PHY_LINK_RATE(6); + case 432000: + return DDI_BUF_PHY_LINK_RATE(7); + case 540000: + return DDI_BUF_PHY_LINK_RATE(2); + case 810000: + return DDI_BUF_PHY_LINK_RATE(3); + default: + MISSING_CASE(port_clock); + return DDI_BUF_PHY_LINK_RATE(0); + } +} + static void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + enum phy phy = intel_port_to_phy(i915, encoder->port); intel_dp->DP = dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE | DDI_BUF_TRANS_SELECT(0); intel_dp->DP |= DDI_PORT_WIDTH(crtc_state->lane_count); + + if (IS_ALDERLAKE_P(i915) && intel_phy_is_tc(i915, phy)) { + intel_dp->DP |= ddi_buf_phy_link_rate(crtc_state->port_clock); + if (dig_port->tc_mode != TC_PORT_TBT_ALT) + intel_dp->DP |= DDI_BUF_CTL_TC_PHY_OWNERSHIP; + } } static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv, @@ -471,7 +508,7 @@ intel_ddi_transcoder_func_reg_val_get(struct intel_encoder *encoder, temp |= DDI_PORT_WIDTH(crtc_state->lane_count); } - if (IS_DISPLAY_RANGE(dev_priv, 8, 10) && + if (IS_DISPLAY_VER(dev_priv, 8, 10) && crtc_state->master_transcoder != INVALID_TRANSCODER) { u8 master_select = bdw_trans_port_sync_master_select(crtc_state->master_transcoder); @@ -546,7 +583,7 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state ctl &= ~TRANS_DDI_FUNC_ENABLE; - if (IS_DISPLAY_RANGE(dev_priv, 8, 10)) + if (IS_DISPLAY_VER(dev_priv, 8, 10)) ctl &= ~(TRANS_DDI_PORT_SYNC_ENABLE | TRANS_DDI_PORT_SYNC_MASTER_SELECT_MASK); @@ -759,7 +796,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, *is_dp_mst = mst_pipe_mask; out: - if (*pipe_mask && IS_GEN9_LP(dev_priv)) { + if (*pipe_mask && (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv))) { tmp = intel_de_read(dev_priv, BXT_PHY_CTL(port)); if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK | BXT_PHY_LANE_POWERDOWN_ACK | @@ -850,18 +887,19 @@ void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder, { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum port port = encoder->port; enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + enum phy phy = intel_port_to_phy(dev_priv, encoder->port); + u32 val; if (cpu_transcoder != TRANSCODER_EDP) { - if (DISPLAY_VER(dev_priv) >= 12) - intel_de_write(dev_priv, - TRANS_CLK_SEL(cpu_transcoder), - TGL_TRANS_CLK_SEL_PORT(port)); + if (DISPLAY_VER(dev_priv) >= 13) + val = TGL_TRANS_CLK_SEL_PORT(phy); + else if (DISPLAY_VER(dev_priv) >= 12) + val = TGL_TRANS_CLK_SEL_PORT(encoder->port); else - intel_de_write(dev_priv, - TRANS_CLK_SEL(cpu_transcoder), - TRANS_CLK_SEL_PORT(port)); + val = TRANS_CLK_SEL_PORT(encoder->port); + + intel_de_write(dev_priv, TRANS_CLK_SEL(cpu_transcoder), val); } } @@ -974,9 +1012,11 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp, if (DISPLAY_VER(dev_priv) >= 12) { if (intel_phy_is_combo(dev_priv, phy)) tgl_get_combo_buf_trans(encoder, crtc_state, &n_entries); + else if (IS_ALDERLAKE_P(dev_priv)) + adlp_get_dkl_buf_trans(encoder, crtc_state, &n_entries); else tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries); - } else if (IS_DISPLAY_VER(dev_priv, 11)) { + } else if (DISPLAY_VER(dev_priv) == 11) { if (IS_PLATFORM(dev_priv, INTEL_JASPERLAKE)) jsl_get_combo_buf_trans(encoder, crtc_state, &n_entries); else if (IS_PLATFORM(dev_priv, INTEL_ELKHARTLAKE)) @@ -987,7 +1027,7 @@ static u8 intel_ddi_dp_voltage_max(struct intel_dp *intel_dp, icl_get_mg_buf_trans(encoder, crtc_state, &n_entries); } else if (IS_CANNONLAKE(dev_priv)) { cnl_get_buf_trans(encoder, crtc_state, &n_entries); - } else if (IS_GEN9_LP(dev_priv)) { + } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { bxt_get_buf_trans(encoder, crtc_state, &n_entries); } else { if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) @@ -1420,7 +1460,10 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, if (enc_to_dig_port(encoder)->tc_mode == TC_PORT_TBT_ALT) return; - ddi_translations = tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries); + if (IS_ALDERLAKE_P(dev_priv)) + ddi_translations = adlp_get_dkl_buf_trans(encoder, crtc_state, &n_entries); + else + ddi_translations = tgl_get_dkl_buf_trans(encoder, crtc_state, &n_entries); if (drm_WARN_ON_ONCE(&dev_priv->drm, !ddi_translations)) return; @@ -1454,6 +1497,14 @@ tgl_dkl_phy_ddi_vswing_sequence(struct intel_encoder *encoder, val = intel_de_read(dev_priv, DKL_TX_DPCNTL2(tc_port)); val &= ~DKL_TX_DP20BITMODE; intel_de_write(dev_priv, DKL_TX_DPCNTL2(tc_port), val); + + if ((intel_crtc_has_dp_encoder(crtc_state) && + crtc_state->port_clock == 162000) || + (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) && + crtc_state->port_clock == 594000)) + val |= DKL_TX_LOADGEN_SHARING_PMD_DISABLE; + else + val &= ~DKL_TX_LOADGEN_SHARING_PMD_DISABLE; } } @@ -1555,7 +1606,7 @@ hsw_set_signal_levels(struct intel_dp *intel_dp, intel_dp->DP &= ~DDI_BUF_EMP_MASK; intel_dp->DP |= signal_levels; - if (IS_GEN9_BC(dev_priv)) + if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) skl_ddi_set_iboost(encoder, crtc_state, level); intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); @@ -2332,8 +2383,8 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL, enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0) drm_dbg_kms(&i915->drm, - "Failed to set MSA_TIMING_PAR_IGNORE %s in the sink\n", - enable ? "enable" : "disable"); + "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n", + enabledisable(enable)); } static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, @@ -2648,7 +2699,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state, icl_ddi_vswing_sequence(encoder, crtc_state, level); else if (IS_CANNONLAKE(dev_priv)) cnl_ddi_vswing_sequence(encoder, crtc_state, level); - else if (IS_GEN9_LP(dev_priv)) + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) bxt_ddi_vswing_sequence(encoder, crtc_state, level); else intel_prepare_dp_ddi_buffers(encoder, crtc_state); @@ -2759,7 +2810,6 @@ static void intel_ddi_pre_enable(struct intel_atomic_state *state, conn_state); /* FIXME precompute everything properly */ - /* FIXME how do we turn infoframes off again? */ if (dig_port->lspcon.active && dig_port->dp.has_hdmi_sink) dig_port->set_infoframes(encoder, crtc_state->has_infoframe, @@ -3092,20 +3142,20 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, if (DISPLAY_VER(dev_priv) >= 12) tgl_ddi_vswing_sequence(encoder, crtc_state, level); - else if (IS_DISPLAY_VER(dev_priv, 11)) + else if (DISPLAY_VER(dev_priv) == 11) icl_ddi_vswing_sequence(encoder, crtc_state, level); else if (IS_CANNONLAKE(dev_priv)) cnl_ddi_vswing_sequence(encoder, crtc_state, level); - else if (IS_GEN9_LP(dev_priv)) + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) bxt_ddi_vswing_sequence(encoder, crtc_state, level); else intel_prepare_hdmi_ddi_buffers(encoder, level); - if (IS_GEN9_BC(dev_priv)) + if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) skl_ddi_set_iboost(encoder, crtc_state, level); /* Display WA #1143: skl,kbl,cfl */ - if (IS_GEN9_BC(dev_priv)) { + if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) { /* * For some reason these chicken bits have been * stuffed into a transcoder register, event though @@ -3144,6 +3194,9 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, /* In HDMI/DVI mode, the port width, and swing/emphasis values * are ignored so nothing special needs to be done besides * enabling the port. + * + * On ADL_P the PHY link rate and lane count must be programmed but + * these are both 0 for HDMI. */ intel_de_write(dev_priv, DDI_BUF_CTL(port), dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE); @@ -3321,7 +3374,7 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, * Type-C ports. Skip this step for TBT. */ intel_tc_port_set_fia_lane_count(dig_port, crtc_state->lane_count); - else if (IS_GEN9_LP(dev_priv)) + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) bxt_ddi_phy_set_lane_optim_mask(encoder, crtc_state->lane_lat_optim_mask); } @@ -3679,7 +3732,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, if (!pipe_config->bigjoiner_slave) ddi_dotclock_get(pipe_config); - if (IS_GEN9_LP(dev_priv)) + if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pipe_config->lane_lat_optim_mask = bxt_ddi_phy_get_lane_lat_optim_mask(encoder); @@ -3705,6 +3758,8 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA); intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); + + intel_psr_get_config(encoder, pipe_config); } void intel_ddi_get_clock(struct intel_encoder *encoder, @@ -3885,7 +3940,7 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder, pipe_config->pch_pfit.enabled || pipe_config->crc_enabled; - if (IS_GEN9_LP(dev_priv)) + if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) pipe_config->lane_lat_optim_mask = bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count); @@ -4007,9 +4062,11 @@ static int intel_ddi_compute_config_late(struct intel_encoder *encoder, static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) { + struct drm_i915_private *i915 = to_i915(encoder->dev); struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); intel_dp_encoder_flush_work(encoder); + intel_display_power_flush_work(i915); drm_encoder_cleanup(encoder); if (dig_port) @@ -4053,7 +4110,7 @@ intel_ddi_init_dp_connector(struct intel_digital_port *dig_port) dig_port->dp.set_signal_levels = icl_set_signal_levels; else if (IS_CANNONLAKE(dev_priv)) dig_port->dp.set_signal_levels = cnl_set_signal_levels; - else if (IS_GEN9_LP(dev_priv)) + else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) dig_port->dp.set_signal_levels = bxt_set_signal_levels; else dig_port->dp.set_signal_levels = hsw_set_signal_levels; @@ -4296,7 +4353,7 @@ static bool intel_ddi_a_force_4_lanes(struct intel_digital_port *dig_port) /* Broxton/Geminilake: Bspec says that DDI_A_4_LANES is the only * supported configuration */ - if (IS_GEN9_LP(dev_priv)) + if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) return true; /* Cannonlake: Most of SKUs don't support DDI_E, and the only @@ -4350,6 +4407,17 @@ static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy) i915->hti_state & HDPORT_DDI_USED(phy); } +static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv, + enum port port) +{ + if (port >= PORT_D_XELPD) + return HPD_PORT_D + port - PORT_D_XELPD; + else if (port >= PORT_TC1) + return HPD_PORT_TC1 + port - PORT_TC1; + else + return HPD_PORT_A + port - PORT_A; +} + static enum hpd_pin dg1_hpd_pin(struct drm_i915_private *dev_priv, enum port port) { @@ -4489,7 +4557,13 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder = &dig_port->base; encoder->devdata = devdata; - if (DISPLAY_VER(dev_priv) >= 12) { + if (DISPLAY_VER(dev_priv) >= 13 && port >= PORT_D_XELPD) { + drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, + DRM_MODE_ENCODER_TMDS, + "DDI %c/PHY %c", + port_name(port - PORT_D_XELPD + PORT_D), + phy_name(phy)); + } else if (DISPLAY_VER(dev_priv) >= 12) { enum tc_port tc_port = intel_port_to_tc(dev_priv, port); drm_encoder_init(&dev_priv->drm, &encoder->base, &intel_ddi_funcs, @@ -4585,10 +4659,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->disable_clock = cnl_ddi_disable_clock; encoder->is_clock_enabled = cnl_ddi_is_clock_enabled; encoder->get_config = cnl_ddi_get_config; - } else if (IS_GEN9_LP(dev_priv)) { + } else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) { /* BXT/GLK have fixed PLL->port mapping */ encoder->get_config = bxt_ddi_get_config; - } else if (IS_GEN9_BC(dev_priv)) { + } else if (DISPLAY_VER(dev_priv) == 9) { encoder->enable_clock = skl_ddi_enable_clock; encoder->disable_clock = skl_ddi_disable_clock; encoder->is_clock_enabled = skl_ddi_is_clock_enabled; @@ -4600,7 +4674,9 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->get_config = hsw_ddi_get_config; } - if (IS_DG1(dev_priv)) + if (DISPLAY_VER(dev_priv) >= 13) + encoder->hpd_pin = xelpd_hpd_pin(dev_priv, port); + else if (IS_DG1(dev_priv)) encoder->hpd_pin = dg1_hpd_pin(dev_priv, port); else if (IS_ROCKETLAKE(dev_priv)) encoder->hpd_pin = rkl_hpd_pin(dev_priv, port); @@ -4608,11 +4684,11 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) encoder->hpd_pin = tgl_hpd_pin(dev_priv, port); else if (IS_JSL_EHL(dev_priv)) encoder->hpd_pin = ehl_hpd_pin(dev_priv, port); - else if (IS_DISPLAY_VER(dev_priv, 11)) + else if (DISPLAY_VER(dev_priv) == 11) encoder->hpd_pin = icl_hpd_pin(dev_priv, port); - else if (IS_DISPLAY_VER(dev_priv, 10)) + else if (IS_CANNONLAKE(dev_priv)) encoder->hpd_pin = cnl_hpd_pin(dev_priv, port); - else if (IS_DISPLAY_VER(dev_priv, 9)) + else if (DISPLAY_VER(dev_priv) == 9 && !IS_BROXTON(dev_priv)) encoder->hpd_pin = skl_hpd_pin(dev_priv, port); else encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port); @@ -4654,9 +4730,12 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) dig_port->hpd_pulse = intel_dp_hpd_pulse; - /* Splitter enable for eDP MSO is supported for pipe A only. */ - if (dig_port->dp.mso_link_count) + /* Splitter enable for eDP MSO is limited to certain pipes. */ + if (dig_port->dp.mso_link_count) { encoder->pipe_mask = BIT(PIPE_A); + if (IS_ALDERLAKE_P(dev_priv)) + encoder->pipe_mask |= BIT(PIPE_B); + } } /* In theory we don't need the encoder->type check, but leave it just in @@ -4672,7 +4751,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) else dig_port->connected = lpt_digital_port_connected; } else if (DISPLAY_VER(dev_priv) >= 8) { - if (port == PORT_A || IS_GEN9_LP(dev_priv)) + if (port == PORT_A || IS_GEMINILAKE(dev_priv) || + IS_BROXTON(dev_priv)) dig_port->connected = bdw_digital_port_connected; else dig_port->connected = lpt_digital_port_connected; |