drm/i915/ivb: Move WaCxSRDisabledForSpriteScaling w/a to atomic check
authorMatt Roper <matthew.d.roper@intel.com>
Thu, 24 Sep 2015 22:53:12 +0000 (15:53 -0700)
committerMatt Roper <matthew.d.roper@intel.com>
Wed, 21 Oct 2015 21:53:23 +0000 (14:53 -0700)
Determine whether we need to apply this workaround at atomic check time
and just set a flag that will be used by the main watermark update
routine.

Moving this workaround into the atomic framework reduces
ilk_update_sprite_wm() to just a standard watermark update, so drop it
completely and just ensure that ilk_update_wm() is called whenever a
sprite plane is updated in a way that would affect watermarks.

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Smoke-tested-by: Paulo Zanoni <przanoni@gmail.com>
Link: http://patchwork.freedesktop.org/patch/60367/
drivers/gpu/drm/i915/intel_atomic.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_pm.c

index f1975f267710ba22f0569c3abfa026dc10b5985b..05b12032d2628fe2dab8d059b1b7c881ceb881a4 100644 (file)
@@ -94,6 +94,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
        __drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
 
        crtc_state->update_pipe = false;
+       crtc_state->disable_lp_wm = false;
 
        return &crtc_state->base;
 }
index bd1977ed6e88af557d31a6ee15d08bbe0c666125..49af225757bd22f68c19f514fa0b39fb4e58be03 100644 (file)
@@ -11581,18 +11581,32 @@ retry:
 static bool intel_wm_need_update(struct drm_plane *plane,
                                 struct drm_plane_state *state)
 {
-       /* Update watermarks on tiling changes. */
+       struct intel_plane_state *new = to_intel_plane_state(state);
+       struct intel_plane_state *cur = to_intel_plane_state(plane->state);
+
+       /* Update watermarks on tiling or size changes. */
        if (!plane->state->fb || !state->fb ||
            plane->state->fb->modifier[0] != state->fb->modifier[0] ||
-           plane->state->rotation != state->rotation)
-               return true;
-
-       if (plane->state->crtc_w != state->crtc_w)
+           plane->state->rotation != state->rotation ||
+           drm_rect_width(&new->src) != drm_rect_width(&cur->src) ||
+           drm_rect_height(&new->src) != drm_rect_height(&cur->src) ||
+           drm_rect_width(&new->dst) != drm_rect_width(&cur->dst) ||
+           drm_rect_height(&new->dst) != drm_rect_height(&cur->dst))
                return true;
 
        return false;
 }
 
+static bool needs_scaling(struct intel_plane_state *state)
+{
+       int src_w = drm_rect_width(&state->src) >> 16;
+       int src_h = drm_rect_height(&state->src) >> 16;
+       int dst_w = drm_rect_width(&state->dst);
+       int dst_h = drm_rect_height(&state->dst);
+
+       return (src_w != dst_w || src_h != dst_h);
+}
+
 int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
                                    struct drm_plane_state *plane_state)
 {
@@ -11608,7 +11622,6 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        bool mode_changed = needs_modeset(crtc_state);
        bool was_crtc_enabled = crtc->state->active;
        bool is_crtc_enabled = crtc_state->active;
-
        bool turn_off, turn_on, visible, was_visible;
        struct drm_framebuffer *fb = plane_state->fb;
 
@@ -11718,11 +11731,23 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state,
        case DRM_PLANE_TYPE_CURSOR:
                break;
        case DRM_PLANE_TYPE_OVERLAY:
-               if (turn_off && !mode_changed) {
+               /*
+                * WaCxSRDisabledForSpriteScaling:ivb
+                *
+                * cstate->update_wm was already set above, so this flag will
+                * take effect when we commit and program watermarks.
+                */
+               if (IS_IVYBRIDGE(dev) &&
+                   needs_scaling(to_intel_plane_state(plane_state)) &&
+                   !needs_scaling(old_plane_state)) {
+                       to_intel_crtc_state(crtc_state)->disable_lp_wm = true;
+               } else if (turn_off && !mode_changed) {
                        intel_crtc->atomic.wait_vblank = true;
                        intel_crtc->atomic.update_sprite_watermarks |=
                                1 << i;
                }
+
+               break;
        }
        return 0;
 }
index 6790187de8dce2bba16149dbc321e9a270a2801d..754fdce86aa2bb613c33b0a1bb73747fb3a3f717 100644 (file)
@@ -468,6 +468,9 @@ struct intel_crtc_state {
 
        /* w/a for waiting 2 vblanks during crtc enable */
        enum pipe hsw_workaround_pipe;
+
+       /* IVB sprite scaling w/a (WaCxSRDisabledForSpriteScaling:ivb) */
+       bool disable_lp_wm;
 };
 
 struct vlv_wm_state {
index 4c1c1bb96a9e1aef55e829514da483823e0f657e..af9057a381cfa2158d070b1a05660943dead8d2b 100644 (file)
@@ -3674,6 +3674,18 @@ static void ilk_update_wm(struct drm_crtc *crtc)
 
        WARN_ON(cstate->base.active != intel_crtc->active);
 
+       /*
+        * IVB workaround: must disable low power watermarks for at least
+        * one frame before enabling scaling.  LP watermarks can be re-enabled
+        * when scaling is disabled.
+        *
+        * WaCxSRDisabledForSpriteScaling:ivb
+        */
+       if (cstate->disable_lp_wm) {
+               ilk_disable_lp_wm(dev);
+               intel_wait_for_vblank(dev, intel_crtc->pipe);
+       }
+
        intel_compute_pipe_wm(cstate, &pipe_wm);
 
        if (!memcmp(&intel_crtc->wm.active, &pipe_wm, sizeof(pipe_wm)))
@@ -3705,28 +3717,6 @@ static void ilk_update_wm(struct drm_crtc *crtc)
        ilk_write_wm_values(dev_priv, &results);
 }
 
-static void
-ilk_update_sprite_wm(struct drm_plane *plane,
-                    struct drm_crtc *crtc,
-                    uint32_t sprite_width, uint32_t sprite_height,
-                    int pixel_size, bool enabled, bool scaled)
-{
-       struct drm_device *dev = plane->dev;
-       struct intel_plane *intel_plane = to_intel_plane(plane);
-
-       /*
-        * IVB workaround: must disable low power watermarks for at least
-        * one frame before enabling scaling.  LP watermarks can be re-enabled
-        * when scaling is disabled.
-        *
-        * WaCxSRDisabledForSpriteScaling:ivb
-        */
-       if (IS_IVYBRIDGE(dev) && scaled && ilk_disable_lp_wm(dev))
-               intel_wait_for_vblank(dev, intel_plane->pipe);
-
-       ilk_update_wm(crtc);
-}
-
 static void skl_pipe_wm_active_state(uint32_t val,
                                     struct skl_pipe_wm *active,
                                     bool is_transwm,
@@ -7040,7 +7030,6 @@ void intel_init_pm(struct drm_device *dev)
                    (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] &&
                     dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) {
                        dev_priv->display.update_wm = ilk_update_wm;
-                       dev_priv->display.update_sprite_wm = ilk_update_sprite_wm;
                } else {
                        DRM_DEBUG_KMS("Failed to read display plane latency. "
                                      "Disable CxSR\n");