Skip to content

Commit

Permalink
drm/i915: Handle untiled planes when computing their offsets
Browse files Browse the repository at this point in the history
We trim the fb to fit the CRTC by computing the offset of that CRTC to
its nearest tile_row origin. This allows us to use framebuffers that are
larger than the CRTC limits without additional work.

However, we failed to compute the offset for a linear framebuffer
correctly as we treated its x-advance in whole tiles (instead of the
linear increment expected), leaving the CRTC misaligned with its
contents.

Fixes regression from commit c2c7513
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Thu Jul 5 12:17:30 2012 +0200

    drm/i915: adjust framebuffer base address on gen4+

v2: Adjust relative x-coordinate after linear alignment (vsyrjala)
v3: Repaint with pokadots (vsyrjala)

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61152
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: stable@vger.kernel.org
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Feb 21, 2013
1 parent 210561f commit bc75286
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 22 deletions.
41 changes: 26 additions & 15 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2001,18 +2001,29 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj)

/* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel
* is assumed to be a power-of-two. */
unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
unsigned int bpp,
unsigned int pitch)
unsigned long intel_gen4_compute_page_offset(int *x, int *y,
unsigned int tiling_mode,
unsigned int cpp,
unsigned int pitch)
{
int tile_rows, tiles;
if (tiling_mode != I915_TILING_NONE) {
unsigned int tile_rows, tiles;

tile_rows = *y / 8;
*y %= 8;
tiles = *x / (512/bpp);
*x %= 512/bpp;
tile_rows = *y / 8;
*y %= 8;

return tile_rows * pitch * 8 + tiles * 4096;
tiles = *x / (512/cpp);
*x %= 512/cpp;

return tile_rows * pitch * 8 + tiles * 4096;
} else {
unsigned int offset;

offset = *y * pitch + *x * cpp;
*y = 0;
*x = (offset & 4095) / cpp;
return offset & -4096;
}
}

static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
Expand Down Expand Up @@ -2089,9 +2100,9 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,

if (INTEL_INFO(dev)->gen >= 4) {
intel_crtc->dspaddr_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
fb->bits_per_pixel / 8,
fb->pitches[0]);
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
fb->bits_per_pixel / 8,
fb->pitches[0]);
linear_offset -= intel_crtc->dspaddr_offset;
} else {
intel_crtc->dspaddr_offset = linear_offset;
Expand Down Expand Up @@ -2182,9 +2193,9 @@ static int ironlake_update_plane(struct drm_crtc *crtc,

linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
intel_crtc->dspaddr_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
fb->bits_per_pixel / 8,
fb->pitches[0]);
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
fb->bits_per_pixel / 8,
fb->pitches[0]);
linear_offset -= intel_crtc->dspaddr_offset;

DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n",
Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -649,9 +649,10 @@ extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe,
extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe,
struct drm_display_mode *mode);

extern unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y,
unsigned int bpp,
unsigned int pitch);
extern unsigned long intel_gen4_compute_page_offset(int *x, int *y,
unsigned int tiling_mode,
unsigned int bpp,
unsigned int pitch);

extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
struct drm_file *file_priv);
Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/i915/intel_sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,

linear_offset = y * fb->pitches[0] + x * pixel_size;
sprsurf_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
pixel_size, fb->pitches[0]);
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
pixel_size, fb->pitches[0]);
linear_offset -= sprsurf_offset;

/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
Expand Down Expand Up @@ -295,8 +295,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,

linear_offset = y * fb->pitches[0] + x * pixel_size;
dvssurf_offset =
intel_gen4_compute_offset_xtiled(&x, &y,
pixel_size, fb->pitches[0]);
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
pixel_size, fb->pitches[0]);
linear_offset -= dvssurf_offset;

if (obj->tiling_mode != I915_TILING_NONE)
Expand Down

0 comments on commit bc75286

Please sign in to comment.