Merge tag 'drm-intel-next-2018-09-21' of git://anongit.freedesktop.org/drm/drm-intel...
[muen/linux.git] / drivers / gpu / drm / i915 / intel_display.c
index 5711cb7017601b4319d3b710b07fea2adefa8919..fbcc56caffb6596a75ddc8975a8c813caef2c909 100644 (file)
@@ -1917,10 +1917,10 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv)
 }
 
 static unsigned int
-intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane)
+intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane)
 {
        struct drm_i915_private *dev_priv = to_i915(fb->dev);
-       unsigned int cpp = fb->format->cpp[plane];
+       unsigned int cpp = fb->format->cpp[color_plane];
 
        switch (fb->modifier) {
        case DRM_FORMAT_MOD_LINEAR:
@@ -1931,7 +1931,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane)
                else
                        return 512;
        case I915_FORMAT_MOD_Y_TILED_CCS:
-               if (plane == 1)
+               if (color_plane == 1)
                        return 128;
                /* fall through */
        case I915_FORMAT_MOD_Y_TILED:
@@ -1940,7 +1940,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane)
                else
                        return 512;
        case I915_FORMAT_MOD_Yf_TILED_CCS:
-               if (plane == 1)
+               if (color_plane == 1)
                        return 128;
                /* fall through */
        case I915_FORMAT_MOD_Yf_TILED:
@@ -1965,22 +1965,22 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane)
 }
 
 static unsigned int
-intel_tile_height(const struct drm_framebuffer *fb, int plane)
+intel_tile_height(const struct drm_framebuffer *fb, int color_plane)
 {
        if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
                return 1;
        else
                return intel_tile_size(to_i915(fb->dev)) /
-                       intel_tile_width_bytes(fb, plane);
+                       intel_tile_width_bytes(fb, color_plane);
 }
 
 /* Return the tile dimensions in pixel units */
-static void intel_tile_dims(const struct drm_framebuffer *fb, int plane,
+static void intel_tile_dims(const struct drm_framebuffer *fb, int color_plane,
                            unsigned int *tile_width,
                            unsigned int *tile_height)
 {
-       unsigned int tile_width_bytes = intel_tile_width_bytes(fb, plane);
-       unsigned int cpp = fb->format->cpp[plane];
+       unsigned int tile_width_bytes = intel_tile_width_bytes(fb, color_plane);
+       unsigned int cpp = fb->format->cpp[color_plane];
 
        *tile_width = tile_width_bytes / cpp;
        *tile_height = intel_tile_size(to_i915(fb->dev)) / tile_width_bytes;
@@ -1988,9 +1988,9 @@ static void intel_tile_dims(const struct drm_framebuffer *fb, int plane,
 
 unsigned int
 intel_fb_align_height(const struct drm_framebuffer *fb,
-                     int plane, unsigned int height)
+                     int color_plane, unsigned int height)
 {
-       unsigned int tile_height = intel_tile_height(fb, plane);
+       unsigned int tile_height = intel_tile_height(fb, color_plane);
 
        return ALIGN(height, tile_height);
 }
@@ -2044,12 +2044,12 @@ static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_pr
 }
 
 static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb,
-                                        int plane)
+                                        int color_plane)
 {
        struct drm_i915_private *dev_priv = to_i915(fb->dev);
 
        /* AUX_DIST needs only 4K alignment */
-       if (plane == 1)
+       if (color_plane == 1)
                return 4096;
 
        switch (fb->modifier) {
@@ -2080,14 +2080,13 @@ static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state)
 
 struct i915_vma *
 intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
-                          unsigned int rotation,
+                          const struct i915_ggtt_view *view,
                           bool uses_fence,
                           unsigned long *out_flags)
 {
        struct drm_device *dev = fb->dev;
        struct drm_i915_private *dev_priv = to_i915(dev);
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
-       struct i915_ggtt_view view;
        struct i915_vma *vma;
        unsigned int pinctl;
        u32 alignment;
@@ -2096,8 +2095,6 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
 
        alignment = intel_surf_alignment(fb, 0);
 
-       intel_fill_fb_ggtt_view(&view, fb, rotation);
-
        /* Note that the w/a also requires 64 PTE of padding following the
         * bo. We currently fill all unused PTE with the shadow page and so
         * we should always have valid PTE following the scanout preventing
@@ -2130,7 +2127,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
                pinctl |= PIN_MAPPABLE;
 
        vma = i915_gem_object_pin_to_display_plane(obj,
-                                                  alignment, &view, pinctl);
+                                                  alignment, view, pinctl);
        if (IS_ERR(vma))
                goto err;
 
@@ -2182,13 +2179,13 @@ void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags)
        i915_vma_put(vma);
 }
 
-static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
+static int intel_fb_pitch(const struct drm_framebuffer *fb, int color_plane,
                          unsigned int rotation)
 {
        if (drm_rotation_90_or_270(rotation))
-               return to_intel_framebuffer(fb)->rotated[plane].pitch;
+               return to_intel_framebuffer(fb)->rotated[color_plane].pitch;
        else
-               return fb->pitches[plane];
+               return fb->pitches[color_plane];
 }
 
 /*
@@ -2199,11 +2196,11 @@ static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane,
  */
 u32 intel_fb_xy_to_linear(int x, int y,
                          const struct intel_plane_state *state,
-                         int plane)
+                         int color_plane)
 {
        const struct drm_framebuffer *fb = state->base.fb;
-       unsigned int cpp = fb->format->cpp[plane];
-       unsigned int pitch = fb->pitches[plane];
+       unsigned int cpp = fb->format->cpp[color_plane];
+       unsigned int pitch = state->color_plane[color_plane].stride;
 
        return y * pitch + x * cpp;
 }
@@ -2215,28 +2212,28 @@ u32 intel_fb_xy_to_linear(int x, int y,
  */
 void intel_add_fb_offsets(int *x, int *y,
                          const struct intel_plane_state *state,
-                         int plane)
+                         int color_plane)
 
 {
        const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb);
        unsigned int rotation = state->base.rotation;
 
        if (drm_rotation_90_or_270(rotation)) {
-               *x += intel_fb->rotated[plane].x;
-               *y += intel_fb->rotated[plane].y;
+               *x += intel_fb->rotated[color_plane].x;
+               *y += intel_fb->rotated[color_plane].y;
        } else {
-               *x += intel_fb->normal[plane].x;
-               *y += intel_fb->normal[plane].y;
+               *x += intel_fb->normal[color_plane].x;
+               *y += intel_fb->normal[color_plane].y;
        }
 }
 
-static u32 __intel_adjust_tile_offset(int *x, int *y,
-                                     unsigned int tile_width,
-                                     unsigned int tile_height,
-                                     unsigned int tile_size,
-                                     unsigned int pitch_tiles,
-                                     u32 old_offset,
-                                     u32 new_offset)
+static u32 intel_adjust_tile_offset(int *x, int *y,
+                                   unsigned int tile_width,
+                                   unsigned int tile_height,
+                                   unsigned int tile_size,
+                                   unsigned int pitch_tiles,
+                                   u32 old_offset,
+                                   u32 new_offset)
 {
        unsigned int pitch_pixels = pitch_tiles * tile_width;
        unsigned int tiles;
@@ -2257,14 +2254,15 @@ static u32 __intel_adjust_tile_offset(int *x, int *y,
        return new_offset;
 }
 
-static u32 _intel_adjust_tile_offset(int *x, int *y,
-                                    const struct drm_framebuffer *fb, int plane,
-                                    unsigned int rotation,
-                                    u32 old_offset, u32 new_offset)
+static u32 intel_adjust_aligned_offset(int *x, int *y,
+                                      const struct drm_framebuffer *fb,
+                                      int color_plane,
+                                      unsigned int rotation,
+                                      unsigned int pitch,
+                                      u32 old_offset, u32 new_offset)
 {
-       const struct drm_i915_private *dev_priv = to_i915(fb->dev);
-       unsigned int cpp = fb->format->cpp[plane];
-       unsigned int pitch = intel_fb_pitch(fb, plane, rotation);
+       struct drm_i915_private *dev_priv = to_i915(fb->dev);
+       unsigned int cpp = fb->format->cpp[color_plane];
 
        WARN_ON(new_offset > old_offset);
 
@@ -2273,7 +2271,7 @@ static u32 _intel_adjust_tile_offset(int *x, int *y,
                unsigned int pitch_tiles;
 
                tile_size = intel_tile_size(dev_priv);
-               intel_tile_dims(fb, plane, &tile_width, &tile_height);
+               intel_tile_dims(fb, color_plane, &tile_width, &tile_height);
 
                if (drm_rotation_90_or_270(rotation)) {
                        pitch_tiles = pitch / tile_height;
@@ -2282,9 +2280,9 @@ static u32 _intel_adjust_tile_offset(int *x, int *y,
                        pitch_tiles = pitch / (tile_width * cpp);
                }
 
-               __intel_adjust_tile_offset(x, y, tile_width, tile_height,
-                                          tile_size, pitch_tiles,
-                                          old_offset, new_offset);
+               intel_adjust_tile_offset(x, y, tile_width, tile_height,
+                                        tile_size, pitch_tiles,
+                                        old_offset, new_offset);
        } else {
                old_offset += *y * pitch + *x * cpp;
 
@@ -2299,17 +2297,19 @@ static u32 _intel_adjust_tile_offset(int *x, int *y,
  * Adjust the tile offset by moving the difference into
  * the x/y offsets.
  */
-static u32 intel_adjust_tile_offset(int *x, int *y,
-                                   const struct intel_plane_state *state, int plane,
-                                   u32 old_offset, u32 new_offset)
-{
-       return _intel_adjust_tile_offset(x, y, state->base.fb, plane,
-                                        state->base.rotation,
-                                        old_offset, new_offset);
+static u32 intel_plane_adjust_aligned_offset(int *x, int *y,
+                                            const struct intel_plane_state *state,
+                                            int color_plane,
+                                            u32 old_offset, u32 new_offset)
+{
+       return intel_adjust_aligned_offset(x, y, state->base.fb, color_plane,
+                                          state->base.rotation,
+                                          state->color_plane[color_plane].stride,
+                                          old_offset, new_offset);
 }
 
 /*
- * Computes the linear offset to the base tile and adjusts
+ * Computes the aligned offset to the base tile and adjusts
  * x, y. bytes per pixel is assumed to be a power-of-two.
  *
  * In the 90/270 rotated case, x and y are assumed
@@ -2322,15 +2322,16 @@ static u32 intel_adjust_tile_offset(int *x, int *y,
  * used. This is why the user has to pass in the pitch since it
  * is specified in the rotated orientation.
  */
-static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
-                                     int *x, int *y,
-                                     const struct drm_framebuffer *fb, int plane,
-                                     unsigned int pitch,
-                                     unsigned int rotation,
-                                     u32 alignment)
+static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv,
+                                       int *x, int *y,
+                                       const struct drm_framebuffer *fb,
+                                       int color_plane,
+                                       unsigned int pitch,
+                                       unsigned int rotation,
+                                       u32 alignment)
 {
        uint64_t fb_modifier = fb->modifier;
-       unsigned int cpp = fb->format->cpp[plane];
+       unsigned int cpp = fb->format->cpp[color_plane];
        u32 offset, offset_aligned;
 
        if (alignment)
@@ -2341,7 +2342,7 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
                unsigned int tile_rows, tiles, pitch_tiles;
 
                tile_size = intel_tile_size(dev_priv);
-               intel_tile_dims(fb, plane, &tile_width, &tile_height);
+               intel_tile_dims(fb, color_plane, &tile_width, &tile_height);
 
                if (drm_rotation_90_or_270(rotation)) {
                        pitch_tiles = pitch / tile_height;
@@ -2359,9 +2360,9 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
                offset = (tile_rows * pitch_tiles + tiles) * tile_size;
                offset_aligned = offset & ~alignment;
 
-               __intel_adjust_tile_offset(x, y, tile_width, tile_height,
-                                          tile_size, pitch_tiles,
-                                          offset, offset_aligned);
+               intel_adjust_tile_offset(x, y, tile_width, tile_height,
+                                        tile_size, pitch_tiles,
+                                        offset, offset_aligned);
        } else {
                offset = *y * pitch + *x * cpp;
                offset_aligned = offset & ~alignment;
@@ -2373,42 +2374,44 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv,
        return offset_aligned;
 }
 
-u32 intel_compute_tile_offset(int *x, int *y,
-                             const struct intel_plane_state *state,
-                             int plane)
+static u32 intel_plane_compute_aligned_offset(int *x, int *y,
+                                             const struct intel_plane_state *state,
+                                             int color_plane)
 {
        struct intel_plane *intel_plane = to_intel_plane(state->base.plane);
        struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev);
        const struct drm_framebuffer *fb = state->base.fb;
        unsigned int rotation = state->base.rotation;
-       int pitch = intel_fb_pitch(fb, plane, rotation);
+       int pitch = state->color_plane[color_plane].stride;
        u32 alignment;
 
        if (intel_plane->id == PLANE_CURSOR)
                alignment = intel_cursor_alignment(dev_priv);
        else
-               alignment = intel_surf_alignment(fb, plane);
+               alignment = intel_surf_alignment(fb, color_plane);
 
-       return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch,
-                                         rotation, alignment);
+       return intel_compute_aligned_offset(dev_priv, x, y, fb, color_plane,
+                                           pitch, rotation, alignment);
 }
 
 /* Convert the fb->offset[] into x/y offsets */
 static int intel_fb_offset_to_xy(int *x, int *y,
-                                const struct drm_framebuffer *fb, int plane)
+                                const struct drm_framebuffer *fb,
+                                int color_plane)
 {
        struct drm_i915_private *dev_priv = to_i915(fb->dev);
 
        if (fb->modifier != DRM_FORMAT_MOD_LINEAR &&
-           fb->offsets[plane] % intel_tile_size(dev_priv))
+           fb->offsets[color_plane] % intel_tile_size(dev_priv))
                return -EINVAL;
 
        *x = 0;
        *y = 0;
 
-       _intel_adjust_tile_offset(x, y,
-                                 fb, plane, DRM_MODE_ROTATE_0,
-                                 fb->offsets[plane], 0);
+       intel_adjust_aligned_offset(x, y,
+                                   fb, color_plane, DRM_MODE_ROTATE_0,
+                                   fb->pitches[color_plane],
+                                   fb->offsets[color_plane], 0);
 
        return 0;
 }
@@ -2565,9 +2568,10 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
                intel_fb->normal[i].x = x;
                intel_fb->normal[i].y = y;
 
-               offset = _intel_compute_tile_offset(dev_priv, &x, &y,
-                                                   fb, i, fb->pitches[i],
-                                                   DRM_MODE_ROTATE_0, tile_size);
+               offset = intel_compute_aligned_offset(dev_priv, &x, &y, fb, i,
+                                                     fb->pitches[i],
+                                                     DRM_MODE_ROTATE_0,
+                                                     tile_size);
                offset /= tile_size;
 
                if (fb->modifier != DRM_FORMAT_MOD_LINEAR) {
@@ -2614,10 +2618,10 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
                         * We only keep the x/y offsets, so push all of the
                         * gtt offset into the x/y offsets.
                         */
-                       __intel_adjust_tile_offset(&x, &y,
-                                                  tile_width, tile_height,
-                                                  tile_size, pitch_tiles,
-                                                  gtt_offset_rotated * tile_size, 0);
+                       intel_adjust_tile_offset(&x, &y,
+                                                tile_width, tile_height,
+                                                tile_size, pitch_tiles,
+                                                gtt_offset_rotated * tile_size, 0);
 
                        gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height;
 
@@ -2636,9 +2640,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
                max_size = max(max_size, offset + size);
        }
 
-       if (max_size * tile_size > obj->base.size) {
-               DRM_DEBUG_KMS("fb too big for bo (need %u bytes, have %zu bytes)\n",
-                             max_size * tile_size, obj->base.size);
+       if (mul_u32_u32(max_size, tile_size) > obj->base.size) {
+               DRM_DEBUG_KMS("fb too big for bo (need %llu bytes, have %zu bytes)\n",
+                             mul_u32_u32(max_size, tile_size), obj->base.size);
                return -EINVAL;
        }
 
@@ -2853,10 +2857,15 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        return;
 
 valid_fb:
+       intel_fill_fb_ggtt_view(&intel_state->view, fb,
+                               intel_state->base.rotation);
+       intel_state->color_plane[0].stride =
+               intel_fb_pitch(fb, 0, intel_state->base.rotation);
+
        mutex_lock(&dev->struct_mutex);
        intel_state->vma =
                intel_pin_and_fence_fb_obj(fb,
-                                          primary->state->rotation,
+                                          &intel_state->view,
                                           intel_plane_uses_fence(intel_state),
                                           &intel_state->flags);
        mutex_unlock(&dev->struct_mutex);
@@ -2899,10 +2908,11 @@ valid_fb:
                  &obj->frontbuffer_bits);
 }
 
-static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
+static int skl_max_plane_width(const struct drm_framebuffer *fb,
+                              int color_plane,
                               unsigned int rotation)
 {
-       int cpp = fb->format->cpp[plane];
+       int cpp = fb->format->cpp[color_plane];
 
        switch (fb->modifier) {
        case DRM_FORMAT_MOD_LINEAR:
@@ -2950,9 +2960,9 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state
        const struct drm_framebuffer *fb = plane_state->base.fb;
        int hsub = fb->format->hsub;
        int vsub = fb->format->vsub;
-       int aux_x = plane_state->aux.x;
-       int aux_y = plane_state->aux.y;
-       u32 aux_offset = plane_state->aux.offset;
+       int aux_x = plane_state->color_plane[1].x;
+       int aux_y = plane_state->color_plane[1].y;
+       u32 aux_offset = plane_state->color_plane[1].offset;
        u32 alignment = intel_surf_alignment(fb, 1);
 
        while (aux_offset >= main_offset && aux_y <= main_y) {
@@ -2966,8 +2976,8 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state
 
                x = aux_x / hsub;
                y = aux_y / vsub;
-               aux_offset = intel_adjust_tile_offset(&x, &y, plane_state, 1,
-                                                     aux_offset, aux_offset - alignment);
+               aux_offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1,
+                                                              aux_offset, aux_offset - alignment);
                aux_x = x * hsub + aux_x % hsub;
                aux_y = y * vsub + aux_y % vsub;
        }
@@ -2975,30 +2985,24 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state
        if (aux_x != main_x || aux_y != main_y)
                return false;
 
-       plane_state->aux.offset = aux_offset;
-       plane_state->aux.x = aux_x;
-       plane_state->aux.y = aux_y;
+       plane_state->color_plane[1].offset = aux_offset;
+       plane_state->color_plane[1].x = aux_x;
+       plane_state->color_plane[1].y = aux_y;
 
        return true;
 }
 
-static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,
-                                 struct intel_plane_state *plane_state)
+static int skl_check_main_surface(struct intel_plane_state *plane_state)
 {
-       struct drm_i915_private *dev_priv =
-               to_i915(plane_state->base.plane->dev);
        const struct drm_framebuffer *fb = plane_state->base.fb;
        unsigned int rotation = plane_state->base.rotation;
        int x = plane_state->base.src.x1 >> 16;
        int y = plane_state->base.src.y1 >> 16;
        int w = drm_rect_width(&plane_state->base.src) >> 16;
        int h = drm_rect_height(&plane_state->base.src) >> 16;
-       int dst_x = plane_state->base.dst.x1;
-       int dst_w = drm_rect_width(&plane_state->base.dst);
-       int pipe_src_w = crtc_state->pipe_src_w;
        int max_width = skl_max_plane_width(fb, 0, rotation);
        int max_height = 4096;
-       u32 alignment, offset, aux_offset = plane_state->aux.offset;
+       u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset;
 
        if (w > max_width || h > max_height) {
                DRM_DEBUG_KMS("requested Y/RGB source size %dx%d too big (limit %dx%d)\n",
@@ -3006,26 +3010,8 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,
                return -EINVAL;
        }
 
-       /*
-        * Display WA #1175: cnl,glk
-        * Planes other than the cursor may cause FIFO underflow and display
-        * corruption if starting less than 4 pixels from the right edge of
-        * the screen.
-        * Besides the above WA fix the similar problem, where planes other
-        * than the cursor ending less than 4 pixels from the left edge of the
-        * screen may cause FIFO underflow and display corruption.
-        */
-       if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) &&
-           (dst_x + dst_w < 4 || dst_x > pipe_src_w - 4)) {
-               DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n",
-                             dst_x + dst_w < 4 ? "end" : "start",
-                             dst_x + dst_w < 4 ? dst_x + dst_w : dst_x,
-                             4, pipe_src_w - 4);
-               return -ERANGE;
-       }
-
        intel_add_fb_offsets(&x, &y, plane_state, 0);
-       offset = intel_compute_tile_offset(&x, &y, plane_state, 0);
+       offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 0);
        alignment = intel_surf_alignment(fb, 0);
 
        /*
@@ -3034,8 +3020,8 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,
         * sure that is what we will get.
         */
        if (offset > aux_offset)
-               offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
-                                                 offset, aux_offset & ~(alignment - 1));
+               offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
+                                                          offset, aux_offset & ~(alignment - 1));
 
        /*
         * When using an X-tiled surface, the plane blows up
@@ -3046,14 +3032,14 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,
        if (fb->modifier == I915_FORMAT_MOD_X_TILED) {
                int cpp = fb->format->cpp[0];
 
-               while ((x + w) * cpp > fb->pitches[0]) {
+               while ((x + w) * cpp > plane_state->color_plane[0].stride) {
                        if (offset == 0) {
                                DRM_DEBUG_KMS("Unable to find suitable display surface offset due to X-tiling\n");
                                return -EINVAL;
                        }
 
-                       offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
-                                                         offset, offset - alignment);
+                       offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
+                                                                  offset, offset - alignment);
                }
        }
 
@@ -3066,26 +3052,25 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state,
                        if (offset == 0)
                                break;
 
-                       offset = intel_adjust_tile_offset(&x, &y, plane_state, 0,
-                                                         offset, offset - alignment);
+                       offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0,
+                                                                  offset, offset - alignment);
                }
 
-               if (x != plane_state->aux.x || y != plane_state->aux.y) {
+               if (x != plane_state->color_plane[1].x || y != plane_state->color_plane[1].y) {
                        DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n");
                        return -EINVAL;
                }
        }
 
-       plane_state->main.offset = offset;
-       plane_state->main.x = x;
-       plane_state->main.y = y;
+       plane_state->color_plane[0].offset = offset;
+       plane_state->color_plane[0].x = x;
+       plane_state->color_plane[0].y = y;
 
        return 0;
 }
 
 static int
-skl_check_nv12_surface(const struct intel_crtc_state *crtc_state,
-                      struct intel_plane_state *plane_state)
+skl_check_nv12_surface(struct intel_plane_state *plane_state)
 {
        /* Display WA #1106 */
        if (plane_state->base.rotation !=
@@ -3119,7 +3104,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
        u32 offset;
 
        intel_add_fb_offsets(&x, &y, plane_state, 1);
-       offset = intel_compute_tile_offset(&x, &y, plane_state, 1);
+       offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1);
 
        /* FIXME not quite sure how/if these apply to the chroma plane */
        if (w > max_width || h > max_height) {
@@ -3128,9 +3113,9 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state)
                return -EINVAL;
        }
 
-       plane_state->aux.offset = offset;
-       plane_state->aux.x = x;
-       plane_state->aux.y = y;
+       plane_state->color_plane[1].offset = offset;
+       plane_state->color_plane[1].x = x;
+       plane_state->color_plane[1].y = y;
 
        return 0;
 }
@@ -3146,34 +3131,25 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state)
        int y = src_y / vsub;
        u32 offset;
 
-       if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) {
-               DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n",
-                             plane_state->base.rotation);
-               return -EINVAL;
-       }
-
        intel_add_fb_offsets(&x, &y, plane_state, 1);
-       offset = intel_compute_tile_offset(&x, &y, plane_state, 1);
+       offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1);
 
-       plane_state->aux.offset = offset;
-       plane_state->aux.x = x * hsub + src_x % hsub;
-       plane_state->aux.y = y * vsub + src_y % vsub;
+       plane_state->color_plane[1].offset = offset;
+       plane_state->color_plane[1].x = x * hsub + src_x % hsub;
+       plane_state->color_plane[1].y = y * vsub + src_y % vsub;
 
        return 0;
 }
 
-int skl_check_plane_surface(const struct intel_crtc_state *crtc_state,
-                           struct intel_plane_state *plane_state)
+int skl_check_plane_surface(struct intel_plane_state *plane_state)
 {
        const struct drm_framebuffer *fb = plane_state->base.fb;
        unsigned int rotation = plane_state->base.rotation;
        int ret;
 
-       if (rotation & DRM_MODE_REFLECT_X &&
-           fb->modifier == DRM_FORMAT_MOD_LINEAR) {
-               DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n");
-               return -EINVAL;
-       }
+       intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
+       plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
+       plane_state->color_plane[1].stride = intel_fb_pitch(fb, 1, rotation);
 
        if (!plane_state->base.visible)
                return 0;
@@ -3189,7 +3165,7 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state,
         * the main surface setup depends on it.
         */
        if (fb->format->format == DRM_FORMAT_NV12) {
-               ret = skl_check_nv12_surface(crtc_state, plane_state);
+               ret = skl_check_nv12_surface(plane_state);
                if (ret)
                        return ret;
                ret = skl_check_nv12_aux_surface(plane_state);
@@ -3200,18 +3176,45 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state,
                if (ret)
                        return ret;
        } else {
-               plane_state->aux.offset = ~0xfff;
-               plane_state->aux.x = 0;
-               plane_state->aux.y = 0;
+               plane_state->color_plane[1].offset = ~0xfff;
+               plane_state->color_plane[1].x = 0;
+               plane_state->color_plane[1].y = 0;
        }
 
-       ret = skl_check_main_surface(crtc_state, plane_state);
+       ret = skl_check_main_surface(plane_state);
        if (ret)
                return ret;
 
        return 0;
 }
 
+unsigned int
+i9xx_plane_max_stride(struct intel_plane *plane,
+                     u32 pixel_format, u64 modifier,
+                     unsigned int rotation)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+
+       if (!HAS_GMCH_DISPLAY(dev_priv)) {
+               return 32*1024;
+       } else if (INTEL_GEN(dev_priv) >= 4) {
+               if (modifier == I915_FORMAT_MOD_X_TILED)
+                       return 16*1024;
+               else
+                       return 32*1024;
+       } else if (INTEL_GEN(dev_priv) >= 3) {
+               if (modifier == I915_FORMAT_MOD_X_TILED)
+                       return 8*1024;
+               else
+                       return 16*1024;
+       } else {
+               if (plane->i9xx_plane == PLANE_C)
+                       return 4*1024;
+               else
+                       return 8*1024;
+       }
+}
+
 static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state,
                          const struct intel_plane_state *plane_state)
 {
@@ -3278,21 +3281,25 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv =
                to_i915(plane_state->base.plane->dev);
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       unsigned int rotation = plane_state->base.rotation;
        int src_x = plane_state->base.src.x1 >> 16;
        int src_y = plane_state->base.src.y1 >> 16;
        u32 offset;
 
+       intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
+       plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
+
        intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
 
        if (INTEL_GEN(dev_priv) >= 4)
-               offset = intel_compute_tile_offset(&src_x, &src_y,
-                                                  plane_state, 0);
+               offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
+                                                           plane_state, 0);
        else
                offset = 0;
 
        /* HSW/BDW do this automagically in hardware */
        if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) {
-               unsigned int rotation = plane_state->base.rotation;
                int src_w = drm_rect_width(&plane_state->base.src) >> 16;
                int src_h = drm_rect_height(&plane_state->base.src) >> 16;
 
@@ -3304,9 +3311,43 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state)
                }
        }
 
-       plane_state->main.offset = offset;
-       plane_state->main.x = src_x;
-       plane_state->main.y = src_y;
+       plane_state->color_plane[0].offset = offset;
+       plane_state->color_plane[0].x = src_x;
+       plane_state->color_plane[0].y = src_y;
+
+       return 0;
+}
+
+static int
+i9xx_plane_check(struct intel_crtc_state *crtc_state,
+                struct intel_plane_state *plane_state)
+{
+       int ret;
+
+       ret = chv_plane_check_rotation(plane_state);
+       if (ret)
+               return ret;
+
+       ret = drm_atomic_helper_check_plane_state(&plane_state->base,
+                                                 &crtc_state->base,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 DRM_PLANE_HELPER_NO_SCALING,
+                                                 false, true);
+       if (ret)
+               return ret;
+
+       if (!plane_state->base.visible)
+               return 0;
+
+       ret = intel_plane_check_src_coordinates(plane_state);
+       if (ret)
+               return ret;
+
+       ret = i9xx_check_plane_surface(plane_state);
+       if (ret)
+               return ret;
+
+       plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state);
 
        return 0;
 }
@@ -3316,20 +3357,19 @@ static void i9xx_update_plane(struct intel_plane *plane,
                              const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
        enum i9xx_plane_id i9xx_plane = plane->i9xx_plane;
        u32 linear_offset;
        u32 dspcntr = plane_state->ctl;
        i915_reg_t reg = DSPCNTR(i9xx_plane);
-       int x = plane_state->main.x;
-       int y = plane_state->main.y;
+       int x = plane_state->color_plane[0].x;
+       int y = plane_state->color_plane[0].y;
        unsigned long irqflags;
        u32 dspaddr_offset;
 
        linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0);
 
        if (INTEL_GEN(dev_priv) >= 4)
-               dspaddr_offset = plane_state->main.offset;
+               dspaddr_offset = plane_state->color_plane[0].offset;
        else
                dspaddr_offset = linear_offset;
 
@@ -3353,7 +3393,7 @@ static void i9xx_update_plane(struct intel_plane *plane,
 
        I915_WRITE_FW(reg, dspcntr);
 
-       I915_WRITE_FW(DSPSTRIDE(i9xx_plane), fb->pitches[0]);
+       I915_WRITE_FW(DSPSTRIDE(i9xx_plane), plane_state->color_plane[0].stride);
        if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
                I915_WRITE_FW(DSPSURF(i9xx_plane),
                              intel_plane_ggtt_offset(plane_state) +
@@ -3428,12 +3468,12 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane,
 }
 
 static u32
-intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane)
+intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane)
 {
        if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
                return 64;
        else
-               return intel_tile_width_bytes(fb, plane);
+               return intel_tile_width_bytes(fb, color_plane);
 }
 
 static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
@@ -3463,24 +3503,24 @@ static void skl_detach_scalers(struct intel_crtc *intel_crtc)
        }
 }
 
-u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane,
-                    unsigned int rotation)
+u32 skl_plane_stride(const struct intel_plane_state *plane_state,
+                    int color_plane)
 {
-       u32 stride;
+       const struct drm_framebuffer *fb = plane_state->base.fb;
+       unsigned int rotation = plane_state->base.rotation;
+       u32 stride = plane_state->color_plane[color_plane].stride;
 
-       if (plane >= fb->format->num_planes)
+       if (color_plane >= fb->format->num_planes)
                return 0;
 
-       stride = intel_fb_pitch(fb, plane, rotation);
-
        /*
         * The stride is either expressed as a multiple of 64 bytes chunks for
         * linear buffers or in number of tiles for tiled buffers.
         */
        if (drm_rotation_90_or_270(rotation))
-               stride /= intel_tile_height(fb, plane);
+               stride /= intel_tile_height(fb, color_plane);
        else
-               stride /= intel_fb_stride_alignment(fb, plane);
+               stride /= intel_fb_stride_alignment(fb, color_plane);
 
        return stride;
 }
@@ -6014,6 +6054,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config,
 
        i9xx_set_pipeconf(intel_crtc);
 
+       intel_color_set_csc(&pipe_config->base);
+
        intel_crtc->active = true;
 
        intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
@@ -6113,8 +6155,8 @@ static void i9xx_pfit_disable(struct intel_crtc *crtc)
 
        assert_pipe_disabled(dev_priv, crtc->pipe);
 
-       DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n",
-                        I915_READ(PFIT_CONTROL));
+       DRM_DEBUG_KMS("disabling pfit, current: 0x%08x\n",
+                     I915_READ(PFIT_CONTROL));
        I915_WRITE(PFIT_CONTROL, 0);
 }
 
@@ -8634,8 +8676,8 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc,
        ironlake_compute_dpll(crtc, crtc_state, NULL);
 
        if (!intel_get_shared_dpll(crtc, crtc_state, NULL)) {
-               DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-                                pipe_name(crtc->pipe));
+               DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
+                             pipe_name(crtc->pipe));
                return -EINVAL;
        }
 
@@ -9202,8 +9244,8 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc,
                        intel_get_crtc_new_encoder(state, crtc_state);
 
                if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) {
-                       DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n",
-                                        pipe_name(crtc->pipe));
+                       DRM_DEBUG_KMS("failed to find PLL for pipe %c\n",
+                                     pipe_name(crtc->pipe));
                        return -EINVAL;
                }
        }
@@ -9592,7 +9634,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
        else
                base = intel_plane_ggtt_offset(plane_state);
 
-       base += plane_state->main.offset;
+       base += plane_state->color_plane[0].offset;
 
        /* ILK+ do this automagically */
        if (HAS_GMCH_DISPLAY(dev_priv) &&
@@ -9635,14 +9677,44 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state)
                height > 0 && height <= config->cursor_height;
 }
 
-static int intel_check_cursor(struct intel_crtc_state *crtc_state,
-                             struct intel_plane_state *plane_state)
+static int intel_cursor_check_surface(struct intel_plane_state *plane_state)
 {
        const struct drm_framebuffer *fb = plane_state->base.fb;
+       unsigned int rotation = plane_state->base.rotation;
        int src_x, src_y;
        u32 offset;
+
+       intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation);
+       plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation);
+
+       src_x = plane_state->base.src_x >> 16;
+       src_y = plane_state->base.src_y >> 16;
+
+       intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
+       offset = intel_plane_compute_aligned_offset(&src_x, &src_y,
+                                                   plane_state, 0);
+
+       if (src_x != 0 || src_y != 0) {
+               DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n");
+               return -EINVAL;
+       }
+
+       plane_state->color_plane[0].offset = offset;
+
+       return 0;
+}
+
+static int intel_check_cursor(struct intel_crtc_state *crtc_state,
+                             struct intel_plane_state *plane_state)
+{
+       const struct drm_framebuffer *fb = plane_state->base.fb;
        int ret;
 
+       if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) {
+               DRM_DEBUG_KMS("cursor cannot be tiled\n");
+               return -EINVAL;
+       }
+
        ret = drm_atomic_helper_check_plane_state(&plane_state->base,
                                                  &crtc_state->base,
                                                  DRM_PLANE_HELPER_NO_SCALING,
@@ -9651,39 +9723,35 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state,
        if (ret)
                return ret;
 
-       if (!fb)
+       if (!plane_state->base.visible)
                return 0;
 
-       if (fb->modifier != DRM_FORMAT_MOD_LINEAR) {
-               DRM_DEBUG_KMS("cursor cannot be tiled\n");
-               return -EINVAL;
-       }
-
-       src_x = plane_state->base.src_x >> 16;
-       src_y = plane_state->base.src_y >> 16;
-
-       intel_add_fb_offsets(&src_x, &src_y, plane_state, 0);
-       offset = intel_compute_tile_offset(&src_x, &src_y, plane_state, 0);
-
-       if (src_x != 0 || src_y != 0) {
-               DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n");
-               return -EINVAL;
-       }
+       ret = intel_plane_check_src_coordinates(plane_state);
+       if (ret)
+               return ret;
 
-       plane_state->main.offset = offset;
+       ret = intel_cursor_check_surface(plane_state);
+       if (ret)
+               return ret;
 
        return 0;
 }
 
+static unsigned int
+i845_cursor_max_stride(struct intel_plane *plane,
+                      u32 pixel_format, u64 modifier,
+                      unsigned int rotation)
+{
+       return 2048;
+}
+
 static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state,
                           const struct intel_plane_state *plane_state)
 {
-       const struct drm_framebuffer *fb = plane_state->base.fb;
-
        return CURSOR_ENABLE |
                CURSOR_GAMMA_ENABLE |
                CURSOR_FORMAT_ARGB |
-               CURSOR_STRIDE(fb->pitches[0]);
+               CURSOR_STRIDE(plane_state->color_plane[0].stride);
 }
 
 static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state)
@@ -9719,6 +9787,9 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state,
                return -EINVAL;
        }
 
+       WARN_ON(plane_state->base.visible &&
+               plane_state->color_plane[0].stride != fb->pitches[0]);
+
        switch (fb->pitches[0]) {
        case 256:
        case 512:
@@ -9807,6 +9878,14 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane,
        return ret;
 }
 
+static unsigned int
+i9xx_cursor_max_stride(struct intel_plane *plane,
+                      u32 pixel_format, u64 modifier,
+                      unsigned int rotation)
+{
+       return plane->base.dev->mode_config.cursor_width * 4;
+}
+
 static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state,
                           const struct intel_plane_state *plane_state)
 {
@@ -9912,6 +9991,9 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state,
                return -EINVAL;
        }
 
+       WARN_ON(plane_state->base.visible &&
+               plane_state->color_plane[0].stride != fb->pitches[0]);
+
        if (fb->pitches[0] != plane_state->base.crtc_w * fb->format->cpp[0]) {
                DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n",
                              fb->pitches[0], plane_state->base.crtc_w);
@@ -12982,7 +13064,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state)
        }
 
        vma = intel_pin_and_fence_fb_obj(fb,
-                                        plane_state->base.rotation,
+                                        &plane_state->view,
                                         intel_plane_uses_fence(plane_state),
                                         &plane_state->flags);
        if (IS_ERR(vma))
@@ -13160,19 +13242,17 @@ intel_cleanup_plane_fb(struct drm_plane *plane,
 }
 
 int
-skl_max_scale(struct intel_crtc *intel_crtc,
-             struct intel_crtc_state *crtc_state,
-             uint32_t pixel_format)
+skl_max_scale(const struct intel_crtc_state *crtc_state,
+             u32 pixel_format)
 {
-       struct drm_i915_private *dev_priv;
+       struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
+       struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
        int max_scale, mult;
        int crtc_clock, max_dotclk, tmpclk1, tmpclk2;
 
-       if (!intel_crtc || !crtc_state->base.enable)
+       if (!crtc_state->base.enable)
                return DRM_PLANE_HELPER_NO_SCALING;
 
-       dev_priv = to_i915(intel_crtc->base.dev);
-
        crtc_clock = crtc_state->base.adjusted_mode.crtc_clock;
        max_dotclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk;
 
@@ -13196,61 +13276,6 @@ skl_max_scale(struct intel_crtc *intel_crtc,
        return max_scale;
 }
 
-static int
-intel_check_primary_plane(struct intel_crtc_state *crtc_state,
-                         struct intel_plane_state *state)
-{
-       struct intel_plane *plane = to_intel_plane(state->base.plane);
-       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       struct drm_crtc *crtc = state->base.crtc;
-       int min_scale = DRM_PLANE_HELPER_NO_SCALING;
-       int max_scale = DRM_PLANE_HELPER_NO_SCALING;
-       bool can_position = false;
-       int ret;
-       uint32_t pixel_format = 0;
-
-       if (INTEL_GEN(dev_priv) >= 9) {
-               /* use scaler when colorkey is not required */
-               if (!state->ckey.flags) {
-                       min_scale = 1;
-                       if (state->base.fb)
-                               pixel_format = state->base.fb->format->format;
-                       max_scale = skl_max_scale(to_intel_crtc(crtc),
-                                                 crtc_state, pixel_format);
-               }
-               can_position = true;
-       }
-
-       ret = drm_atomic_helper_check_plane_state(&state->base,
-                                                 &crtc_state->base,
-                                                 min_scale, max_scale,
-                                                 can_position, true);
-       if (ret)
-               return ret;
-
-       if (!state->base.fb)
-               return 0;
-
-       if (INTEL_GEN(dev_priv) >= 9) {
-               ret = skl_check_plane_surface(crtc_state, state);
-               if (ret)
-                       return ret;
-
-               state->ctl = skl_plane_ctl(crtc_state, state);
-       } else {
-               ret = i9xx_check_plane_surface(state);
-               if (ret)
-                       return ret;
-
-               state->ctl = i9xx_plane_ctl(crtc_state, state);
-       }
-
-       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
-               state->color_ctl = glk_plane_color_ctl(crtc_state, state);
-
-       return 0;
-}
-
 static void intel_begin_crtc_commit(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_crtc_state)
 {
@@ -13672,12 +13697,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
 
        primary->base.state = &state->base;
 
-       primary->can_scale = false;
-       primary->max_downscale = 1;
-       if (INTEL_GEN(dev_priv) >= 9) {
-               primary->can_scale = true;
+       if (INTEL_GEN(dev_priv) >= 9)
                state->scaler_id = -1;
-       }
        primary->pipe = pipe;
        /*
         * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS
@@ -13704,8 +13725,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                fbc->possible_framebuffer_bits |= primary->frontbuffer_bit;
        }
 
-       primary->check_plane = intel_check_primary_plane;
-
        if (INTEL_GEN(dev_priv) >= 9) {
                primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe,
                                                     PLANE_PRIMARY);
@@ -13723,9 +13742,11 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                else
                        modifiers = skl_format_modifiers_noccs;
 
+               primary->max_stride = skl_plane_max_stride;
                primary->update_plane = skl_update_plane;
                primary->disable_plane = skl_disable_plane;
                primary->get_hw_state = skl_plane_get_hw_state;
+               primary->check_plane = skl_plane_check;
 
                plane_funcs = &skl_plane_funcs;
        } else if (INTEL_GEN(dev_priv) >= 4) {
@@ -13733,9 +13754,11 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                num_formats = ARRAY_SIZE(i965_primary_formats);
                modifiers = i9xx_format_modifiers;
 
+               primary->max_stride = i9xx_plane_max_stride;
                primary->update_plane = i9xx_update_plane;
                primary->disable_plane = i9xx_disable_plane;
                primary->get_hw_state = i9xx_plane_get_hw_state;
+               primary->check_plane = i9xx_plane_check;
 
                plane_funcs = &i965_plane_funcs;
        } else {
@@ -13743,9 +13766,11 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe)
                num_formats = ARRAY_SIZE(i8xx_primary_formats);
                modifiers = i9xx_format_modifiers;
 
+               primary->max_stride = i9xx_plane_max_stride;
                primary->update_plane = i9xx_update_plane;
                primary->disable_plane = i9xx_disable_plane;
                primary->get_hw_state = i9xx_plane_get_hw_state;
+               primary->check_plane = i9xx_plane_check;
 
                plane_funcs = &i8xx_plane_funcs;
        }
@@ -13842,19 +13867,19 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv,
 
        cursor->base.state = &state->base;
 
-       cursor->can_scale = false;
-       cursor->max_downscale = 1;
        cursor->pipe = pipe;
        cursor->i9xx_plane = (enum i9xx_plane_id) pipe;
        cursor->id = PLANE_CURSOR;
        cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id);
 
        if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) {
+               cursor->max_stride = i845_cursor_max_stride;
                cursor->update_plane = i845_update_cursor;
                cursor->disable_plane = i845_disable_cursor;
                cursor->get_hw_state = i845_cursor_get_hw_state;
                cursor->check_plane = i845_check_cursor;
        } else {
+               cursor->max_stride = i9xx_cursor_max_stride;
                cursor->update_plane = i9xx_update_cursor;
                cursor->disable_plane = i9xx_disable_cursor;
                cursor->get_hw_state = i9xx_cursor_get_hw_state;
@@ -14380,31 +14405,18 @@ static
 u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv,
                         uint64_t fb_modifier, uint32_t pixel_format)
 {
-       u32 gen = INTEL_GEN(dev_priv);
+       struct intel_crtc *crtc;
+       struct intel_plane *plane;
 
-       if (gen >= 9) {
-               int cpp = drm_format_plane_cpp(pixel_format, 0);
+       /*
+        * We assume the primary plane for pipe A has
+        * the highest stride limits of them all.
+        */
+       crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A);
+       plane = to_intel_plane(crtc->base.primary);
 
-               /* "The stride in bytes must not exceed the of the size of 8K
-                *  pixels and 32K bytes."
-                */
-               return min(8192 * cpp, 32768);
-       } else if (gen >= 5 && !HAS_GMCH_DISPLAY(dev_priv)) {
-               return 32*1024;
-       } else if (gen >= 4) {
-               if (fb_modifier == I915_FORMAT_MOD_X_TILED)
-                       return 16*1024;
-               else
-                       return 32*1024;
-       } else if (gen >= 3) {
-               if (fb_modifier == I915_FORMAT_MOD_X_TILED)
-                       return 8*1024;
-               else
-                       return 16*1024;
-       } else {
-               /* XXX DSPC is limited to 4k tiled */
-               return 8*1024;
-       }
+       return plane->max_stride(plane, pixel_format, fb_modifier,
+                                DRM_MODE_ROTATE_0);
 }
 
 static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,