diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-02-21 15:04:31 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-02-21 15:52:08 -0500 |
commit | bc752862170c135d6c09fb22d79eeb451023568e (patch) | |
tree | c9c9d867a1c9c347eff829fc28278168c6364eba /drivers/gpu | |
parent | 210561ffd72d00eccf12c0131b8024d5436bae95 (diff) |
drm/i915: Handle untiled planes when computing their offsets
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 c2c75131244507c93f812862fdbd4f3a37139401
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>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_sprite.c | 8 |
3 files changed, 34 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6eb3882ba9bf..0ff10b3af9ea 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2001,18 +2001,29 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) | |||
2001 | 2001 | ||
2002 | /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel | 2002 | /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel |
2003 | * is assumed to be a power-of-two. */ | 2003 | * is assumed to be a power-of-two. */ |
2004 | unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y, | 2004 | unsigned long intel_gen4_compute_page_offset(int *x, int *y, |
2005 | unsigned int bpp, | 2005 | unsigned int tiling_mode, |
2006 | unsigned int pitch) | 2006 | unsigned int cpp, |
2007 | unsigned int pitch) | ||
2007 | { | 2008 | { |
2008 | int tile_rows, tiles; | 2009 | if (tiling_mode != I915_TILING_NONE) { |
2010 | unsigned int tile_rows, tiles; | ||
2009 | 2011 | ||
2010 | tile_rows = *y / 8; | 2012 | tile_rows = *y / 8; |
2011 | *y %= 8; | 2013 | *y %= 8; |
2012 | tiles = *x / (512/bpp); | ||
2013 | *x %= 512/bpp; | ||
2014 | 2014 | ||
2015 | return tile_rows * pitch * 8 + tiles * 4096; | 2015 | tiles = *x / (512/cpp); |
2016 | *x %= 512/cpp; | ||
2017 | |||
2018 | return tile_rows * pitch * 8 + tiles * 4096; | ||
2019 | } else { | ||
2020 | unsigned int offset; | ||
2021 | |||
2022 | offset = *y * pitch + *x * cpp; | ||
2023 | *y = 0; | ||
2024 | *x = (offset & 4095) / cpp; | ||
2025 | return offset & -4096; | ||
2026 | } | ||
2016 | } | 2027 | } |
2017 | 2028 | ||
2018 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 2029 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
@@ -2089,9 +2100,9 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
2089 | 2100 | ||
2090 | if (INTEL_INFO(dev)->gen >= 4) { | 2101 | if (INTEL_INFO(dev)->gen >= 4) { |
2091 | intel_crtc->dspaddr_offset = | 2102 | intel_crtc->dspaddr_offset = |
2092 | intel_gen4_compute_offset_xtiled(&x, &y, | 2103 | intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, |
2093 | fb->bits_per_pixel / 8, | 2104 | fb->bits_per_pixel / 8, |
2094 | fb->pitches[0]); | 2105 | fb->pitches[0]); |
2095 | linear_offset -= intel_crtc->dspaddr_offset; | 2106 | linear_offset -= intel_crtc->dspaddr_offset; |
2096 | } else { | 2107 | } else { |
2097 | intel_crtc->dspaddr_offset = linear_offset; | 2108 | intel_crtc->dspaddr_offset = linear_offset; |
@@ -2182,9 +2193,9 @@ static int ironlake_update_plane(struct drm_crtc *crtc, | |||
2182 | 2193 | ||
2183 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 2194 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
2184 | intel_crtc->dspaddr_offset = | 2195 | intel_crtc->dspaddr_offset = |
2185 | intel_gen4_compute_offset_xtiled(&x, &y, | 2196 | intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, |
2186 | fb->bits_per_pixel / 8, | 2197 | fb->bits_per_pixel / 8, |
2187 | fb->pitches[0]); | 2198 | fb->pitches[0]); |
2188 | linear_offset -= intel_crtc->dspaddr_offset; | 2199 | linear_offset -= intel_crtc->dspaddr_offset; |
2189 | 2200 | ||
2190 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", | 2201 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 005a91f1f8f5..cba02619ec0f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -649,9 +649,10 @@ extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, | |||
649 | extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe, | 649 | extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe, |
650 | struct drm_display_mode *mode); | 650 | struct drm_display_mode *mode); |
651 | 651 | ||
652 | extern unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y, | 652 | extern unsigned long intel_gen4_compute_page_offset(int *x, int *y, |
653 | unsigned int bpp, | 653 | unsigned int tiling_mode, |
654 | unsigned int pitch); | 654 | unsigned int bpp, |
655 | unsigned int pitch); | ||
655 | 656 | ||
656 | extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | 657 | extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, |
657 | struct drm_file *file_priv); | 658 | struct drm_file *file_priv); |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index d086e48a831a..1b6eb76beb7c 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -122,8 +122,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
122 | 122 | ||
123 | linear_offset = y * fb->pitches[0] + x * pixel_size; | 123 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
124 | sprsurf_offset = | 124 | sprsurf_offset = |
125 | intel_gen4_compute_offset_xtiled(&x, &y, | 125 | intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, |
126 | pixel_size, fb->pitches[0]); | 126 | pixel_size, fb->pitches[0]); |
127 | linear_offset -= sprsurf_offset; | 127 | linear_offset -= sprsurf_offset; |
128 | 128 | ||
129 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 129 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
@@ -295,8 +295,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
295 | 295 | ||
296 | linear_offset = y * fb->pitches[0] + x * pixel_size; | 296 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
297 | dvssurf_offset = | 297 | dvssurf_offset = |
298 | intel_gen4_compute_offset_xtiled(&x, &y, | 298 | intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, |
299 | pixel_size, fb->pitches[0]); | 299 | pixel_size, fb->pitches[0]); |
300 | linear_offset -= dvssurf_offset; | 300 | linear_offset -= dvssurf_offset; |
301 | 301 | ||
302 | if (obj->tiling_mode != I915_TILING_NONE) | 302 | if (obj->tiling_mode != I915_TILING_NONE) |