diff options
author | Kalle Valo <kvalo@kernel.org> | 2023-01-17 13:36:25 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@kernel.org> | 2023-01-17 13:36:25 +0200 |
commit | d0e99511834b6828c960e978d9a8cb6e5731250d (patch) | |
tree | e7b062c1f9d28a55083477a1462286a7923a57fd /drivers/gpu/drm/i915/display/intel_ddi.c | |
parent | de7d0ff301fccc75281d7d8eb98c4a47faacf32d (diff) | |
parent | 80f8a66dede0a4b4e9e846765a97809c6fe49ce5 (diff) | |
download | linux-d0e99511834b6828c960e978d9a8cb6e5731250d.tar.gz linux-d0e99511834b6828c960e978d9a8cb6e5731250d.tar.bz2 linux-d0e99511834b6828c960e978d9a8cb6e5731250d.zip |
Merge wireless into wireless-next
Due to the two cherry picked commits from wireless to wireless-next we have
several conflicts in mt76. To avoid any bugs with conflicts merge wireless into
wireless-next.
96f134dc1964 wifi: mt76: handle possible mt76_rx_token_consume failures
fe13dad8992b wifi: mt76: dma: do not increment queue head if mt76_dma_add_buf fails
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_ddi.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_ddi.c | 137 |
1 files changed, 82 insertions, 55 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 69ecf2a3d6c6..0f1ec2a98cc8 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -31,6 +31,7 @@ #include <drm/drm_privacy_screen_consumer.h> #include "i915_drv.h" +#include "i915_reg.h" #include "intel_audio.h" #include "intel_audio_regs.h" #include "intel_backlight.h" @@ -44,6 +45,7 @@ #include "intel_display_power.h" #include "intel_display_types.h" #include "intel_dkl_phy.h" +#include "intel_dkl_phy_regs.h" #include "intel_dp.h" #include "intel_dp_link_training.h" #include "intel_dp_mst.h" @@ -55,14 +57,15 @@ #include "intel_hdcp.h" #include "intel_hdmi.h" #include "intel_hotplug.h" +#include "intel_hti.h" #include "intel_lspcon.h" +#include "intel_mg_phy_regs.h" #include "intel_pps.h" #include "intel_psr.h" #include "intel_quirks.h" #include "intel_snps_phy.h" #include "intel_sprite.h" #include "intel_tc.h" -#include "intel_tc_phy_regs.h" #include "intel_vdsc.h" #include "intel_vrr.h" #include "skl_scaler.h" @@ -845,22 +848,65 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, } static enum intel_display_power_domain -intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port) +intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port, + const struct intel_crtc_state *crtc_state) { - /* ICL+ HW requires corresponding AUX IOs to be powered up for PSR with + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); + + /* + * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with * DC states enabled at the same time, while for driver initiated AUX * transfers we need the same AUX IOs to be powered but with DC states - * disabled. Accordingly use the AUX power domain here which leaves DC - * states enabled. - * However, for non-A AUX ports the corresponding non-EDP transcoders - * would have already enabled power well 2 and DC_OFF. This means we can - * acquire a wider POWER_DOMAIN_AUX_{B,C,D,F} reference instead of a - * specific AUX_IO reference without powering up any extra wells. - * Note that PSR is enabled only on Port A even though this function - * returns the correct domain for other ports too. + * disabled. Accordingly use the AUX_IO_<port> power domain here which + * leaves DC states enabled. + * + * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require + * AUX IO to be enabled, but all these require DC_OFF to be enabled as + * well, so we can acquire a wider AUX_<port> power domain reference + * instead of a specific AUX_IO_<port> reference without powering up any + * extra wells. */ - return dig_port->aux_ch == AUX_CH_A ? POWER_DOMAIN_AUX_IO_A : - intel_aux_power_domain(dig_port); + if (intel_encoder_can_psr(&dig_port->base)) + return intel_display_power_aux_io_domain(i915, dig_port->aux_ch); + else if (DISPLAY_VER(i915) < 14 && + (intel_crtc_has_dp_encoder(crtc_state) || + intel_phy_is_tc(i915, phy))) + return intel_aux_power_domain(dig_port); + else + return POWER_DOMAIN_INVALID; +} + +static void +main_link_aux_power_domain_get(struct intel_digital_port *dig_port, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum intel_display_power_domain domain = + intel_ddi_main_link_aux_domain(dig_port, crtc_state); + + drm_WARN_ON(&i915->drm, dig_port->aux_wakeref); + + if (domain == POWER_DOMAIN_INVALID) + return; + + dig_port->aux_wakeref = intel_display_power_get(i915, domain); +} + +static void +main_link_aux_power_domain_put(struct intel_digital_port *dig_port, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); + enum intel_display_power_domain domain = + intel_ddi_main_link_aux_domain(dig_port, crtc_state); + intel_wakeref_t wf; + + wf = fetch_and_zero(&dig_port->aux_wakeref); + if (!wf) + return; + + intel_display_power_put(i915, domain, wf); } static void intel_ddi_get_power_domains(struct intel_encoder *encoder, @@ -868,7 +914,6 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port; - enum phy phy = intel_port_to_phy(dev_priv, encoder->port); /* * TODO: Add support for MST encoders. Atm, the following should never @@ -887,17 +932,7 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder, dig_port->ddi_io_power_domain); } - /* - * AUX power is only needed for (e)DP mode, and for HDMI mode on TC - * ports. - */ - if (intel_crtc_has_dp_encoder(crtc_state) || - intel_phy_is_tc(dev_priv, phy)) { - drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref); - dig_port->aux_wakeref = - intel_display_power_get(dev_priv, - intel_ddi_main_link_aux_domain(dig_port)); - } + main_link_aux_power_domain_get(dig_port, crtc_state); } void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder, @@ -1263,11 +1298,11 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, for (ln = 0; ln < 2; ln++) { int level; - intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), ln, 0); + intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0); level = intel_ddi_level(encoder, crtc_state, 2*ln+0); - intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), ln, + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln), DKL_TX_PRESHOOT_COEFF_MASK | DKL_TX_DE_EMPAHSIS_COEFF_MASK | DKL_TX_VSWING_CONTROL_MASK, @@ -1277,7 +1312,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, level = intel_ddi_level(encoder, crtc_state, 2*ln+1); - intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), ln, + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln), DKL_TX_PRESHOOT_COEFF_MASK | DKL_TX_DE_EMPAHSIS_COEFF_MASK | DKL_TX_VSWING_CONTROL_MASK, @@ -1285,7 +1320,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) | DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing)); - intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln, + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln), DKL_TX_DP20BITMODE, 0); if (IS_ALDERLAKE_P(dev_priv)) { @@ -1304,7 +1339,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder, val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0); } - intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln, + intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln), DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK | DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, val); @@ -2017,8 +2052,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, return; if (DISPLAY_VER(dev_priv) >= 12) { - ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 0); - ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 1); + ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0)); + ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1)); } else { ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port)); ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port)); @@ -2079,8 +2114,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port, } if (DISPLAY_VER(dev_priv) >= 12) { - intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 0, ln0); - intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 1, ln1); + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0); + intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1); } else { intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0); intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1); @@ -2736,10 +2771,7 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state, intel_ddi_post_disable_dp(state, encoder, old_crtc_state, old_conn_state); - if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port) - intel_display_power_put(dev_priv, - intel_ddi_main_link_aux_domain(dig_port), - fetch_and_zero(&dig_port->aux_wakeref)); + main_link_aux_power_domain_put(dig_port, old_crtc_state); if (is_tc_port) intel_tc_port_put_link(dig_port); @@ -3060,12 +3092,7 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, if (is_tc_port) intel_tc_port_get_link(dig_port, crtc_state->lane_count); - if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port) { - drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref); - dig_port->aux_wakeref = - intel_display_power_get(dev_priv, - intel_ddi_main_link_aux_domain(dig_port)); - } + main_link_aux_power_domain_get(dig_port, crtc_state); if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port)) /* @@ -3085,7 +3112,7 @@ static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder) int ln; for (ln = 0; ln < 2; ln++) - intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port), ln, DKL_PCS_DW5_CORE_SOFTRESET, 0); + intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0); } static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp, @@ -3524,7 +3551,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, if (drm_WARN_ON(&i915->drm, !pll)) return; - if (intel_get_shared_dpll_id(i915, pll) == DPLL_ID_ICL_TBTPLL) + if (pll->info->id == DPLL_ID_ICL_TBTPLL) port_dpll_id = ICL_PORT_DPLL_DEFAULT; else port_dpll_id = ICL_PORT_DPLL_MG_PHY; @@ -3537,7 +3564,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder, icl_set_active_port_dpll(crtc_state, port_dpll_id); - if (intel_get_shared_dpll_id(i915, crtc_state->shared_dpll) == DPLL_ID_ICL_TBTPLL) + if (crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL) crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port); else crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll, @@ -3579,7 +3606,7 @@ static void intel_ddi_sync_state(struct intel_encoder *encoder, enum phy phy = intel_port_to_phy(i915, encoder->port); if (intel_phy_is_tc(i915, phy)) - intel_tc_port_sanitize(enc_to_dig_port(encoder)); + intel_tc_port_sanitize_mode(enc_to_dig_port(encoder)); if (crtc_state && intel_crtc_has_dp_encoder(crtc_state)) intel_dp_sync_state(encoder, crtc_state); @@ -3789,11 +3816,17 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) static void intel_ddi_encoder_reset(struct drm_encoder *encoder) { + struct drm_i915_private *i915 = to_i915(encoder->dev); struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder)); + struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder)); + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); intel_dp->reset_link_params = true; intel_pps_encoder_reset(intel_dp); + + if (intel_phy_is_tc(i915, phy)) + intel_tc_port_init_mode(dig_port); } static const struct drm_encoder_funcs intel_ddi_funcs = { @@ -4106,12 +4139,6 @@ intel_ddi_max_lanes(struct intel_digital_port *dig_port) return max_lanes; } -static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy) -{ - return i915->hti_state & HDPORT_ENABLED && - i915->hti_state & HDPORT_DDI_USED(phy); -} - static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv, enum port port) { @@ -4240,7 +4267,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) * driver. In that case we should skip initializing the corresponding * outputs. */ - if (hti_uses_phy(dev_priv, phy)) { + if (intel_hti_uses_phy(dev_priv, phy)) { drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n", port_name(port), phy_name(phy)); return; |