On Wed, Oct 21, 2015 at 02:01:01PM +0200, Daniel Vetter wrote:
> On Thu, Oct 15, 2015 at 08:59:45PM +0300, [email protected] wrote:
> > From: Ville Syrjälä <[email protected]>
> > 
> > Redo the fb rotation handling in order to:
> > - eliminate the NV12 special casing
> > - handle fb->offsets[] properly
> > - make the rotation handling reasier for the plane code
> 
> I think this is too big and should be split a bit. There's also a pile of
> renames mixed int on top.

It grew from a bunch of sepearate changes, but they got gobbled
together due to changing the entire approach a few times. In the end I
was too scared to split it up anymore. But I guess I should really try.

> 
> > To achieve these goals we reduce intel_rotation_info to only contain
> > (for each plane) the rotated view width,height,stride in tile units,
> > and the page offset into the object where the plane starts. Each plane
> > is handled exactly the same way, no special casing for NV12 or other
> > formats.
> 
> That sounds like a good prep patch to split out.
> 
> > We then store the computed rotation_info under
> > intel_framebuffer so that we don't have to recompute it again.
> 
> And another one, plus then following up with the fallout.
> 
> This patch also fixes the intel_plane_obj_offset issue for earlier in the
> series. Looks good otherwise from reading through it.
> 
> > To handle fb->offsets[] we treat them as a linear offsets and convert
> > them to x/y offsets from the start of the relevant GTT mapping (either
> > normal or rotated). We store the x/y offsets under intel_framebuffer,
> > and for some extra convenience we also store the rotated pitch (ie.
> > tile aligned plane height). So for each plane we have the normal
> > x/y offsets, rotated x/y offsets, and the rotated pitch. The normal
> > pitch is available already in fb->pitches[].
> > 
> > While we're gathering up all that extra information, we can also easily
> > compute the storage requirements for the framebuffer, so that we can
> > check that the object is big enough to hold it.
> > 
> > When it comes time to deal with the plane source coordinates, we first
> > rotate the clipped src coordinates to match the relevant GTT view
> > orientation, then add to them the fb x/y offsets. Next we compute
> > the aligned surface page offset, and as a result we're left with some
> > residual x/y offsets. Finally, if required by the hardware, we convert
> > the remaining x/y offsets into a linear offset.
> > 
> > For gen2/3 we simply skip computing the final page offset, and just
> > convert the src+fb x/y offsets directly into a linear offset since
> > that's what the hardware wants.
> > 
> > After this all platforms, incluing SKL+, compute these things in exactly
> > the same way (excluding alignemnt differences).
> > 
> > v2: Use BIT(DRM_ROTATE_270) instead of ROTATE_270 when rotating
> >     plane src coordinates
> >     Drop some spurious changes that got left behind during development
> > 
> > Signed-off-by: Ville Syrjälä <[email protected]>
> 
> Two comments below inline.
> -Daniel
> 
> > ---
> >  drivers/gpu/drm/i915/i915_gem_gtt.c  |  66 ++----
> >  drivers/gpu/drm/i915/i915_gem_gtt.h  |  14 +-
> >  drivers/gpu/drm/i915/intel_display.c | 448 
> > ++++++++++++++++++++++++-----------
> >  drivers/gpu/drm/i915/intel_drv.h     |  32 ++-
> >  drivers/gpu/drm/i915/intel_sprite.c  | 102 ++++----
> >  5 files changed, 402 insertions(+), 260 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c 
> > b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > index bb95b86..98aee6c 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.c
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
> > @@ -3255,11 +3255,6 @@ rotate_pages(const dma_addr_t *in, unsigned int 
> > offset,
> >     unsigned int column, row;
> >     unsigned int src_idx;
> >  
> > -   if (!sg) {
> > -           st->nents = 0;
> > -           sg = st->sgl;
> > -   }
> > -
> >     for (column = 0; column < width; column++) {
> >             src_idx = stride * (height - 1) + column;
> >             for (row = 0; row < height; row++) {
> > @@ -3280,16 +3275,14 @@ rotate_pages(const dma_addr_t *in, unsigned int 
> > offset,
> >  }
> >  
> >  static struct sg_table *
> > -intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
> > +intel_rotate_fb_obj_pages(const struct intel_rotation_info *info,
> >                       struct drm_i915_gem_object *obj)
> >  {
> > -   unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
> > -   unsigned int size_pages_uv;
> > +   unsigned int size = intel_rotation_info_size(info);
> >     struct sg_page_iter sg_iter;
> >     unsigned long i;
> >     dma_addr_t *page_addr_list;
> >     struct sg_table *st;
> > -   unsigned int uv_start_page;
> >     struct scatterlist *sg;
> >     int ret = -ENOMEM;
> >  
> > @@ -3299,57 +3292,32 @@ intel_rotate_fb_obj_pages(struct 
> > intel_rotation_info *rot_info,
> >     if (!page_addr_list)
> >             return ERR_PTR(ret);
> >  
> > -   /* Account for UV plane with NV12. */
> > -   if (rot_info->pixel_format == DRM_FORMAT_NV12)
> > -           size_pages_uv = rot_info->size_uv >> PAGE_SHIFT;
> > -   else
> > -           size_pages_uv = 0;
> > -
> >     /* Allocate target SG list. */
> >     st = kmalloc(sizeof(*st), GFP_KERNEL);
> >     if (!st)
> >             goto err_st_alloc;
> >  
> > -   ret = sg_alloc_table(st, size_pages + size_pages_uv, GFP_KERNEL);
> > +   ret = sg_alloc_table(st, size, GFP_KERNEL);
> >     if (ret)
> >             goto err_sg_alloc;
> >  
> >     /* Populate source page list from the object. */
> >     i = 0;
> >     for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) {
> > -           page_addr_list[i] = sg_page_iter_dma_address(&sg_iter);
> > -           i++;
> > +           page_addr_list[i++] = sg_page_iter_dma_address(&sg_iter);
> >     }
> >  
> > -   /* Rotate the pages. */
> > -   sg = rotate_pages(page_addr_list, 0,
> > -                rot_info->width_pages, rot_info->height_pages,
> > -                rot_info->width_pages,
> > -                st, NULL);
> > +   st->nents = 0;
> > +   sg = st->sgl;
> >  
> > -   /* Append the UV plane if NV12. */
> > -   if (rot_info->pixel_format == DRM_FORMAT_NV12) {
> > -           uv_start_page = size_pages;
> > -
> > -           /* Check for tile-row un-alignment. */
> > -           if (offset_in_page(rot_info->uv_offset))
> > -                   uv_start_page--;
> > -
> > -           rot_info->uv_start_page = uv_start_page;
> > -
> > -           rotate_pages(page_addr_list, uv_start_page,
> > -                        rot_info->width_pages_uv,
> > -                        rot_info->height_pages_uv,
> > -                        rot_info->width_pages_uv,
> > -                        st, sg);
> > +   for (i = 0 ; i < ARRAY_SIZE(info->plane); i++) {
> > +           sg = rotate_pages(page_addr_list, info->plane[i].offset,
> > +                             info->plane[i].width, info->plane[i].height,
> > +                             info->plane[i].stride, st, sg);
> >     }
> >  
> > -   DRM_DEBUG_KMS(
> > -                 "Created rotated page mapping for object size %zu 
> > (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u plane 
> > 0)).\n",
> > -                 obj->base.size, rot_info->pitch, rot_info->height,
> > -                 rot_info->pixel_format, rot_info->width_pages,
> > -                 rot_info->height_pages, size_pages + size_pages_uv,
> > -                 size_pages);
> > +   DRM_DEBUG_KMS("Created rotated page mapping for object size %zu (%ux%u 
> > tiles, %u pages)\n",
> > +                 obj->base.size, info->plane[0].width, 
> > info->plane[0].height, size);
> >  
> >     drm_free_large(page_addr_list);
> >  
> > @@ -3360,12 +3328,8 @@ err_sg_alloc:
> >  err_st_alloc:
> >     drm_free_large(page_addr_list);
> >  
> > -   DRM_DEBUG_KMS(
> > -                 "Failed to create rotated mapping for object size %zu! 
> > (%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %u pages (%u 
> > plane 0))\n",
> > -                 obj->base.size, ret, rot_info->pitch, rot_info->height,
> > -                 rot_info->pixel_format, rot_info->width_pages,
> > -                 rot_info->height_pages, size_pages + size_pages_uv,
> > -                 size_pages);
> > +   DRM_DEBUG_KMS("Failed to create rotated mapping for object size %zu! 
> > (%ux%u tiles, %u pages)\n",
> > +                 obj->base.size, info->plane[0].width, 
> > info->plane[0].height, size);
> >     return ERR_PTR(ret);
> >  }
> >  
> > @@ -3516,7 +3480,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
> >     if (view->type == I915_GGTT_VIEW_NORMAL) {
> >             return obj->base.size;
> >     } else if (view->type == I915_GGTT_VIEW_ROTATED) {
> > -           return view->rotated.size;
> > +           return intel_rotation_info_size(&view->rotated) << PAGE_SHIFT;
> >     } else if (view->type == I915_GGTT_VIEW_PARTIAL) {
> >             return view->partial.size << PAGE_SHIFT;
> >     } else {
> > diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h 
> > b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > index 68de734..ea28f7d 100644
> > --- a/drivers/gpu/drm/i915/i915_gem_gtt.h
> > +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
> > @@ -136,16 +136,10 @@ enum i915_ggtt_view_type {
> >  };
> >  
> >  struct intel_rotation_info {
> > -   unsigned int height;
> > -   unsigned int pitch;
> > -   unsigned int uv_offset;
> > -   uint32_t pixel_format;
> > -   uint64_t fb_modifier;
> > -   unsigned int width_pages, height_pages;
> > -   uint64_t size;
> > -   unsigned int width_pages_uv, height_pages_uv;
> > -   uint64_t size_uv;
> > -   unsigned int uv_start_page;
> > +   struct {
> > +           /* tiles */
> > +           unsigned int width, height, stride, offset;
> > +   } plane[2];
> >  };
> >  
> >  struct i915_ggtt_view {
> > diff --git a/drivers/gpu/drm/i915/intel_display.c 
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 028dc4a..0dcb710 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -2274,49 +2274,28 @@ intel_fb_align_height(struct drm_device *dev, 
> > unsigned int height,
> >     return ALIGN(height, tile_height);
> >  }
> >  
> > -static int
> > +unsigned int intel_rotation_info_size(const struct intel_rotation_info 
> > *info)
> > +{
> > +   unsigned int size = 0;
> > +   int i;
> > +
> > +   for (i = 0 ; i < ARRAY_SIZE(info->plane); i++)
> > +           size += info->plane[i].width * info->plane[i].height;
> > +
> > +   return size;
> > +}
> > +
> > +static void
> >  intel_fill_fb_ggtt_view(struct i915_ggtt_view *view,
> >                     const struct drm_framebuffer *fb,
> >                     unsigned int rotation)
> >  {
> > -   struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > -   struct intel_rotation_info *info = &view->rotated;
> > -   unsigned int tile_size, tile_width, tile_height, cpp;
> > -
> > -   *view = i915_ggtt_view_normal;
> > -
> > -   if (!intel_rotation_90_or_270(rotation))
> > -           return 0;
> > -
> > -   *view = i915_ggtt_view_rotated;
> > -
> > -   info->height = fb->height;
> > -   info->pixel_format = fb->pixel_format;
> > -   info->pitch = fb->pitches[0];
> > -   info->uv_offset = fb->offsets[1];
> > -   info->fb_modifier = fb->modifier[0];
> > -
> > -   tile_size = intel_tile_size(dev_priv);
> > -
> > -   cpp = drm_format_plane_cpp(fb->pixel_format, 0);
> > -   tile_width = intel_tile_width(dev_priv, cpp, fb->modifier[0]);
> > -   tile_height = tile_size / tile_width;
> > -
> > -   info->width_pages = DIV_ROUND_UP(fb->pitches[0], tile_width);
> > -   info->height_pages = DIV_ROUND_UP(fb->height, tile_height);
> > -   info->size = info->width_pages * info->height_pages * tile_size;
> > -
> > -   if (info->pixel_format == DRM_FORMAT_NV12) {
> > -           cpp = drm_format_plane_cpp(fb->pixel_format, 1);
> > -           tile_width = intel_tile_width(dev_priv, fb->modifier[1], cpp);
> > -           tile_height = tile_size / tile_width;
> > -
> > -           info->width_pages_uv = DIV_ROUND_UP(fb->pitches[1], tile_width);
> > -           info->height_pages_uv = DIV_ROUND_UP(fb->height / 2, 
> > tile_height);
> > -           info->size_uv = info->width_pages_uv * info->height_pages_uv * 
> > tile_size;
> > +   if (intel_rotation_90_or_270(rotation)) {
> > +           *view = i915_ggtt_view_rotated;
> > +           view->rotated = to_intel_framebuffer(fb)->info;
> > +   } else {
> > +           *view = i915_ggtt_view_normal;
> >     }
> > -
> > -   return 0;
> >  }
> >  
> >  static unsigned int intel_linear_alignment(const struct drm_i915_private 
> > *dev_priv)
> > @@ -2368,9 +2347,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb,
> >  
> >     alignment = intel_surf_alignment(dev_priv, fb->modifier[0]);
> >  
> > -   ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
> > -   if (ret)
> > -           return ret;
> > +   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
> > @@ -2433,18 +2410,31 @@ static void intel_unpin_fb_obj(struct 
> > drm_framebuffer *fb, unsigned int rotation
> >  {
> >     struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >     struct i915_ggtt_view view;
> > -   int ret;
> >  
> >     WARN_ON(!mutex_is_locked(&obj->base.dev->struct_mutex));
> >  
> > -   ret = intel_fill_fb_ggtt_view(&view, fb, rotation);
> > -   WARN_ONCE(ret, "Couldn't get view from plane state!");
> > +   intel_fill_fb_ggtt_view(&view, fb, rotation);
> >  
> >     i915_gem_object_unpin_fence(obj);
> >     i915_gem_object_unpin_from_display_plane(obj, &view);
> >  }
> >  
> >  /*
> > + * Convert the x/y offsets into a linear offset.
> > + * Only valid with 0/180 degree rotation, which is fine since linear
> > + * offset is only used with linear buffers on pre-hsw and tiled buffers
> > + * with gen2/3, and 90/270 degree rotations isn't supported on any of them.
> > + */
> > +unsigned int intel_fb_xy_to_linear(int x, int y,
> > +                              const struct drm_framebuffer *fb, int plane)
> > +{
> > +   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > +   unsigned int pitch = fb->pitches[plane];
> > +
> > +   return y * pitch + x * cpp;
> > +}
> > +
> > +/*
> >   * Return the tile dimensions in pixel units matching
> >   * the specified rotation angle.
> >   */
> > @@ -2475,6 +2465,55 @@ static void intel_rotate_tile_dims(unsigned int 
> > *tile_width,
> >  }
> >  
> >  /*
> > + * Add the x/y offsets derived from fb->offsets[] to the user
> > + * specified plane src x/y offsets. The resulting x/y offsets
> > + * specify the start of scanout from the beginning of the gtt mapping.
> > + */
> > +void intel_add_fb_offsets(int *x, int *y,
> > +                     const struct drm_framebuffer *fb, int plane,
> > +                     unsigned int rotation)
> > +
> > +{
> > +   const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > +   const struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > +   unsigned int pitch;
> > +
> > +   if (intel_rotation_90_or_270(rotation)) {
> > +           pitch = intel_fb->plane[plane].rotated.pitch;
> > +
> > +           *x += intel_fb->plane[plane].rotated.x;
> > +           *y += intel_fb->plane[plane].rotated.y;
> > +   } else {
> > +           pitch = fb->pitches[plane];
> > +
> > +           *x += intel_fb->plane[plane].normal.x;
> > +           *y += intel_fb->plane[plane].normal.y;
> > +   }
> > +
> > +   /* minimize x */
> > +   if (fb->modifier[plane] != DRM_FORMAT_MOD_NONE) {
> > +           unsigned int tile_size, tile_width, tile_height;
> > +
> > +           tile_size = intel_tile_size(dev_priv);
> > +           tile_width = intel_tile_width(dev_priv, fb->modifier[plane], 
> > cpp);
> > +           tile_height = tile_size / tile_width;
> > +
> > +           intel_rotate_tile_dims(&tile_width, &tile_height,
> > +                                  &pitch, cpp, rotation);
> > +
> > +           *y += *x / pitch * tile_height;
> > +           *x  = *x % pitch;
> > +   } else {
> > +           /* in pixels */
> > +           pitch /= cpp;
> > +
> > +           *y += *x / pitch;
> > +           *x  = *x % pitch;
> > +   }
> 
> This is called before we do the entire page_offset dance, so I don't think
> we need a special case for tiled vs. untiled.

Hmm. I think this is leftover from some earlier version where I did
stuff in a different order. Yeah, the page_offset stuff should deal
with this just fine, and for gen2/3 we just convert it to a linear 
offset anyway so it's the same thing in the end. I'll just throw the
entire "minimize x" crap in the bin.

> -Daniel
> 
> > +}
> > +
> > +/*
> >   * Adjust the page offset by moving the difference into
> >   * the x/y offsets.
> >   *
> > @@ -2514,20 +2553,23 @@ static void intel_adjust_page_offset(int *x, int *y,
> >   * In the 90/270 rotated case, x and y are assumed
> >   * to be already rotated to match the rotated GTT view, and
> >   * pitch is the tile_height aligned framebuffer height.
> > + *
> > + * This function is used when computing the derived information
> > + * under intel_framebuffer, so using any of that information
> > + * here is not allowed. Anything under drm_framebuffer can be
> > + * used. This is why the user has to pass in the pitch since it
> > + * is specified in the rotated orientation.
> >   */
> > -unsigned long intel_compute_page_offset(int *x, int *y,
> > -                                   const struct drm_framebuffer *fb, int 
> > plane,
> > -                                   unsigned int pitch,
> > -                                   unsigned int rotation)
> > +static unsigned int _intel_compute_page_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,
> > +                                          unsigned int alignment)
> >  {
> > -   const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> >     uint64_t fb_modifier = fb->modifier[plane];
> >     unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > -   unsigned int offset, alignment;
> > -
> > -   alignment = intel_surf_alignment(dev_priv, fb_modifier);
> > -   if (alignment)
> > -           alignment--;
> > +   unsigned int offset;
> >  
> >     if (fb_modifier != DRM_FORMAT_MOD_NONE) {
> >             unsigned int tile_size, tile_width, tile_height;
> > @@ -2560,6 +2602,145 @@ unsigned long intel_compute_page_offset(int *x, int 
> > *y,
> >     return offset & ~alignment;
> >  }
> >  
> > +unsigned int intel_compute_page_offset(int *x, int *y,
> > +                                  const struct drm_framebuffer *fb, int 
> > plane,
> > +                                  unsigned int pitch,
> > +                                  unsigned int rotation)
> > +{
> > +   const struct drm_i915_private *dev_priv = to_i915(fb->dev);
> > +   unsigned int alignment = intel_surf_alignment(dev_priv, 
> > fb->modifier[plane]);
> > +
> > +   return _intel_compute_page_offset(dev_priv, x, y, fb, plane, pitch,
> > +                                     rotation, alignment ? (alignment - 1) 
> > : 0);
> > +}
> > +
> > +/* Convert the fb->offset[] linear offset into x/y offsets */
> > +static void intel_fb_offset_to_xy(int *x, int *y,
> > +                             const struct drm_framebuffer *fb, int plane)
> > +{
> > +   unsigned int cpp = drm_format_plane_cpp(fb->pixel_format, plane);
> > +   unsigned int pitch = fb->pitches[plane];
> > +   unsigned int linear_offset = fb->offsets[plane];
> > +
> > +   *y = linear_offset / pitch;
> > +   *x = linear_offset % pitch / cpp;
> > +}
> > +
> > +static int
> > +intel_fill_fb_info(struct drm_i915_private *dev_priv,
> > +              struct drm_framebuffer *fb)
> > +{
> > +   struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> > +   struct intel_rotation_info *info = &intel_fb->info;
> > +   unsigned int tile_size;
> > +   unsigned int gtt_offset_rotated = 0;
> > +   unsigned int max_size = 0;
> > +   uint32_t format = fb->pixel_format;
> > +   int i, num_planes = drm_format_num_planes(format);
> > +
> > +   tile_size = intel_tile_size(dev_priv);
> > +
> > +   for (i = 0; i < num_planes; i++) {
> > +           unsigned int width, height;
> > +           unsigned int cpp, offset, size;
> > +           int x, y;
> > +
> > +           cpp = drm_format_plane_cpp(format, i);
> > +           width = drm_format_plane_width(fb->width, format, i);
> > +           height = drm_format_plane_height(fb->height, format, i);
> > +
> > +           intel_fb_offset_to_xy(&x, &y, fb, i);
> > +
> > +           /*
> > +            * First pixel of the framebuffer from
> > +            * the start of the normal gtt mapping.
> > +            */
> > +           intel_fb->plane[i].normal.x = x;
> > +           intel_fb->plane[i].normal.y = y;
> > +
> > +           offset = _intel_compute_page_offset(dev_priv, &x, &y,
> > +                                               fb, 0, fb->pitches[i],
> > +                                               BIT(DRM_ROTATE_0),
> > +                                               tile_size);
> > +           offset /= tile_size;
> > +           DRM_DEBUG("page offset %u pages\n", offset);
> > +
> > +           if (fb->modifier[i] != DRM_FORMAT_MOD_NONE) {
> > +                   unsigned int tile_width, tile_height;
> > +                   unsigned int pitch;
> > +                   struct drm_rect r;
> > +
> > +                   tile_width = intel_tile_width(dev_priv, 
> > fb->modifier[i], cpp);
> > +                   tile_height = tile_size / tile_width;
> > +
> > +                   info->plane[i].offset = offset;
> > +                   info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i], 
> > tile_width);
> > +                   info->plane[i].width = DIV_ROUND_UP((x + width) * cpp, 
> > tile_width);
> > +                   info->plane[i].height = DIV_ROUND_UP(y + height, 
> > tile_height);
> > +
> > +
> > +                   intel_fb->plane[i].rotated.pitch =
> > +                           info->plane[i].height * tile_height;
> > +
> > +                   /* how many tiles does this plane need */
> > +                   size = info->plane[i].stride * info->plane[i].height;
> > +                   /*
> > +                    * If the plane isn't horizontally tile aligned,
> > +                    * we need one more tile.
> > +                    */
> > +                   if (x != 0)
> > +                           size++;
> > +
> > +                   pitch = intel_fb->plane[i].rotated.pitch;
> > +
> > +                   /* rotate the x/y offsets to match the GTT view */
> > +                   r.x1 = x;
> > +                   r.y1 = y;
> > +                   r.x2 = x + width;
> > +                   r.y2 = y + height;
> > +                   drm_rect_rotate(&r, width, pitch, BIT(DRM_ROTATE_270));
> > +                   x = r.x1;
> > +                   y = r.y1;
> > +
> > +                   intel_rotate_tile_dims(&tile_width, &tile_height, 
> > &pitch,
> > +                                          cpp, BIT(DRM_ROTATE_270));
> > +
> > +                   /*
> > +                    * We only keep the x/y offsets, so push all of the
> > +                    * gtt offset into the x/y offsets.
> > +                    */
> > +                   intel_adjust_page_offset(&x, &y, tile_width, 
> > tile_height,
> > +                                            tile_size, pitch,
> > +                                            gtt_offset_rotated * 
> > tile_size, 0);
> > +
> > +                   gtt_offset_rotated += info->plane[i].width * 
> > info->plane[i].height;
> > +
> > +                   /*
> > +                    * First pixel of the framebuffer from
> > +                    * the start of the rotated gtt mapping.
> > +                    */
> > +                   intel_fb->plane[i].rotated.x = x;
> > +                   intel_fb->plane[i].rotated.y = y;
> > +           } else {
> > +                   size = DIV_ROUND_UP((y + height) * fb->pitches[i] +
> > +                                       x * cpp, tile_size);
> > +           }
> > +           DRM_DEBUG("%d offset %u, size %u, stride %u, height %u\n",
> > +                     i, offset, size, info->plane[i].stride, 
> > info->plane[i].height);
> > +
> > +           /* how many tiles in total needed in the bo */
> > +           max_size = max(max_size, offset + size);
> > +   }
> > +
> > +   if (max_size * tile_size > to_intel_framebuffer(fb)->obj->base.size) {
> > +           DRM_DEBUG("fb too big for bo (need %u bytes, have %zu bytes)\n",
> > +                     max_size * tile_size, 
> > to_intel_framebuffer(fb)->obj->base.size);
> > +           return -EINVAL;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> >  static int i9xx_format_to_fourcc(int format)
> >  {
> >     switch (format) {
> > @@ -2761,7 +2942,7 @@ static void i9xx_update_primary_plane(struct drm_crtc 
> > *crtc,
> >     struct drm_i915_gem_object *obj;
> >     int plane = intel_crtc->plane;
> >     unsigned int rotation;
> > -   unsigned long linear_offset;
> > +   unsigned int linear_offset;
> >     u32 dspcntr;
> >     u32 reg = DSPCNTR(plane);
> >     int pixel_size;
> > @@ -2839,30 +3020,25 @@ static void i9xx_update_primary_plane(struct 
> > drm_crtc *crtc,
> >     if (IS_G4X(dev))
> >             dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> >  
> > -   linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >  
> > -   if (INTEL_INFO(dev)->gen >= 4) {
> > +   if (INTEL_INFO(dev)->gen >= 4)
> >             intel_crtc->dspaddr_offset =
> >                     intel_compute_page_offset(&x, &y, fb, 0,
> >                                               fb->pitches[0], rotation);
> > -           linear_offset -= intel_crtc->dspaddr_offset;
> > -   } else {
> > -           intel_crtc->dspaddr_offset = linear_offset;
> > -   }
> >  
> >     if (crtc->primary->state->rotation == BIT(DRM_ROTATE_180)) {
> >             dspcntr |= DISPPLANE_ROTATE_180;
> >  
> >             x += (intel_crtc->config->pipe_src_w - 1);
> >             y += (intel_crtc->config->pipe_src_h - 1);
> > -
> > -           /* Finding the last pixel of the last line of the display
> > -           data and adding to linear_offset*/
> > -           linear_offset +=
> > -                   (intel_crtc->config->pipe_src_h - 1) * fb->pitches[0] +
> > -                   (intel_crtc->config->pipe_src_w - 1) * pixel_size;
> >     }
> >  
> > +   linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> > +   if (INTEL_INFO(dev)->gen < 4)
> > +           intel_crtc->dspaddr_offset = linear_offset;
> > +
> >     intel_crtc->adjusted_x = x;
> >     intel_crtc->adjusted_y = y;
> >  
> > @@ -2871,7 +3047,8 @@ static void i9xx_update_primary_plane(struct drm_crtc 
> > *crtc,
> >     I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
> >     if (INTEL_INFO(dev)->gen >= 4) {
> >             I915_WRITE(DSPSURF(plane),
> > -                      i915_gem_obj_ggtt_offset(obj) + 
> > intel_crtc->dspaddr_offset);
> > +                      intel_surf_gtt_offset(fb, 0, rotation) +
> > +                      intel_crtc->dspaddr_offset);
> >             I915_WRITE(DSPTILEOFF(plane), (y << 16) | x);
> >             I915_WRITE(DSPLINOFF(plane), linear_offset);
> >     } else
> > @@ -2891,7 +3068,7 @@ static void ironlake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >     struct drm_i915_gem_object *obj;
> >     int plane = intel_crtc->plane;
> >     unsigned int rotation;
> > -   unsigned long linear_offset;
> > +   unsigned int linear_offset;
> >     u32 dspcntr;
> >     u32 reg = DSPCNTR(plane);
> >     int pixel_size;
> > @@ -2946,26 +3123,22 @@ static void ironlake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >     if (!IS_HASWELL(dev) && !IS_BROADWELL(dev))
> >             dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE;
> >  
> > -   linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >     intel_crtc->dspaddr_offset =
> >             intel_compute_page_offset(&x, &y, fb, 0,
> >                                       fb->pitches[0], rotation);
> > -   linear_offset -= intel_crtc->dspaddr_offset;
> > +
> >     if (rotation == BIT(DRM_ROTATE_180)) {
> >             dspcntr |= DISPPLANE_ROTATE_180;
> >  
> >             if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> >                     x += (intel_crtc->config->pipe_src_w - 1);
> >                     y += (intel_crtc->config->pipe_src_h - 1);
> > -
> > -                   /* Finding the last pixel of the last line of the 
> > display
> > -                   data and adding to linear_offset*/
> > -                   linear_offset +=
> > -                           (intel_crtc->config->pipe_src_h - 1) * 
> > fb->pitches[0] +
> > -                           (intel_crtc->config->pipe_src_w - 1) * 
> > pixel_size;
> >             }
> >     }
> >  
> > +   linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >     intel_crtc->adjusted_x = x;
> >     intel_crtc->adjusted_y = y;
> >  
> > @@ -2973,7 +3146,8 @@ static void ironlake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >  
> >     I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]);
> >     I915_WRITE(DSPSURF(plane),
> > -              i915_gem_obj_ggtt_offset(obj) + intel_crtc->dspaddr_offset);
> > +              intel_surf_gtt_offset(fb, 0, rotation) +
> > +              intel_crtc->dspaddr_offset);
> >     if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
> >             I915_WRITE(DSPOFFSET(plane), (y << 16) | x);
> >     } else {
> > @@ -3000,30 +3174,15 @@ u32 intel_fb_stride_alignment(const struct 
> > drm_i915_private *dev_priv,
> >     }
> >  }
> >  
> > -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> > -                                struct drm_i915_gem_object *obj,
> > -                                unsigned int plane)
> > +unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
> > +                              unsigned int rotation)
> 
> If you want to frob the interface, then I'd replace the fb and rotation
> with the plane state.

Hmm. Yeah here we should always have a plane state, so could pass that
in. It's a bit funky passing in the plane state and the (color) plane
index. Usually the latter goes with fb or pixel format. But I think I
already have some wm cleanup stuff somewhere that does the same actually,
so might as well do it here.

I'm also thinking we may want to move a bunch of this coordinate
mangling into the check phase of the operation and reduce the commit
to just getting the vma offset and adding it with the page_offset
computed in check(). But I'll leave that for the future.

> 
> >  {
> > -   const struct i915_ggtt_view *view = &i915_ggtt_view_normal;
> > -   struct i915_vma *vma;
> > -   unsigned char *offset;
> > +   struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +   struct i915_ggtt_view view;
> >  
> > -   if (intel_rotation_90_or_270(intel_plane->base.state->rotation))
> > -           view = &i915_ggtt_view_rotated;
> > +   intel_fill_fb_ggtt_view(&view, fb, rotation);
> >  
> > -   vma = i915_gem_obj_to_ggtt_view(obj, view);
> > -   if (WARN(!vma, "ggtt vma for display object not found! (view=%u)\n",
> > -           view->type))
> > -           return -1;
> > -
> > -   offset = (unsigned char *)vma->node.start;
> > -
> > -   if (plane == 1) {
> > -           offset += vma->ggtt_view.rotated.uv_start_page *
> > -                     PAGE_SIZE;
> > -   }
> > -
> > -   return (unsigned long)offset;
> > +   return i915_gem_obj_ggtt_offset_view(obj, &view);
> >  }
> >  
> >  static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id)
> > @@ -3142,18 +3301,16 @@ static void skylake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >     struct drm_i915_private *dev_priv = dev->dev_private;
> >     struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> >     struct drm_plane *plane = crtc->primary;
> > +   struct intel_framebuffer *intel_fb;
> >     bool visible = to_intel_plane_state(plane->state)->visible;
> > -   struct drm_i915_gem_object *obj;
> >     int pipe = intel_crtc->pipe;
> >     u32 plane_ctl, stride_div, stride;
> > -   u32 tile_height, plane_offset, plane_size;
> >     unsigned int rotation;
> > -   int x_offset, y_offset;
> >     unsigned long surf_addr;
> >     struct intel_crtc_state *crtc_state = intel_crtc->config;
> >     struct intel_plane_state *plane_state;
> > -   int src_x = 0, src_y = 0, src_w = 0, src_h = 0;
> > -   int dst_x = 0, dst_y = 0, dst_w = 0, dst_h = 0;
> > +   int src_w, src_h;
> > +   int dst_x, dst_y, dst_w, dst_h;
> >     int scaler_id = -1;
> >     int pixel_size;
> >  
> > @@ -3166,6 +3323,7 @@ static void skylake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >             return;
> >     }
> >  
> > +   intel_fb = to_intel_framebuffer(fb);
> >     pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >  
> >     plane_ctl = PLANE_CTL_ENABLE |
> > @@ -3179,16 +3337,7 @@ static void skylake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >     rotation = plane->state->rotation;
> >     plane_ctl |= skl_plane_ctl_rotation(rotation);
> >  
> > -   obj = intel_fb_obj(fb);
> > -   stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > -                                          fb->pixel_format);
> > -   surf_addr = intel_plane_obj_offset(to_intel_plane(plane), obj, 0);
> > -
> > -   WARN_ON(drm_rect_width(&plane_state->src) == 0);
> > -
> >     scaler_id = plane_state->scaler_id;
> > -   src_x = plane_state->src.x1 >> 16;
> > -   src_y = plane_state->src.y1 >> 16;
> >     src_w = drm_rect_width(&plane_state->src) >> 16;
> >     src_h = drm_rect_height(&plane_state->src) >> 16;
> >     dst_x = plane_state->dst.x1;
> > @@ -3196,31 +3345,48 @@ static void skylake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >     dst_w = drm_rect_width(&plane_state->dst);
> >     dst_h = drm_rect_height(&plane_state->dst);
> >  
> > -   WARN_ON(x != src_x || y != src_y);
> > -
> >     if (intel_rotation_90_or_270(rotation)) {
> > -           /* stride = Surface height in tiles */
> > -           tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> > -                                           pixel_size);
> > -           stride = DIV_ROUND_UP(fb->height, tile_height);
> > -           x_offset = stride * tile_height - y - src_h;
> > -           y_offset = x;
> > -           plane_size = (src_w - 1) << 16 | (src_h - 1);
> > +           struct drm_rect r = {
> > +                   .x1 = x,
> > +                   .x2 = x + src_w,
> > +                   .y1 = y,
> > +                   .y2 = y + src_h,
> > +           };
> > +
> > +           /* Rotate src coordinates to match rotated GTT view */
> > +           drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> > +
> > +           x = r.x1;
> > +           y = r.y1;
> > +           src_w = drm_rect_width(&r);
> > +           src_h = drm_rect_height(&r);
> > +
> > +           stride_div = intel_tile_height(dev_priv, fb->modifier[0],
> > +                                          pixel_size);
> > +           stride = intel_fb->plane[0].rotated.pitch;
> >     } else {
> > -           stride = fb->pitches[0] / stride_div;
> > -           x_offset = x;
> > -           y_offset = y;
> > -           plane_size = (src_h - 1) << 16 | (src_w - 1);
> > +           stride_div = intel_fb_stride_alignment(dev_priv, 
> > fb->modifier[0],
> > +                                                  fb->pixel_format);
> > +           stride = fb->pitches[0];
> >     }
> > -   plane_offset = y_offset << 16 | x_offset;
> >  
> > -   intel_crtc->adjusted_x = x_offset;
> > -   intel_crtc->adjusted_y = y_offset;
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > +   surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> > +                                         stride, rotation);
> > +
> > +   /* Sizes are 0 based */
> > +   src_w--;
> > +   src_h--;
> > +   dst_w--;
> > +   dst_h--;
> > +
> > +   intel_crtc->adjusted_x = x;
> > +   intel_crtc->adjusted_y = y;
> >  
> >     I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl);
> > -   I915_WRITE(PLANE_OFFSET(pipe, 0), plane_offset);
> > -   I915_WRITE(PLANE_SIZE(pipe, 0), plane_size);
> > -   I915_WRITE(PLANE_STRIDE(pipe, 0), stride);
> > +   I915_WRITE(PLANE_OFFSET(pipe, 0), (y << 16) | x);
> > +   I915_WRITE(PLANE_STRIDE(pipe, 0), stride / stride_div);
> > +   I915_WRITE(PLANE_SIZE(pipe, 0), (src_h << 16) | src_w);
> >  
> >     if (scaler_id >= 0) {
> >             uint32_t ps_ctrl = 0;
> > @@ -3237,7 +3403,8 @@ static void skylake_update_primary_plane(struct 
> > drm_crtc *crtc,
> >             I915_WRITE(PLANE_POS(pipe, 0), (dst_y << 16) | dst_x);
> >     }
> >  
> > -   I915_WRITE(PLANE_SURF(pipe, 0), surf_addr);
> > +   I915_WRITE(PLANE_SURF(pipe, 0),
> > +              intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
> >  
> >     POSTING_READ(PLANE_SURF(pipe, 0));
> >  }
> > @@ -11521,8 +11688,7 @@ static int intel_crtc_page_flip(struct drm_crtc 
> > *crtc,
> >     if (ret)
> >             goto cleanup_pending;
> >  
> > -   work->gtt_offset = intel_plane_obj_offset(to_intel_plane(primary),
> > -                                             obj, 0);
> > +   work->gtt_offset = intel_surf_gtt_offset(fb, 0, 
> > primary->state->rotation);
> >     work->gtt_offset += intel_crtc->dspaddr_offset;
> >  
> >     if (mmio_flip) {
> > @@ -14319,7 +14485,6 @@ static int intel_framebuffer_init(struct drm_device 
> > *dev,
> >                               struct drm_i915_gem_object *obj)
> >  {
> >     struct drm_i915_private *dev_priv = to_i915(dev);
> > -   unsigned int aligned_height;
> >     int ret;
> >     u32 pitch_limit, stride_alignment;
> >  
> > @@ -14443,16 +14608,13 @@ static int intel_framebuffer_init(struct 
> > drm_device *dev,
> >     if (ret)
> >             return ret;
> >  
> > -   aligned_height = intel_fb_align_height(dev, mode_cmd->height,
> > -                                          mode_cmd->pixel_format,
> > -                                          mode_cmd->modifier[0]);
> > -   /* FIXME drm helper for size checks (especially planar formats)? */
> > -   if (obj->base.size < aligned_height * mode_cmd->pitches[0])
> > -           return -EINVAL;
> > -
> >     drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd);
> >     intel_fb->obj = obj;
> >  
> > +   ret = intel_fill_fb_info(dev_priv, &intel_fb->base);
> > +   if (ret)
> > +           return ret;
> > +
> >     ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs);
> >     if (ret) {
> >             DRM_ERROR("framebuffer init failed %d\n", ret);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> > b/drivers/gpu/drm/i915/intel_drv.h
> > index 36d049d..395afd3 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -118,6 +118,19 @@ enum intel_output_type {
> >  struct intel_framebuffer {
> >     struct drm_framebuffer base;
> >     struct drm_i915_gem_object *obj;
> > +   struct intel_rotation_info info;
> > +
> > +   struct {
> > +           struct {
> > +                   /* pixels */
> > +                   unsigned int x, y;
> > +           } normal;
> > +           struct {
> > +                   /* pixels */
> > +                   unsigned int x, y;
> > +                   unsigned int pitch;
> > +           } rotated;
> > +   } plane[2];
> >  };
> >  
> >  struct intel_fbdev {
> > @@ -1028,6 +1041,12 @@ void i915_audio_component_init(struct 
> > drm_i915_private *dev_priv);
> >  void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
> >  
> >  /* intel_display.c */
> > +unsigned int intel_rotation_info_size(const struct intel_rotation_info 
> > *info);
> > +unsigned int intel_fb_xy_to_linear(int x, int y,
> > +                              const struct drm_framebuffer *fb, int plane);
> > +void intel_add_fb_offsets(int *x, int *y,
> > +                     const struct drm_framebuffer *fb, int plane,
> > +                     unsigned int rotation);
> >  extern const struct drm_plane_funcs intel_plane_funcs;
> >  bool intel_has_pending_fb_unpin(struct drm_device *dev);
> >  int intel_pch_rawclk(struct drm_device *dev);
> > @@ -1134,10 +1153,10 @@ void assert_fdi_rx_pll(struct drm_i915_private 
> > *dev_priv,
> >  void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool 
> > state);
> >  #define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
> >  #define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
> > -unsigned long intel_compute_page_offset(int *x, int *y,
> > -                                   const struct drm_framebuffer *fb, int 
> > plane,
> > -                                   unsigned int pitch,
> > -                                   unsigned int rotation);
> > +unsigned int intel_compute_page_offset(int *x, int *y,
> > +                                  const struct drm_framebuffer *fb, int 
> > plane,
> > +                                  unsigned int pitch,
> > +                                  unsigned int rotation);
> >  void intel_prepare_reset(struct drm_device *dev);
> >  void intel_finish_reset(struct drm_device *dev);
> >  void hsw_enable_pc8(struct drm_i915_private *dev_priv);
> > @@ -1174,9 +1193,8 @@ void intel_modeset_preclose(struct drm_device *dev, 
> > struct drm_file *file);
> >  int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
> >  int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state 
> > *crtc_state);
> >  
> > -unsigned long intel_plane_obj_offset(struct intel_plane *intel_plane,
> > -                                struct drm_i915_gem_object *obj,
> > -                                unsigned int plane);
> > +unsigned int intel_surf_gtt_offset(struct drm_framebuffer *fb, int plane,
> > +                              unsigned int rotation);
> >  
> >  u32 skl_plane_ctl_format(uint32_t pixel_format);
> >  u32 skl_plane_ctl_tiling(uint64_t fb_modifier);
> > diff --git a/drivers/gpu/drm/i915/intel_sprite.c 
> > b/drivers/gpu/drm/i915/intel_sprite.c
> > index 828c3eb..d9d37b0 100644
> > --- a/drivers/gpu/drm/i915/intel_sprite.c
> > +++ b/drivers/gpu/drm/i915/intel_sprite.c
> > @@ -188,17 +188,15 @@ skl_update_plane(struct drm_plane *drm_plane, struct 
> > drm_crtc *crtc,
> >     struct drm_device *dev = drm_plane->dev;
> >     struct drm_i915_private *dev_priv = dev->dev_private;
> >     struct intel_plane *intel_plane = to_intel_plane(drm_plane);
> > -   struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> > +   struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> >     const int pipe = intel_plane->pipe;
> >     const int plane = intel_plane->plane + 1;
> >     u32 plane_ctl, stride_div, stride;
> >     int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >     const struct drm_intel_sprite_colorkey *key =
> >             &to_intel_plane_state(drm_plane->state)->ckey;
> > -   unsigned long surf_addr;
> > -   u32 tile_height, plane_offset, plane_size;
> > +   unsigned int surf_addr;
> >     unsigned int rotation;
> > -   int x_offset, y_offset;
> >     struct intel_crtc_state *crtc_state = to_intel_crtc(crtc)->config;
> >     int scaler_id;
> >  
> > @@ -215,17 +213,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct 
> > drm_crtc *crtc,
> >                                    pixel_size, true,
> >                                    src_w != crtc_w || src_h != crtc_h);
> >  
> > -   stride_div = intel_fb_stride_alignment(dev_priv, fb->modifier[0],
> > -                                          fb->pixel_format);
> > -
> >     scaler_id = to_intel_plane_state(drm_plane->state)->scaler_id;
> >  
> > -   /* Sizes are 0 based */
> > -   src_w--;
> > -   src_h--;
> > -   crtc_w--;
> > -   crtc_h--;
> > -
> >     if (key->flags) {
> >             I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value);
> >             I915_WRITE(PLANE_KEYMAX(pipe, plane), key->max_value);
> > @@ -237,27 +226,43 @@ skl_update_plane(struct drm_plane *drm_plane, struct 
> > drm_crtc *crtc,
> >     else if (key->flags & I915_SET_COLORKEY_SOURCE)
> >             plane_ctl |= PLANE_CTL_KEY_ENABLE_SOURCE;
> >  
> > -   surf_addr = intel_plane_obj_offset(intel_plane, obj, 0);
> > -
> >     if (intel_rotation_90_or_270(rotation)) {
> > -           /* stride: Surface height in tiles */
> > -           tile_height = intel_tile_height(dev_priv, fb->modifier[0],
> > -                                           pixel_size);
> > -           stride = DIV_ROUND_UP(fb->height, tile_height);
> > -           plane_size = (src_w << 16) | src_h;
> > -           x_offset = stride * tile_height - y - (src_h + 1);
> > -           y_offset = x;
> > +           struct drm_rect r = {
> > +                   .x1 = x,
> > +                   .x2 = x + src_w,
> > +                   .y1 = y,
> > +                   .y2 = y + src_h,
> > +           };
> > +
> > +           /* Rotate src coordinates to match rotated GTT view */
> > +           drm_rect_rotate(&r, fb->width, fb->height, BIT(DRM_ROTATE_270));
> > +
> > +           x = r.x1;
> > +           y = r.y1;
> > +           src_w = drm_rect_width(&r);
> > +           src_h = drm_rect_height(&r);
> > +
> > +           stride_div = intel_tile_height(dev_priv, fb->modifier[0], 
> > pixel_size);
> > +           stride = intel_fb->plane[0].rotated.pitch;
> >     } else {
> > -           stride = fb->pitches[0] / stride_div;
> > -           plane_size = (src_h << 16) | src_w;
> > -           x_offset = x;
> > -           y_offset = y;
> > +           stride_div = intel_fb_stride_alignment(dev_priv, 
> > fb->modifier[0],
> > +                                                  fb->pixel_format);
> > +           stride = fb->pitches[0];
> >     }
> > -   plane_offset = y_offset << 16 | x_offset;
> >  
> > -   I915_WRITE(PLANE_OFFSET(pipe, plane), plane_offset);
> > -   I915_WRITE(PLANE_STRIDE(pipe, plane), stride);
> > -   I915_WRITE(PLANE_SIZE(pipe, plane), plane_size);
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> > +   surf_addr = intel_compute_page_offset(&x, &y, fb, 0,
> > +                                         stride, rotation);
> > +
> > +   /* Sizes are 0 based */
> > +   src_w--;
> > +   src_h--;
> > +   crtc_w--;
> > +   crtc_h--;
> > +
> > +   I915_WRITE(PLANE_OFFSET(pipe, plane), (y << 16) | x);
> > +   I915_WRITE(PLANE_STRIDE(pipe, plane), stride / stride_div);
> > +   I915_WRITE(PLANE_SIZE(pipe, plane), (src_h << 16) | src_w);
> >  
> >     /* program plane scaler */
> >     if (scaler_id >= 0) {
> > @@ -279,7 +284,8 @@ skl_update_plane(struct drm_plane *drm_plane, struct 
> > drm_crtc *crtc,
> >     }
> >  
> >     I915_WRITE(PLANE_CTL(pipe, plane), plane_ctl);
> > -   I915_WRITE(PLANE_SURF(pipe, plane), surf_addr);
> > +   I915_WRITE(PLANE_SURF(pipe, plane),
> > +              intel_surf_gtt_offset(fb, 0, rotation) + surf_addr);
> >     POSTING_READ(PLANE_SURF(pipe, plane));
> >  }
> >  
> > @@ -355,8 +361,7 @@ vlv_update_plane(struct drm_plane *dplane, struct 
> > drm_crtc *crtc,
> >     int plane = intel_plane->plane;
> >     u32 sprctl;
> >     unsigned int rotation = dplane->state->rotation;
> > -   unsigned long sprsurf_offset, linear_offset;
> > -   int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> > +   unsigned int sprsurf_offset, linear_offset;
> >     const struct drm_intel_sprite_colorkey *key =
> >             &to_intel_plane_state(dplane->state)->ckey;
> >  
> > @@ -420,19 +425,19 @@ vlv_update_plane(struct drm_plane *dplane, struct 
> > drm_crtc *crtc,
> >     crtc_w--;
> >     crtc_h--;
> >  
> > -   linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >     sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> >                                                fb->pitches[0], rotation);
> > -   linear_offset -= sprsurf_offset;
> >  
> >     if (rotation == BIT(DRM_ROTATE_180)) {
> >             sprctl |= SP_ROTATE_180;
> >  
> >             x += src_w;
> >             y += src_h;
> > -           linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
> >     }
> >  
> > +   linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >     if (key->flags) {
> >             I915_WRITE(SPKEYMINVAL(pipe, plane), key->min_value);
> >             I915_WRITE(SPKEYMAXVAL(pipe, plane), key->max_value);
> > @@ -457,8 +462,8 @@ vlv_update_plane(struct drm_plane *dplane, struct 
> > drm_crtc *crtc,
> >  
> >     I915_WRITE(SPSIZE(pipe, plane), (crtc_h << 16) | crtc_w);
> >     I915_WRITE(SPCNTR(pipe, plane), sprctl);
> > -   I915_WRITE(SPSURF(pipe, plane), i915_gem_obj_ggtt_offset(obj) +
> > -              sprsurf_offset);
> > +   I915_WRITE(SPSURF(pipe, plane),
> > +              intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
> >     POSTING_READ(SPSURF(pipe, plane));
> >  }
> >  
> > @@ -492,7 +497,7 @@ ivb_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >     enum pipe pipe = intel_plane->pipe;
> >     u32 sprctl, sprscale = 0;
> >     unsigned int rotation = plane->state->rotation;
> > -   unsigned long sprsurf_offset, linear_offset;
> > +   unsigned int sprsurf_offset, linear_offset;
> >     int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >     const struct drm_intel_sprite_colorkey *key =
> >             &to_intel_plane_state(plane->state)->ckey;
> > @@ -552,10 +557,9 @@ ivb_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >     if (crtc_w != src_w || crtc_h != src_h)
> >             sprscale = SPRITE_SCALE_ENABLE | (src_w << 16) | src_h;
> >  
> > -   linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >     sprsurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> >                                                fb->pitches[0], rotation);
> > -   linear_offset -= sprsurf_offset;
> >  
> >     if (rotation == BIT(DRM_ROTATE_180)) {
> >             sprctl |= SPRITE_ROTATE_180;
> > @@ -564,11 +568,11 @@ ivb_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >             if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) {
> >                     x += src_w;
> >                     y += src_h;
> > -                   linear_offset += src_h * fb->pitches[0] +
> > -                           src_w * pixel_size;
> >             }
> >     }
> >  
> > +   linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >     if (key->flags) {
> >             I915_WRITE(SPRKEYVAL(pipe), key->min_value);
> >             I915_WRITE(SPRKEYMAX(pipe), key->max_value);
> > @@ -597,7 +601,7 @@ ivb_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >             I915_WRITE(SPRSCALE(pipe), sprscale);
> >     I915_WRITE(SPRCTL(pipe), sprctl);
> >     I915_WRITE(SPRSURF(pipe),
> > -              i915_gem_obj_ggtt_offset(obj) + sprsurf_offset);
> > +              intel_surf_gtt_offset(fb, 0, rotation) + sprsurf_offset);
> >     POSTING_READ(SPRSURF(pipe));
> >  }
> >  
> > @@ -632,7 +636,7 @@ ilk_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >     struct drm_i915_gem_object *obj = intel_fb_obj(fb);
> >     int pipe = intel_plane->pipe;
> >     unsigned int rotation = plane->state->rotation;
> > -   unsigned long dvssurf_offset, linear_offset;
> > +   unsigned int dvssurf_offset, linear_offset;
> >     u32 dvscntr, dvsscale;
> >     int pixel_size = drm_format_plane_cpp(fb->pixel_format, 0);
> >     const struct drm_intel_sprite_colorkey *key =
> > @@ -689,19 +693,19 @@ ilk_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >     if (crtc_w != src_w || crtc_h != src_h)
> >             dvsscale = DVS_SCALE_ENABLE | (src_w << 16) | src_h;
> >  
> > -   linear_offset = y * fb->pitches[0] + x * pixel_size;
> > +   intel_add_fb_offsets(&x, &y, fb, 0, rotation);
> >     dvssurf_offset = intel_compute_page_offset(&x, &y, fb, 0,
> >                                                fb->pitches[0], rotation);
> > -   linear_offset -= dvssurf_offset;
> >  
> >     if (rotation == BIT(DRM_ROTATE_180)) {
> >             dvscntr |= DVS_ROTATE_180;
> >  
> >             x += src_w;
> >             y += src_h;
> > -           linear_offset += src_h * fb->pitches[0] + src_w * pixel_size;
> >     }
> >  
> > +   linear_offset = intel_fb_xy_to_linear(x, y, fb, 0);
> > +
> >     if (key->flags) {
> >             I915_WRITE(DVSKEYVAL(pipe), key->min_value);
> >             I915_WRITE(DVSKEYMAX(pipe), key->max_value);
> > @@ -725,7 +729,7 @@ ilk_update_plane(struct drm_plane *plane, struct 
> > drm_crtc *crtc,
> >     I915_WRITE(DVSSCALE(pipe), dvsscale);
> >     I915_WRITE(DVSCNTR(pipe), dvscntr);
> >     I915_WRITE(DVSSURF(pipe),
> > -              i915_gem_obj_ggtt_offset(obj) + dvssurf_offset);
> > +              intel_surf_gtt_offset(fb, 0, rotation) + dvssurf_offset);
> >     POSTING_READ(DVSSURF(pipe));
> >  }
> >  
> > -- 
> > 2.4.9
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > [email protected]
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to