drm/i915: Rename primary_disabled to primary_enabled
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_sprite.c
index 1fa5612a4572cc0c3b92a3d6a253bc9f1da573ed..8afaad6bcc4821981a2843a843d2d69c33151dd4 100644 (file)
@@ -38,7 +38,8 @@
 #include "i915_drv.h"
 
 static void
-vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
+vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
+                struct drm_framebuffer *fb,
                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
                 unsigned int crtc_w, unsigned int crtc_h,
                 uint32_t x, uint32_t y,
@@ -108,14 +109,15 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 
        sprctl |= SP_ENABLE;
 
+       intel_update_sprite_watermarks(dplane, crtc, src_w, pixel_size, true,
+                                      src_w != crtc_w || src_h != crtc_h);
+
        /* Sizes are 0 based */
        src_w--;
        src_h--;
        crtc_w--;
        crtc_h--;
 
-       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
-
        I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]);
        I915_WRITE(SPPOS(pipe, plane), (crtc_y << 16) | crtc_x);
 
@@ -133,13 +135,13 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_framebuffer *fb,
 
        I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
        I915_WRITE(SPCNTR(pipe, plane), sprctl);
-       I915_MODIFY_DISPBASE(SPSURF(pipe, plane), obj->gtt_offset +
+       I915_MODIFY_DISPBASE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
                             sprsurf_offset);
        POSTING_READ(SPSURF(pipe, plane));
 }
 
 static void
-vlv_disable_plane(struct drm_plane *dplane)
+vlv_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc)
 {
        struct drm_device *dev = dplane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -152,6 +154,8 @@ vlv_disable_plane(struct drm_plane *dplane)
        /* Activate double buffered register update */
        I915_MODIFY_DISPBASE(SPSURF(pipe, plane), 0);
        POSTING_READ(SPSURF(pipe, plane));
+
+       intel_update_sprite_watermarks(dplane, crtc, 0, 0, false, false);
 }
 
 static int
@@ -206,7 +210,8 @@ vlv_get_colorkey(struct drm_plane *dplane,
 }
 
 static void
-ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+                struct drm_framebuffer *fb,
                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
                 unsigned int crtc_w, unsigned int crtc_h,
                 uint32_t x, uint32_t y,
@@ -255,21 +260,25 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        if (obj->tiling_mode != I915_TILING_NONE)
                sprctl |= SPRITE_TILED;
 
-       /* must disable */
-       sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
+       if (IS_HASWELL(dev))
+               sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE;
+       else
+               sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
+
        sprctl |= SPRITE_ENABLE;
 
        if (IS_HASWELL(dev))
                sprctl |= SPRITE_PIPE_CSC_ENABLE;
 
+       intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+                                      src_w != crtc_w || src_h != crtc_h);
+
        /* Sizes are 0 based */
        src_w--;
        src_h--;
        crtc_w--;
        crtc_h--;
 
-       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
-
        /*
         * IVB workaround: must disable low power watermarks for at least
         * one frame before enabling scaling.  LP watermarks can be re-enabled
@@ -279,7 +288,7 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
                dev_priv->sprite_scaling_enabled |= 1 << pipe;
 
                if (!scaling_was_enabled) {
-                       intel_update_watermarks(dev);
+                       intel_update_watermarks(crtc);
                        intel_wait_for_vblank(dev, pipe);
                }
                sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
@@ -308,16 +317,17 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        if (intel_plane->can_scale)
                I915_WRITE(SPRSCALE(pipe), sprscale);
        I915_WRITE(SPRCTL(pipe), sprctl);
-       I915_MODIFY_DISPBASE(SPRSURF(pipe), obj->gtt_offset + sprsurf_offset);
+       I915_MODIFY_DISPBASE(SPRSURF(pipe),
+                            i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
        POSTING_READ(SPRSURF(pipe));
 
        /* potentially re-enable LP watermarks */
        if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-               intel_update_watermarks(dev);
+               intel_update_watermarks(crtc);
 }
 
 static void
-ivb_disable_plane(struct drm_plane *plane)
+ivb_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -335,11 +345,11 @@ ivb_disable_plane(struct drm_plane *plane)
 
        dev_priv->sprite_scaling_enabled &= ~(1 << pipe);
 
-       intel_update_sprite_watermarks(dev, pipe, 0, 0, false);
+       intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 
        /* potentially re-enable LP watermarks */
        if (scaling_was_enabled && !dev_priv->sprite_scaling_enabled)
-               intel_update_watermarks(dev);
+               intel_update_watermarks(crtc);
 }
 
 static int
@@ -397,7 +407,8 @@ ivb_get_colorkey(struct drm_plane *plane, struct drm_intel_sprite_colorkey *key)
 }
 
 static void
-ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
+ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+                struct drm_framebuffer *fb,
                 struct drm_i915_gem_object *obj, int crtc_x, int crtc_y,
                 unsigned int crtc_w, unsigned int crtc_h,
                 uint32_t x, uint32_t y,
@@ -449,14 +460,15 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
                dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */
        dvscntr |= DVS_ENABLE;
 
+       intel_update_sprite_watermarks(plane, crtc, src_w, pixel_size, true,
+                                      src_w != crtc_w || src_h != crtc_h);
+
        /* Sizes are 0 based */
        src_w--;
        src_h--;
        crtc_w--;
        crtc_h--;
 
-       intel_update_sprite_watermarks(dev, pipe, crtc_w, pixel_size, true);
-
        dvsscale = 0;
        if (IS_GEN5(dev) || crtc_w != src_w || crtc_h != src_h)
                dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
@@ -478,12 +490,13 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
        I915_WRITE(DVSSIZE(pipe), (crtc_h << 16) | crtc_w);
        I915_WRITE(DVSSCALE(pipe), dvsscale);
        I915_WRITE(DVSCNTR(pipe), dvscntr);
-       I915_MODIFY_DISPBASE(DVSSURF(pipe), obj->gtt_offset + dvssurf_offset);
+       I915_MODIFY_DISPBASE(DVSSURF(pipe),
+                            i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
        POSTING_READ(DVSSURF(pipe));
 }
 
 static void
-ilk_disable_plane(struct drm_plane *plane)
+ilk_disable_plane(struct drm_plane *plane, struct drm_crtc *crtc)
 {
        struct drm_device *dev = plane->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -496,6 +509,8 @@ ilk_disable_plane(struct drm_plane *plane)
        /* Flush double buffered register updates */
        I915_MODIFY_DISPBASE(DVSSURF(pipe), 0);
        POSTING_READ(DVSSURF(pipe));
+
+       intel_update_sprite_watermarks(plane, crtc, 0, 0, false, false);
 }
 
 static void
@@ -506,13 +521,28 @@ intel_enable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int reg = DSPCNTR(intel_crtc->plane);
 
-       if (!intel_crtc->primary_disabled)
+       if (intel_crtc->primary_enabled)
                return;
 
-       intel_crtc->primary_disabled = false;
-       intel_update_fbc(dev);
+       intel_crtc->primary_enabled = true;
 
        I915_WRITE(reg, I915_READ(reg) | DISPLAY_PLANE_ENABLE);
+       intel_flush_primary_plane(dev_priv, intel_crtc->plane);
+
+       /*
+        * FIXME IPS should be fine as long as one plane is
+        * enabled, but in practice it seems to have problems
+        * when going from primary only to sprite only and vice
+        * versa.
+        */
+       if (intel_crtc->config.ips_enabled) {
+               intel_wait_for_vblank(dev, intel_crtc->pipe);
+               hsw_enable_ips(intel_crtc);
+       }
+
+       mutex_lock(&dev->struct_mutex);
+       intel_update_fbc(dev);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 static void
@@ -523,13 +553,26 @@ intel_disable_primary(struct drm_crtc *crtc)
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int reg = DSPCNTR(intel_crtc->plane);
 
-       if (intel_crtc->primary_disabled)
+       if (!intel_crtc->primary_enabled)
                return;
 
-       I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
+       intel_crtc->primary_enabled = false;
 
-       intel_crtc->primary_disabled = true;
-       intel_update_fbc(dev);
+       mutex_lock(&dev->struct_mutex);
+       if (dev_priv->fbc.plane == intel_crtc->plane)
+               intel_disable_fbc(dev);
+       mutex_unlock(&dev->struct_mutex);
+
+       /*
+        * FIXME IPS should be fine as long as one plane is
+        * enabled, but in practice it seems to have problems
+        * when going from primary only to sprite only and vice
+        * versa.
+        */
+       hsw_disable_ips(intel_crtc);
+
+       I915_WRITE(reg, I915_READ(reg) & ~DISPLAY_PLANE_ENABLE);
+       intel_flush_primary_plane(dev_priv, intel_crtc->plane);
 }
 
 static int
@@ -608,15 +651,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                   uint32_t src_w, uint32_t src_h)
 {
        struct drm_device *dev = plane->dev;
-       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct intel_plane *intel_plane = to_intel_plane(plane);
-       struct intel_framebuffer *intel_fb;
-       struct drm_i915_gem_object *obj, *old_obj;
-       int pipe = intel_plane->pipe;
-       enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,
-                                                                     pipe);
-       int ret = 0;
+       struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+       struct drm_i915_gem_object *obj = intel_fb->obj;
+       struct drm_i915_gem_object *old_obj = intel_plane->obj;
+       int ret;
        bool disable_primary = false;
        bool visible;
        int hscale, vscale;
@@ -637,29 +677,23 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                .y2 = crtc_y + crtc_h,
        };
        const struct drm_rect clip = {
-               .x2 = crtc->mode.hdisplay,
-               .y2 = crtc->mode.vdisplay,
+               .x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0,
+               .y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0,
+       };
+       const struct {
+               int crtc_x, crtc_y;
+               unsigned int crtc_w, crtc_h;
+               uint32_t src_x, src_y, src_w, src_h;
+       } orig = {
+               .crtc_x = crtc_x,
+               .crtc_y = crtc_y,
+               .crtc_w = crtc_w,
+               .crtc_h = crtc_h,
+               .src_x = src_x,
+               .src_y = src_y,
+               .src_w = src_w,
+               .src_h = src_h,
        };
-
-       intel_fb = to_intel_framebuffer(fb);
-       obj = intel_fb->obj;
-
-       old_obj = intel_plane->obj;
-
-       intel_plane->crtc_x = crtc_x;
-       intel_plane->crtc_y = crtc_y;
-       intel_plane->crtc_w = crtc_w;
-       intel_plane->crtc_h = crtc_h;
-       intel_plane->src_x = src_x;
-       intel_plane->src_y = src_y;
-       intel_plane->src_w = src_w;
-       intel_plane->src_h = src_h;
-
-       /* Pipe must be running... */
-       if (!(I915_READ(PIPECONF(cpu_transcoder)) & PIPECONF_ENABLE)) {
-               DRM_DEBUG_KMS("Pipe disabled\n");
-               return -EINVAL;
-       }
 
        /* Don't modify another pipe's plane */
        if (intel_plane->pipe != intel_crtc->pipe) {
@@ -795,7 +829,7 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
         * we can disable the primary and save power.
         */
        disable_primary = drm_rect_equals(&dst, &clip);
-       WARN_ON(disable_primary && !visible);
+       WARN_ON(disable_primary && !visible && intel_crtc->active);
 
        mutex_lock(&dev->struct_mutex);
 
@@ -805,27 +839,40 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
         * the sprite planes only require 128KiB alignment and 32 PTE padding.
         */
        ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
-       if (ret)
-               goto out_unlock;
-
-       intel_plane->obj = obj;
 
-       /*
-        * Be sure to re-enable the primary before the sprite is no longer
-        * covering it fully.
-        */
-       if (!disable_primary)
-               intel_enable_primary(crtc);
+       mutex_unlock(&dev->struct_mutex);
 
-       if (visible)
-               intel_plane->update_plane(plane, fb, obj,
-                                         crtc_x, crtc_y, crtc_w, crtc_h,
-                                         src_x, src_y, src_w, src_h);
-       else
-               intel_plane->disable_plane(plane);
+       if (ret)
+               return ret;
+
+       intel_plane->crtc_x = orig.crtc_x;
+       intel_plane->crtc_y = orig.crtc_y;
+       intel_plane->crtc_w = orig.crtc_w;
+       intel_plane->crtc_h = orig.crtc_h;
+       intel_plane->src_x = orig.src_x;
+       intel_plane->src_y = orig.src_y;
+       intel_plane->src_w = orig.src_w;
+       intel_plane->src_h = orig.src_h;
+       intel_plane->obj = obj;
 
-       if (disable_primary)
-               intel_disable_primary(crtc);
+       if (intel_crtc->active) {
+               /*
+                * Be sure to re-enable the primary before the sprite is no longer
+                * covering it fully.
+                */
+               if (!disable_primary)
+                       intel_enable_primary(crtc);
+
+               if (visible)
+                       intel_plane->update_plane(plane, crtc, fb, obj,
+                                                 crtc_x, crtc_y, crtc_w, crtc_h,
+                                                 src_x, src_y, src_w, src_h);
+               else
+                       intel_plane->disable_plane(plane, crtc);
+
+               if (disable_primary)
+                       intel_disable_primary(crtc);
+       }
 
        /* Unpin old obj after new one is active to avoid ugliness */
        if (old_obj) {
@@ -835,17 +882,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                 * wait for vblank to avoid ugliness, we only need to
                 * do the pin & ref bookkeeping.
                 */
-               if (old_obj != obj) {
-                       mutex_unlock(&dev->struct_mutex);
-                       intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
-                       mutex_lock(&dev->struct_mutex);
-               }
+               if (old_obj != obj && intel_crtc->active)
+                       intel_wait_for_vblank(dev, intel_crtc->pipe);
+
+               mutex_lock(&dev->struct_mutex);
                intel_unpin_fb_obj(old_obj);
+               mutex_unlock(&dev->struct_mutex);
        }
 
-out_unlock:
-       mutex_unlock(&dev->struct_mutex);
-       return ret;
+       return 0;
 }
 
 static int
@@ -853,24 +898,33 @@ intel_disable_plane(struct drm_plane *plane)
 {
        struct drm_device *dev = plane->dev;
        struct intel_plane *intel_plane = to_intel_plane(plane);
-       int ret = 0;
+       struct intel_crtc *intel_crtc;
 
-       if (plane->crtc)
+       if (!plane->fb)
+               return 0;
+
+       if (WARN_ON(!plane->crtc))
+               return -EINVAL;
+
+       intel_crtc = to_intel_crtc(plane->crtc);
+
+       if (intel_crtc->active) {
                intel_enable_primary(plane->crtc);
-       intel_plane->disable_plane(plane);
+               intel_plane->disable_plane(plane, plane->crtc);
+       }
 
-       if (!intel_plane->obj)
-               goto out;
+       if (intel_plane->obj) {
+               if (intel_crtc->active)
+                       intel_wait_for_vblank(dev, intel_plane->pipe);
 
-       intel_wait_for_vblank(dev, intel_plane->pipe);
+               mutex_lock(&dev->struct_mutex);
+               intel_unpin_fb_obj(intel_plane->obj);
+               mutex_unlock(&dev->struct_mutex);
 
-       mutex_lock(&dev->struct_mutex);
-       intel_unpin_fb_obj(intel_plane->obj);
-       intel_plane->obj = NULL;
-       mutex_unlock(&dev->struct_mutex);
-out:
+               intel_plane->obj = NULL;
+       }
 
-       return ret;
+       return 0;
 }
 
 static void intel_destroy_plane(struct drm_plane *plane)
@@ -1014,7 +1068,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
        if (INTEL_INFO(dev)->gen < 5)
                return -ENODEV;
 
-       intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
+       intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
        if (!intel_plane)
                return -ENOMEM;
 
This page took 0.045044 seconds and 5 git commands to generate.