Skip to content

Commit

Permalink
drm/i915: Fix tiling pitch handling on 8xx.
Browse files Browse the repository at this point in the history
The pitch field is an exponent on pre-965, so we were rejecting buffers
on 8xx that we shouldn't have.  915 got lucky in that the largest legal
value happened to match (8KB / 512 = 0x10), but 8xx has a smaller tile width.
Additionally, we programmed that bad value into the register on 8xx, so the
only pitch that would work correctly was 4096 (512-1023 pixels), while others
would probably give bad rendering or hangs.

Signed-off-by: Eric Anholt <eric@anholt.net>

fd.o bug #20473.
  • Loading branch information
Eric Anholt committed May 27, 2009
1 parent cd86a53 commit e76a16d
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 6 deletions.
6 changes: 4 additions & 2 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,8 +2128,10 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
return;
}

pitch_val = (obj_priv->stride / 128) - 1;
WARN_ON(pitch_val & ~0x0000000f);
pitch_val = obj_priv->stride / 128;
pitch_val = ffs(pitch_val) - 1;
WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);

val = obj_priv->gtt_offset;
if (obj_priv->tiling_mode == I915_TILING_Y)
val |= 1 << I830_FENCE_TILING_Y_SHIFT;
Expand Down
14 changes: 11 additions & 3 deletions drivers/gpu/drm/i915/i915_gem_tiling.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,8 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
if (tiling_mode == I915_TILING_NONE)
return true;

if (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))
if (!IS_I9XX(dev) ||
(tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)))
tile_width = 128;
else
tile_width = 512;
Expand All @@ -225,11 +226,18 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
if (stride / 128 > I965_FENCE_MAX_PITCH_VAL)
return false;
} else if (IS_I9XX(dev)) {
if (stride / tile_width > I830_FENCE_MAX_PITCH_VAL ||
uint32_t pitch_val = ffs(stride / tile_width) - 1;

/* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB)
* instead of 4 (2KB) on 945s.
*/
if (pitch_val > I915_FENCE_MAX_PITCH_VAL ||
size > (I830_FENCE_MAX_SIZE_VAL << 20))
return false;
} else {
if (stride / 128 > I830_FENCE_MAX_PITCH_VAL ||
uint32_t pitch_val = ffs(stride / tile_width) - 1;

if (pitch_val > I830_FENCE_MAX_PITCH_VAL ||
size > (I830_FENCE_MAX_SIZE_VAL << 19))
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@
#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
#define I830_FENCE_PITCH_SHIFT 4
#define I830_FENCE_REG_VALID (1<<0)
#define I830_FENCE_MAX_PITCH_VAL 0x10
#define I915_FENCE_MAX_PITCH_VAL 0x10
#define I830_FENCE_MAX_PITCH_VAL 6
#define I830_FENCE_MAX_SIZE_VAL (1<<8)

#define I915_FENCE_START_MASK 0x0ff00000
Expand Down

0 comments on commit e76a16d

Please sign in to comment.