Merge branch 'topic/skl-stage1' into drm-intel-next-queued
[deliverable/linux.git] / drivers / gpu / drm / i915 / intel_sprite.c
index 57e7190c4c87b9906599b2406c53f08635776b1a..750b634d45eced1387e7a9a8b950bb7f5fe881ed 100644 (file)
@@ -1023,57 +1023,24 @@ static bool colorkey_enabled(struct intel_plane *intel_plane)
 }
 
 static int
-intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
-                  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
-                  unsigned int crtc_w, unsigned int crtc_h,
-                  uint32_t src_x, uint32_t src_y,
-                  uint32_t src_w, uint32_t src_h)
+intel_check_sprite_plane(struct drm_plane *plane,
+                        struct intel_plane_state *state)
 {
-       struct drm_device *dev = plane->dev;
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_crtc *intel_crtc = to_intel_crtc(state->crtc);
        struct intel_plane *intel_plane = to_intel_plane(plane);
-       enum pipe pipe = intel_crtc->pipe;
+       struct drm_framebuffer *fb = state->fb;
        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 primary_enabled;
-       bool visible;
+       int crtc_x, crtc_y;
+       unsigned int crtc_w, crtc_h;
+       uint32_t src_x, src_y, src_w, src_h;
+       struct drm_rect *src = &state->src;
+       struct drm_rect *dst = &state->dst;
+       struct drm_rect *orig_src = &state->orig_src;
+       const struct drm_rect *clip = &state->clip;
        int hscale, vscale;
        int max_scale, min_scale;
        int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
-       struct drm_rect src = {
-               /* sample coordinates in 16.16 fixed point */
-               .x1 = src_x,
-               .x2 = src_x + src_w,
-               .y1 = src_y,
-               .y2 = src_y + src_h,
-       };
-       struct drm_rect dst = {
-               /* integer pixels */
-               .x1 = crtc_x,
-               .x2 = crtc_x + crtc_w,
-               .y1 = crtc_y,
-               .y2 = crtc_y + crtc_h,
-       };
-       const struct drm_rect clip = {
-               .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,
-       };
 
        /* Don't modify another pipe's plane */
        if (intel_plane->pipe != intel_crtc->pipe) {
@@ -1105,55 +1072,55 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        max_scale = intel_plane->max_downscale << 16;
        min_scale = intel_plane->can_scale ? 1 : (1 << 16);
 
-       drm_rect_rotate(&src, fb->width << 16, fb->height << 16,
+       drm_rect_rotate(src, fb->width << 16, fb->height << 16,
                        intel_plane->rotation);
 
-       hscale = drm_rect_calc_hscale_relaxed(&src, &dst, min_scale, max_scale);
+       hscale = drm_rect_calc_hscale_relaxed(src, dst, min_scale, max_scale);
        BUG_ON(hscale < 0);
 
-       vscale = drm_rect_calc_vscale_relaxed(&src, &dst, min_scale, max_scale);
+       vscale = drm_rect_calc_vscale_relaxed(src, dst, min_scale, max_scale);
        BUG_ON(vscale < 0);
 
-       visible = drm_rect_clip_scaled(&src, &dst, &clip, hscale, vscale);
+       state->visible =  drm_rect_clip_scaled(src, dst, clip, hscale, vscale);
 
-       crtc_x = dst.x1;
-       crtc_y = dst.y1;
-       crtc_w = drm_rect_width(&dst);
-       crtc_h = drm_rect_height(&dst);
+       crtc_x = dst->x1;
+       crtc_y = dst->y1;
+       crtc_w = drm_rect_width(dst);
+       crtc_h = drm_rect_height(dst);
 
-       if (visible) {
+       if (state->visible) {
                /* check again in case clipping clamped the results */
-               hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
+               hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
                if (hscale < 0) {
                        DRM_DEBUG_KMS("Horizontal scaling factor out of limits\n");
-                       drm_rect_debug_print(&src, true);
-                       drm_rect_debug_print(&dst, false);
+                       drm_rect_debug_print(src, true);
+                       drm_rect_debug_print(dst, false);
 
                        return hscale;
                }
 
-               vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
+               vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
                if (vscale < 0) {
                        DRM_DEBUG_KMS("Vertical scaling factor out of limits\n");
-                       drm_rect_debug_print(&src, true);
-                       drm_rect_debug_print(&dst, false);
+                       drm_rect_debug_print(src, true);
+                       drm_rect_debug_print(dst, false);
 
                        return vscale;
                }
 
                /* Make the source viewport size an exact multiple of the scaling factors. */
-               drm_rect_adjust_size(&src,
-                                    drm_rect_width(&dst) * hscale - drm_rect_width(&src),
-                                    drm_rect_height(&dst) * vscale - drm_rect_height(&src));
+               drm_rect_adjust_size(src,
+                                    drm_rect_width(dst) * hscale - drm_rect_width(src),
+                                    drm_rect_height(dst) * vscale - drm_rect_height(src));
 
-               drm_rect_rotate_inv(&src, fb->width << 16, fb->height << 16,
+               drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16,
                                    intel_plane->rotation);
 
                /* sanity check to make sure the src viewport wasn't enlarged */
-               WARN_ON(src.x1 < (int) src_x ||
-                       src.y1 < (int) src_y ||
-                       src.x2 > (int) (src_x + src_w) ||
-                       src.y2 > (int) (src_y + src_h));
+               WARN_ON(src->x1 < (int) orig_src->x1 ||
+                       src->y1 < (int) orig_src->y1 ||
+                       src->x2 > (int) orig_src->x2 ||
+                       src->y2 > (int) orig_src->y2);
 
                /*
                 * Hardware doesn't handle subpixel coordinates.
@@ -1161,10 +1128,10 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                 * increase the source viewport size, because that could
                 * push the downscaling factor out of bounds.
                 */
-               src_x = src.x1 >> 16;
-               src_w = drm_rect_width(&src) >> 16;
-               src_y = src.y1 >> 16;
-               src_h = drm_rect_height(&src) >> 16;
+               src_x = src->x1 >> 16;
+               src_w = drm_rect_width(src) >> 16;
+               src_y = src->y1 >> 16;
+               src_h = drm_rect_height(src) >> 16;
 
                if (format_is_yuv(fb->pixel_format)) {
                        src_x &= ~1;
@@ -1178,12 +1145,12 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                                crtc_w &= ~1;
 
                        if (crtc_w == 0)
-                               visible = false;
+                               state->visible = false;
                }
        }
 
        /* Check size restrictions when scaling */
-       if (visible && (src_w != crtc_w || src_h != crtc_h)) {
+       if (state->visible && (src_w != crtc_w || src_h != crtc_h)) {
                unsigned int width_bytes;
 
                WARN_ON(!intel_plane->can_scale);
@@ -1191,12 +1158,13 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                /* FIXME interlacing min height is 6 */
 
                if (crtc_w < 3 || crtc_h < 3)
-                       visible = false;
+                       state->visible = false;
 
                if (src_w < 3 || src_h < 3)
-                       visible = false;
+                       state->visible = false;
 
-               width_bytes = ((src_x * pixel_size) & 63) + src_w * pixel_size;
+               width_bytes = ((src_x * pixel_size) & 63) +
+                                       src_w * pixel_size;
 
                if (src_w > 2048 || src_h > 2048 ||
                    width_bytes > 4096 || fb->pitches[0] > 4096) {
@@ -1205,42 +1173,76 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                }
        }
 
-       dst.x1 = crtc_x;
-       dst.x2 = crtc_x + crtc_w;
-       dst.y1 = crtc_y;
-       dst.y2 = crtc_y + crtc_h;
+       if (state->visible) {
+               src->x1 = src_x;
+               src->x2 = src_x + src_w;
+               src->y1 = src_y;
+               src->y2 = src_y + src_h;
+       }
+
+       dst->x1 = crtc_x;
+       dst->x2 = crtc_x + crtc_w;
+       dst->y1 = crtc_y;
+       dst->y2 = crtc_y + crtc_h;
+
+       return 0;
+}
+
+static int
+intel_commit_sprite_plane(struct drm_plane *plane,
+                         struct intel_plane_state *state)
+{
+       struct drm_device *dev = plane->dev;
+       struct drm_crtc *crtc = state->crtc;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       struct intel_plane *intel_plane = to_intel_plane(plane);
+       enum pipe pipe = intel_crtc->pipe;
+       struct drm_framebuffer *fb = state->fb;
+       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 crtc_x, crtc_y;
+       unsigned int crtc_w, crtc_h;
+       uint32_t src_x, src_y, src_w, src_h;
+       struct drm_rect *dst = &state->dst;
+       const struct drm_rect *clip = &state->clip;
+       bool primary_enabled;
+       int ret;
 
        /*
         * If the sprite is completely covering the primary plane,
         * we can disable the primary and save power.
         */
-       primary_enabled = !drm_rect_equals(&dst, &clip) || colorkey_enabled(intel_plane);
-       WARN_ON(!primary_enabled && !visible && intel_crtc->active);
+       primary_enabled = !drm_rect_equals(dst, clip) || colorkey_enabled(intel_plane);
+       WARN_ON(!primary_enabled && !state->visible && intel_crtc->active);
 
-       mutex_lock(&dev->struct_mutex);
 
-       /* Note that this will apply the VT-d workaround for scanouts,
-        * which is more restrictive than required for sprites. (The
-        * primary plane requires 256KiB alignment with 64 PTE padding,
-        * the sprite planes only require 128KiB alignment and 32 PTE padding.
-        */
-       ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
-
-       i915_gem_track_fb(old_obj, obj,
-                         INTEL_FRONTBUFFER_SPRITE(pipe));
-       mutex_unlock(&dev->struct_mutex);
+       if (old_obj != obj) {
+               mutex_lock(&dev->struct_mutex);
 
-       if (ret)
-               return ret;
+               /* Note that this will apply the VT-d workaround for scanouts,
+                * which is more restrictive than required for sprites. (The
+                * primary plane requires 256KiB alignment with 64 PTE padding,
+                * the sprite planes only require 128KiB alignment and 32 PTE
+                * padding.
+                */
+               ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+               if (ret == 0)
+                       i915_gem_track_fb(old_obj, obj,
+                                         INTEL_FRONTBUFFER_SPRITE(pipe));
+               mutex_unlock(&dev->struct_mutex);
+               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->crtc_x = state->orig_dst.x1;
+       intel_plane->crtc_y = state->orig_dst.y1;
+       intel_plane->crtc_w = drm_rect_width(&state->orig_dst);
+       intel_plane->crtc_h = drm_rect_height(&state->orig_dst);
+       intel_plane->src_x = state->orig_src.x1;
+       intel_plane->src_y = state->orig_src.y1;
+       intel_plane->src_w = drm_rect_width(&state->orig_src);
+       intel_plane->src_h = drm_rect_height(&state->orig_src);
        intel_plane->obj = obj;
 
        if (intel_crtc->active) {
@@ -1254,12 +1256,22 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
                if (primary_was_enabled && !primary_enabled)
                        intel_pre_disable_primary(crtc);
 
-               if (visible)
+               if (state->visible) {
+                       crtc_x = state->dst.x1;
+                       crtc_y = state->dst.y1;
+                       crtc_w = drm_rect_width(&state->dst);
+                       crtc_h = drm_rect_height(&state->dst);
+                       src_x = state->src.x1;
+                       src_y = state->src.y1;
+                       src_w = drm_rect_width(&state->src);
+                       src_h = drm_rect_height(&state->src);
                        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
+               } else {
                        intel_plane->disable_plane(plane, crtc);
+               }
+
 
                intel_frontbuffer_flip(dev, INTEL_FRONTBUFFER_SPRITE(pipe));
 
@@ -1268,14 +1280,15 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        }
 
        /* Unpin old obj after new one is active to avoid ugliness */
-       if (old_obj) {
+       if (old_obj && old_obj != obj) {
+
                /*
                 * It's fairly common to simply update the position of
                 * an existing object.  In that case, we don't need to
                 * wait for vblank to avoid ugliness, we only need to
                 * do the pin & ref bookkeeping.
                 */
-               if (old_obj != obj && intel_crtc->active)
+               if (intel_crtc->active)
                        intel_wait_for_vblank(dev, intel_crtc->pipe);
 
                mutex_lock(&dev->struct_mutex);
@@ -1286,6 +1299,46 @@ intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
        return 0;
 }
 
+static int
+intel_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
+                  struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+                  unsigned int crtc_w, unsigned int crtc_h,
+                  uint32_t src_x, uint32_t src_y,
+                  uint32_t src_w, uint32_t src_h)
+{
+       struct intel_plane_state state;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+       int ret;
+
+       state.crtc = crtc;
+       state.fb = fb;
+
+       /* sample coordinates in 16.16 fixed point */
+       state.src.x1 = src_x;
+       state.src.x2 = src_x + src_w;
+       state.src.y1 = src_y;
+       state.src.y2 = src_y + src_h;
+
+       /* integer pixels */
+       state.dst.x1 = crtc_x;
+       state.dst.x2 = crtc_x + crtc_w;
+       state.dst.y1 = crtc_y;
+       state.dst.y2 = crtc_y + crtc_h;
+
+       state.clip.x1 = 0;
+       state.clip.y1 = 0;
+       state.clip.x2 = intel_crtc->active ? intel_crtc->config.pipe_src_w : 0;
+       state.clip.y2 = intel_crtc->active ? intel_crtc->config.pipe_src_h : 0;
+       state.orig_src = state.src;
+       state.orig_dst = state.dst;
+
+       ret = intel_check_sprite_plane(plane, &state);
+       if (ret)
+               return ret;
+
+       return intel_commit_sprite_plane(plane, &state);
+}
+
 static int
 intel_disable_plane(struct drm_plane *plane)
 {
This page took 0.038642 seconds and 5 git commands to generate.