Merge tag 'drm-intel-next-2018-07-09' of git://anongit.freedesktop.org/drm/drm-intel...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / intel_sprite.c
index e2328d0402d88da94286c491653ab0889c4ce686..4990d6e84ddfaf99a02fc4fd1adfb11eecba48ec 100644 (file)
@@ -978,22 +978,12 @@ intel_check_sprite_plane(struct intel_plane *plane,
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
        struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
        struct drm_framebuffer *fb = state->base.fb;
-       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->base.src;
-       struct drm_rect *dst = &state->base.dst;
-       struct drm_rect clip = {};
        int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384;
-       int hscale, vscale;
        int max_scale, min_scale;
        bool can_scale;
        int ret;
        uint32_t pixel_format = 0;
 
-       *src = drm_plane_state_src(&state->base);
-       *dst = drm_plane_state_dest(&state->base);
-
        if (!fb) {
                state->base.visible = false;
                return 0;
@@ -1032,64 +1022,19 @@ intel_check_sprite_plane(struct intel_plane *plane,
                min_scale = plane->can_scale ? 1 : (1 << 16);
        }
 
-       /*
-        * FIXME the following code does a bunch of fuzzy adjustments to the
-        * coordinates and sizes. We probably need some way to decide whether
-        * more strict checking should be done instead.
-        */
-       drm_rect_rotate(src, fb->width << 16, fb->height << 16,
-                       state->base.rotation);
-
-       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);
-       BUG_ON(vscale < 0);
-
-       if (crtc_state->base.enable)
-               drm_mode_get_hv_timing(&crtc_state->base.mode,
-                                      &clip.x2, &clip.y2);
-
-       state->base.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);
+       ret = drm_atomic_helper_check_plane_state(&state->base,
+                                                 &crtc_state->base,
+                                                 min_scale, max_scale,
+                                                 true, true);
+       if (ret)
+               return ret;
 
        if (state->base.visible) {
-               /* check again in case clipping clamped the results */
-               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: ", src, true);
-                       drm_rect_debug_print("dst: ", dst, false);
-
-                       return hscale;
-               }
-
-               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: ", src, true);
-                       drm_rect_debug_print("dst: ", 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_rotate_inv(src, fb->width << 16, fb->height << 16,
-                                   state->base.rotation);
-
-               /* sanity check to make sure the src viewport wasn't enlarged */
-               WARN_ON(src->x1 < (int) state->base.src_x ||
-                       src->y1 < (int) state->base.src_y ||
-                       src->x2 > (int) state->base.src_x + state->base.src_w ||
-                       src->y2 > (int) state->base.src_y + state->base.src_h);
+               struct drm_rect *src = &state->base.src;
+               struct drm_rect *dst = &state->base.dst;
+               unsigned int crtc_w = drm_rect_width(dst);
+               unsigned int crtc_h = drm_rect_height(dst);
+               uint32_t src_x, src_y, src_w, src_h;
 
                /*
                 * Hardware doesn't handle subpixel coordinates.
@@ -1102,59 +1047,40 @@ intel_check_sprite_plane(struct intel_plane *plane,
                src_y = src->y1 >> 16;
                src_h = drm_rect_height(src) >> 16;
 
+               src->x1 = src_x << 16;
+               src->x2 = (src_x + src_w) << 16;
+               src->y1 = src_y << 16;
+               src->y2 = (src_y + src_h) << 16;
+
                if (intel_format_is_yuv(fb->format->format) &&
-                   fb->format->format != DRM_FORMAT_NV12) {
-                       src_x &= ~1;
-                       src_w &= ~1;
-
-                       /*
-                        * Must keep src and dst the
-                        * same if we can't scale.
-                        */
-                       if (!can_scale)
-                               crtc_w &= ~1;
-
-                       if (crtc_w == 0)
-                               state->base.visible = false;
+                   fb->format->format != DRM_FORMAT_NV12 &&
+                   (src_x % 2 || src_w % 2)) {
+                       DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n",
+                                     src_x, src_w);
+                       return -EINVAL;
                }
-       }
-
-       /* Check size restrictions when scaling */
-       if (state->base.visible && (src_w != crtc_w || src_h != crtc_h)) {
-               unsigned int width_bytes;
-               int cpp = fb->format->cpp[0];
 
-               WARN_ON(!can_scale);
+               /* Check size restrictions when scaling */
+               if (src_w != crtc_w || src_h != crtc_h) {
+                       unsigned int width_bytes;
+                       int cpp = fb->format->cpp[0];
 
-               /* FIXME interlacing min height is 6 */
+                       WARN_ON(!can_scale);
 
-               if (crtc_w < 3 || crtc_h < 3)
-                       state->base.visible = false;
+                       width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
 
-               if (src_w < 3 || src_h < 3)
-                       state->base.visible = false;
-
-               width_bytes = ((src_x * cpp) & 63) + src_w * cpp;
-
-               if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 ||
-                   width_bytes > 4096 || fb->pitches[0] > 4096)) {
-                       DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
-                       return -EINVAL;
+                       /* FIXME interlacing min height is 6 */
+                       if (INTEL_GEN(dev_priv) < 9 && (
+                            src_w < 3 || src_h < 3 ||
+                            src_w > 2048 || src_h > 2048 ||
+                            crtc_w < 3 || crtc_h < 3 ||
+                            width_bytes > 4096 || fb->pitches[0] > 4096)) {
+                               DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n");
+                               return -EINVAL;
+                       }
                }
        }
 
-       if (state->base.visible) {
-               src->x1 = src_x << 16;
-               src->x2 = (src_x + src_w) << 16;
-               src->y1 = src_y << 16;
-               src->y2 = (src_y + src_h) << 16;
-       }
-
-       dst->x1 = crtc_x;
-       dst->x2 = crtc_x + crtc_w;
-       dst->y1 = crtc_y;
-       dst->y2 = crtc_y + crtc_h;
-
        if (INTEL_GEN(dev_priv) >= 9) {
                ret = skl_check_plane_surface(crtc_state, state);
                if (ret)
@@ -1385,8 +1311,17 @@ static const uint64_t skl_plane_format_modifiers_ccs[] = {
        DRM_FORMAT_MOD_INVALID
 };
 
-static bool g4x_mod_supported(uint32_t format, uint64_t modifier)
+static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_YUYV:
@@ -1402,8 +1337,17 @@ static bool g4x_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool snb_mod_supported(uint32_t format, uint64_t modifier)
+static bool snb_sprite_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_XBGR8888:
@@ -1420,8 +1364,17 @@ static bool snb_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool vlv_mod_supported(uint32_t format, uint64_t modifier)
+static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane,
+                                           u32 format, u64 modifier)
 {
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_RGB565:
        case DRM_FORMAT_ABGR8888:
@@ -1443,8 +1396,26 @@ static bool vlv_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool skl_mod_supported(uint32_t format, uint64_t modifier)
+static bool skl_plane_format_mod_supported(struct drm_plane *_plane,
+                                          u32 format, u64 modifier)
 {
+       struct intel_plane *plane = to_intel_plane(_plane);
+
+       switch (modifier) {
+       case DRM_FORMAT_MOD_LINEAR:
+       case I915_FORMAT_MOD_X_TILED:
+       case I915_FORMAT_MOD_Y_TILED:
+       case I915_FORMAT_MOD_Yf_TILED:
+               break;
+       case I915_FORMAT_MOD_Y_TILED_CCS:
+       case I915_FORMAT_MOD_Yf_TILED_CCS:
+               if (!plane->has_ccs)
+                       return false;
+               break;
+       default:
+               return false;
+       }
+
        switch (format) {
        case DRM_FORMAT_XRGB8888:
        case DRM_FORMAT_XBGR8888:
@@ -1476,30 +1447,40 @@ static bool skl_mod_supported(uint32_t format, uint64_t modifier)
        }
 }
 
-static bool intel_sprite_plane_format_mod_supported(struct drm_plane *plane,
-                                                   uint32_t format,
-                                                   uint64_t modifier)
-{
-       struct drm_i915_private *dev_priv = to_i915(plane->dev);
-
-       if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
-               return false;
+static const struct drm_plane_funcs g4x_sprite_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = g4x_sprite_format_mod_supported,
+};
 
-       if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_INTEL &&
-           modifier != DRM_FORMAT_MOD_LINEAR)
-               return false;
+static const struct drm_plane_funcs snb_sprite_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = snb_sprite_format_mod_supported,
+};
 
-       if (INTEL_GEN(dev_priv) >= 9)
-               return skl_mod_supported(format, modifier);
-       else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-               return vlv_mod_supported(format, modifier);
-       else if (INTEL_GEN(dev_priv) >= 6)
-               return snb_mod_supported(format, modifier);
-       else
-               return g4x_mod_supported(format, modifier);
-}
+static const struct drm_plane_funcs vlv_sprite_funcs = {
+       .update_plane = drm_atomic_helper_update_plane,
+       .disable_plane = drm_atomic_helper_disable_plane,
+       .destroy = intel_plane_destroy,
+       .atomic_get_property = intel_plane_atomic_get_property,
+       .atomic_set_property = intel_plane_atomic_set_property,
+       .atomic_duplicate_state = intel_plane_duplicate_state,
+       .atomic_destroy_state = intel_plane_destroy_state,
+       .format_mod_supported = vlv_sprite_format_mod_supported,
+};
 
-static const struct drm_plane_funcs intel_sprite_plane_funcs = {
+static const struct drm_plane_funcs skl_plane_funcs = {
        .update_plane = drm_atomic_helper_update_plane,
        .disable_plane = drm_atomic_helper_disable_plane,
        .destroy = intel_plane_destroy,
@@ -1507,7 +1488,7 @@ static const struct drm_plane_funcs intel_sprite_plane_funcs = {
        .atomic_set_property = intel_plane_atomic_set_property,
        .atomic_duplicate_state = intel_plane_duplicate_state,
        .atomic_destroy_state = intel_plane_destroy_state,
-       .format_mod_supported = intel_sprite_plane_format_mod_supported,
+       .format_mod_supported = skl_plane_format_mod_supported,
 };
 
 bool skl_plane_has_ccs(struct drm_i915_private *dev_priv,
@@ -1533,6 +1514,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 {
        struct intel_plane *intel_plane = NULL;
        struct intel_plane_state *state = NULL;
+       const struct drm_plane_funcs *plane_funcs;
        unsigned long possible_crtcs;
        const uint32_t *plane_formats;
        const uint64_t *modifiers;
@@ -1557,6 +1539,9 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                intel_plane->can_scale = true;
                state->scaler_id = -1;
 
+               intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
+                                                        PLANE_SPRITE0 + plane);
+
                intel_plane->update_plane = skl_update_plane;
                intel_plane->disable_plane = skl_disable_plane;
                intel_plane->get_hw_state = skl_plane_get_hw_state;
@@ -1570,10 +1555,12 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                        num_plane_formats = ARRAY_SIZE(skl_plane_formats);
                }
 
-               if (skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane))
+               if (intel_plane->has_ccs)
                        modifiers = skl_plane_format_modifiers_ccs;
                else
                        modifiers = skl_plane_format_modifiers_noccs;
+
+               plane_funcs = &skl_plane_funcs;
        } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                intel_plane->can_scale = false;
                intel_plane->max_downscale = 1;
@@ -1585,6 +1572,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                plane_formats = vlv_plane_formats;
                num_plane_formats = ARRAY_SIZE(vlv_plane_formats);
                modifiers = i9xx_plane_format_modifiers;
+
+               plane_funcs = &vlv_sprite_funcs;
        } else if (INTEL_GEN(dev_priv) >= 7) {
                if (IS_IVYBRIDGE(dev_priv)) {
                        intel_plane->can_scale = true;
@@ -1601,6 +1590,8 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                plane_formats = snb_plane_formats;
                num_plane_formats = ARRAY_SIZE(snb_plane_formats);
                modifiers = i9xx_plane_format_modifiers;
+
+               plane_funcs = &snb_sprite_funcs;
        } else {
                intel_plane->can_scale = true;
                intel_plane->max_downscale = 16;
@@ -1613,9 +1604,13 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
                if (IS_GEN6(dev_priv)) {
                        plane_formats = snb_plane_formats;
                        num_plane_formats = ARRAY_SIZE(snb_plane_formats);
+
+                       plane_funcs = &snb_sprite_funcs;
                } else {
                        plane_formats = g4x_plane_formats;
                        num_plane_formats = ARRAY_SIZE(g4x_plane_formats);
+
+                       plane_funcs = &g4x_sprite_funcs;
                }
        }
 
@@ -1642,14 +1637,14 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv,
 
        if (INTEL_GEN(dev_priv) >= 9)
                ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
-                                              possible_crtcs, &intel_sprite_plane_funcs,
+                                              possible_crtcs, plane_funcs,
                                               plane_formats, num_plane_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_OVERLAY,
                                               "plane %d%c", plane + 2, pipe_name(pipe));
        else
                ret = drm_universal_plane_init(&dev_priv->drm, &intel_plane->base,
-                                              possible_crtcs, &intel_sprite_plane_funcs,
+                                              possible_crtcs, plane_funcs,
                                               plane_formats, num_plane_formats,
                                               modifiers,
                                               DRM_PLANE_TYPE_OVERLAY,