Skip to content

Commit

Permalink
drm/i915: Actually respect DSPSURF alignment restrictions
Browse files Browse the repository at this point in the history
Currently intel_gen4_compute_page_offset() simply picks the closest
page boundary below the linear offset. That however may not be suitably
aligned to satisfy any hardware specific restrictions. So let's make
sure the page boundary we choose is properly aligned.

Also to play it a bit safer lets split the remaining linear offset into
x and y values instead of just x. This should make no difference for
most platforms since we convert the x and y offsets back into a linear
offset before feeding them to the hardware. HSW+ are different however
and use x and y offsets even with linear buffers, so they might have
trouble if either the x or y get too big.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Ville Syrjälä authored and Daniel Vetter committed Jun 15, 2015
1 parent 7cd3527 commit 4e9a86b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 18 deletions.
37 changes: 23 additions & 14 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2329,6 +2329,18 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, struct drm_framebuffer *fb,
return 0;
}

static unsigned int intel_linear_alignment(struct drm_i915_private *dev_priv)
{
if (INTEL_INFO(dev_priv)->gen >= 9)
return 256 * 1024;
else if (IS_BROADWATER(dev_priv) || IS_CRESTLINE(dev_priv))
return 128 * 1024;
else if (INTEL_INFO(dev_priv)->gen >= 4)
return 4 * 1024;
else
return 64 * 1024;
}

int
intel_pin_and_fence_fb_obj(struct drm_plane *plane,
struct drm_framebuffer *fb,
Expand All @@ -2346,14 +2358,7 @@ intel_pin_and_fence_fb_obj(struct drm_plane *plane,

switch (fb->modifier[0]) {
case DRM_FORMAT_MOD_NONE:
if (INTEL_INFO(dev)->gen >= 9)
alignment = 256 * 1024;
else if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
alignment = 128 * 1024;
else if (INTEL_INFO(dev)->gen >= 4)
alignment = 4 * 1024;
else
alignment = 64 * 1024;
alignment = intel_linear_alignment(dev_priv);
break;
case I915_FORMAT_MOD_X_TILED:
if (INTEL_INFO(dev)->gen >= 9)
Expand Down Expand Up @@ -2443,7 +2448,8 @@ static void intel_unpin_fb_obj(struct drm_framebuffer *fb,

/* 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_page_offset(int *x, int *y,
unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
int *x, int *y,
unsigned int tiling_mode,
unsigned int cpp,
unsigned int pitch)
Expand All @@ -2459,12 +2465,13 @@ unsigned long intel_gen4_compute_page_offset(int *x, int *y,

return tile_rows * pitch * 8 + tiles * 4096;
} else {
unsigned int alignment = intel_linear_alignment(dev_priv) - 1;
unsigned int offset;

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

Expand Down Expand Up @@ -2733,7 +2740,8 @@ static void i9xx_update_primary_plane(struct drm_crtc *crtc,

if (INTEL_INFO(dev)->gen >= 4) {
intel_crtc->dspaddr_offset =
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
intel_gen4_compute_page_offset(dev_priv,
&x, &y, obj->tiling_mode,
pixel_size,
fb->pitches[0]);
linear_offset -= intel_crtc->dspaddr_offset;
Expand Down Expand Up @@ -2834,7 +2842,8 @@ static void ironlake_update_primary_plane(struct drm_crtc *crtc,

linear_offset = y * fb->pitches[0] + x * pixel_size;
intel_crtc->dspaddr_offset =
intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode,
intel_gen4_compute_page_offset(dev_priv,
&x, &y, obj->tiling_mode,
pixel_size,
fb->pitches[0]);
linear_offset -= intel_crtc->dspaddr_offset;
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,8 @@ 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_gen4_compute_page_offset(int *x, int *y,
unsigned long intel_gen4_compute_page_offset(struct drm_i915_private *dev_priv,
int *x, int *y,
unsigned int tiling_mode,
unsigned int bpp,
unsigned int pitch);
Expand Down
9 changes: 6 additions & 3 deletions drivers/gpu/drm/i915/intel_sprite.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ vlv_update_plane(struct drm_plane *dplane, struct drm_crtc *crtc,
crtc_h--;

linear_offset = y * fb->pitches[0] + x * pixel_size;
sprsurf_offset = intel_gen4_compute_page_offset(&x, &y,
sprsurf_offset = intel_gen4_compute_page_offset(dev_priv,
&x, &y,
obj->tiling_mode,
pixel_size,
fb->pitches[0]);
Expand Down Expand Up @@ -546,7 +547,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,

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

Expand Down Expand Up @@ -682,7 +684,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,

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

Expand Down

0 comments on commit 4e9a86b

Please sign in to comment.