diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_psr.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_psr.c | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 31084d95711d..6badfff2b4a2 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -34,6 +34,7 @@ #include "intel_dp_aux.h" #include "intel_hdmi.h" #include "intel_psr.h" +#include "intel_psr_regs.h" #include "intel_snps_phy.h" #include "skl_universal_plane.h" @@ -519,6 +520,17 @@ static u32 intel_psr2_get_tp_time(struct intel_dp *intel_dp) return val; } +static int psr2_block_count_lines(struct intel_dp *intel_dp) +{ + return intel_dp->psr.io_wake_lines < 9 && + intel_dp->psr.fast_wake_lines < 9 ? 8 : 12; +} + +static int psr2_block_count(struct intel_dp *intel_dp) +{ + return psr2_block_count_lines(intel_dp) / 4; +} + static void hsw_activate_psr2(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -536,11 +548,10 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= intel_psr2_get_tp_time(intel_dp); if (DISPLAY_VER(dev_priv) >= 12) { - if (intel_dp->psr.io_wake_lines < 9 && - intel_dp->psr.fast_wake_lines < 9) - val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; - else + if (psr2_block_count(intel_dp) > 2) val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_3; + else + val |= TGL_EDP_PSR2_BLOCK_COUNT_NUM_2; } /* Wa_22012278275:adl-p */ @@ -958,6 +969,15 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } + /* Vblank >= PSR2_CTL Block Count Number maximum line count */ + if (crtc_state->hw.adjusted_mode.crtc_vblank_end - + crtc_state->hw.adjusted_mode.crtc_vblank_start < + psr2_block_count_lines(intel_dp)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, too short vblank time\n"); + return false; + } + if (HAS_PSR2_SEL_FETCH(dev_priv)) { if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && !HAS_PSR_HW_TRACKING(dev_priv)) { @@ -1134,6 +1154,34 @@ static u32 wa_16013835468_bit_get(struct intel_dp *intel_dp) } } +/* + * Wa_16013835468 + * Wa_14015648006 + */ +static void wm_optimization_wa(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + bool set_wa_bit = false; + + /* Wa_14015648006 */ + if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || + IS_DISPLAY_VER(dev_priv, 11, 13)) + set_wa_bit |= crtc_state->wm_level_disabled; + + /* Wa_16013835468 */ + if (DISPLAY_VER(dev_priv) == 12) + set_wa_bit |= crtc_state->hw.adjusted_mode.crtc_vblank_start != + crtc_state->hw.adjusted_mode.crtc_vdisplay; + + if (set_wa_bit) + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + 0, wa_16013835468_bit_get(intel_dp)); + else + intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, + wa_16013835468_bit_get(intel_dp), 0); +} + static void intel_psr_enable_source(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -1177,13 +1225,7 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, * Wa_16013835468 * Wa_14015648006 */ - if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || - IS_DISPLAY_VER(dev_priv, 12, 13)) { - if (crtc_state->hw.adjusted_mode.crtc_vblank_start != - crtc_state->hw.adjusted_mode.crtc_vdisplay) - intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, 0, - wa_16013835468_bit_get(intel_dp)); - } + wm_optimization_wa(intel_dp, crtc_state); if (intel_dp->psr.psr2_enabled) { if (DISPLAY_VER(dev_priv) == 9) @@ -1361,8 +1403,7 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) * Wa_16013835468 * Wa_14015648006 */ - if (IS_MTL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_B0) || - IS_DISPLAY_VER(dev_priv, 12, 13)) + if (DISPLAY_VER(dev_priv) >= 11) intel_de_rmw(dev_priv, GEN8_CHICKEN_DCPR_1, wa_16013835468_bit_get(intel_dp), 0); @@ -1928,14 +1969,20 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, * - PSR disabled in new state * - All planes will go inactive * - Changing between PSR versions + * - Display WA #1136: skl, bxt */ needs_to_disable |= intel_crtc_needs_modeset(new_crtc_state); needs_to_disable |= !new_crtc_state->has_psr; needs_to_disable |= !new_crtc_state->active_planes; needs_to_disable |= new_crtc_state->has_psr2 != psr->psr2_enabled; + needs_to_disable |= DISPLAY_VER(i915) < 11 && + new_crtc_state->wm_level_disabled; if (psr->enabled && needs_to_disable) intel_psr_disable_locked(intel_dp); + else if (psr->enabled && new_crtc_state->wm_level_disabled) + /* Wa_14015648006 */ + wm_optimization_wa(intel_dp, new_crtc_state); mutex_unlock(&psr->lock); } @@ -1954,23 +2001,29 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state, crtc_state->uapi.encoder_mask) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_psr *psr = &intel_dp->psr; + bool keep_disabled = false; mutex_lock(&psr->lock); - if (psr->sink_not_reliable) - goto exit; - drm_WARN_ON(&dev_priv->drm, psr->enabled && !crtc_state->active_planes); - /* Only enable if there is active planes */ - if (!psr->enabled && crtc_state->active_planes) + keep_disabled |= psr->sink_not_reliable; + keep_disabled |= !crtc_state->active_planes; + + /* Display WA #1136: skl, bxt */ + keep_disabled |= DISPLAY_VER(dev_priv) < 11 && + crtc_state->wm_level_disabled; + + if (!psr->enabled && !keep_disabled) intel_psr_enable_locked(intel_dp, crtc_state); + else if (psr->enabled && !crtc_state->wm_level_disabled) + /* Wa_14015648006 */ + wm_optimization_wa(intel_dp, crtc_state); /* Force a PSR exit when enabling CRC to avoid CRC timeouts */ if (crtc_state->crc_enabled && psr->enabled) psr_force_hw_tracking_exit(intel_dp); -exit: mutex_unlock(&psr->lock); } } |