summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c112
1 files changed, 102 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f2c1d030f7f9..48ea0fca1f72 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -58,24 +58,24 @@
static void gen9_init_clock_gating(struct drm_i915_private *dev_priv)
{
- /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl */
+ /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */
I915_WRITE(CHICKEN_PAR1_1,
I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP);
I915_WRITE(GEN8_CONFIG0,
I915_READ(GEN8_CONFIG0) | GEN9_DEFAULT_FIXES);
- /* WaEnableChickenDCPR:skl,bxt,kbl,glk */
+ /* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */
I915_WRITE(GEN8_CHICKEN_DCPR_1,
I915_READ(GEN8_CHICKEN_DCPR_1) | MASK_WAKEMEM);
- /* WaFbcTurnOffFbcWatermark:skl,bxt,kbl */
- /* WaFbcWakeMemOn:skl,bxt,kbl,glk */
+ /* WaFbcTurnOffFbcWatermark:skl,bxt,kbl,cfl */
+ /* WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl */
I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
DISP_FBC_WM_DIS |
DISP_FBC_MEMORY_WAKE);
- /* WaFbcHighMemBwCorruptionAvoidance:skl,bxt,kbl */
+ /* WaFbcHighMemBwCorruptionAvoidance:skl,bxt,kbl,cfl */
I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) |
ILK_DPFC_DISABLE_DUMMY0);
}
@@ -3549,7 +3549,7 @@ static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state)
static bool
intel_has_sagv(struct drm_i915_private *dev_priv)
{
- if (IS_KABYLAKE(dev_priv))
+ if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv))
return true;
if (IS_SKYLAKE(dev_priv) &&
@@ -3869,6 +3869,97 @@ skl_plane_downscale_amount(const struct intel_crtc_state *cstate,
return mul_fixed16(downscale_w, downscale_h);
}
+static uint_fixed_16_16_t
+skl_pipe_downscale_amount(const struct intel_crtc_state *crtc_state)
+{
+ uint_fixed_16_16_t pipe_downscale = u32_to_fixed_16_16(1);
+
+ if (!crtc_state->base.enable)
+ return pipe_downscale;
+
+ if (crtc_state->pch_pfit.enabled) {
+ uint32_t src_w, src_h, dst_w, dst_h;
+ uint32_t pfit_size = crtc_state->pch_pfit.size;
+ uint_fixed_16_16_t fp_w_ratio, fp_h_ratio;
+ uint_fixed_16_16_t downscale_h, downscale_w;
+
+ src_w = crtc_state->pipe_src_w;
+ src_h = crtc_state->pipe_src_h;
+ dst_w = pfit_size >> 16;
+ dst_h = pfit_size & 0xffff;
+
+ if (!dst_w || !dst_h)
+ return pipe_downscale;
+
+ fp_w_ratio = fixed_16_16_div(src_w, dst_w);
+ fp_h_ratio = fixed_16_16_div(src_h, dst_h);
+ downscale_w = max_fixed_16_16(fp_w_ratio, u32_to_fixed_16_16(1));
+ downscale_h = max_fixed_16_16(fp_h_ratio, u32_to_fixed_16_16(1));
+
+ pipe_downscale = mul_fixed16(downscale_w, downscale_h);
+ }
+
+ return pipe_downscale;
+}
+
+int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc,
+ struct intel_crtc_state *cstate)
+{
+ struct drm_crtc_state *crtc_state = &cstate->base;
+ struct drm_atomic_state *state = crtc_state->state;
+ struct drm_plane *plane;
+ const struct drm_plane_state *pstate;
+ struct intel_plane_state *intel_pstate;
+ int crtc_clock, dotclk;
+ uint32_t pipe_max_pixel_rate;
+ uint_fixed_16_16_t pipe_downscale;
+ uint_fixed_16_16_t max_downscale = u32_to_fixed_16_16(1);
+
+ if (!cstate->base.enable)
+ return 0;
+
+ drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
+ uint_fixed_16_16_t plane_downscale;
+ uint_fixed_16_16_t fp_9_div_8 = fixed_16_16_div(9, 8);
+ int bpp;
+
+ if (!intel_wm_plane_visible(cstate,
+ to_intel_plane_state(pstate)))
+ continue;
+
+ if (WARN_ON(!pstate->fb))
+ return -EINVAL;
+
+ intel_pstate = to_intel_plane_state(pstate);
+ plane_downscale = skl_plane_downscale_amount(cstate,
+ intel_pstate);
+ bpp = pstate->fb->format->cpp[0] * 8;
+ if (bpp == 64)
+ plane_downscale = mul_fixed16(plane_downscale,
+ fp_9_div_8);
+
+ max_downscale = max_fixed_16_16(plane_downscale, max_downscale);
+ }
+ pipe_downscale = skl_pipe_downscale_amount(cstate);
+
+ pipe_downscale = mul_fixed16(pipe_downscale, max_downscale);
+
+ crtc_clock = crtc_state->adjusted_mode.crtc_clock;
+ dotclk = to_intel_atomic_state(state)->cdclk.logical.cdclk;
+
+ if (IS_GEMINILAKE(to_i915(intel_crtc->base.dev)))
+ dotclk *= 2;
+
+ pipe_max_pixel_rate = div_round_up_u32_fixed16(dotclk, pipe_downscale);
+
+ if (pipe_max_pixel_rate < crtc_clock) {
+ DRM_DEBUG_KMS("Max supported pixel clock with scaling exceeded\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static unsigned int
skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
const struct drm_plane_state *pstate,
@@ -4289,8 +4380,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
fb->modifier == I915_FORMAT_MOD_Yf_TILED;
x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED;
- /* Display WA #1141: kbl. */
- if (IS_KABYLAKE(dev_priv) && dev_priv->ipc_enabled)
+ /* Display WA #1141: kbl,cfl */
+ if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) &&
+ dev_priv->ipc_enabled)
latency += 4;
if (apply_memory_bw_wa && x_tiled)
@@ -8160,7 +8252,7 @@ static void kabylake_init_clock_gating(struct drm_i915_private *dev_priv)
I915_WRITE(GEN6_UCGCTL1, I915_READ(GEN6_UCGCTL1) |
GEN6_GAMUNIT_CLOCK_GATE_DISABLE);
- /* WaFbcNukeOnHostModify:kbl */
+ /* WaFbcNukeOnHostModify:kbl,cfl */
I915_WRITE(ILK_DPFC_CHICKEN, I915_READ(ILK_DPFC_CHICKEN) |
ILK_DPFC_NUKE_ON_ANY_MODIFICATION);
}
@@ -8628,7 +8720,7 @@ void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv)
{
if (IS_SKYLAKE(dev_priv))
dev_priv->display.init_clock_gating = skylake_init_clock_gating;
- else if (IS_KABYLAKE(dev_priv))
+ else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv))
dev_priv->display.init_clock_gating = kabylake_init_clock_gating;
else if (IS_BROXTON(dev_priv))
dev_priv->display.init_clock_gating = bxt_init_clock_gating;