diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-05 06:17:30 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-07-05 07:36:01 -0400 |
commit | c2c75131244507c93f812862fdbd4f3a37139401 (patch) | |
tree | 068e1aae4099aafe1a31948e382bf882af43d378 /drivers/gpu/drm/i915/intel_display.c | |
parent | e506a0c6381f180858d2e343c3ed5c0bde8e84ba (diff) |
drm/i915: adjust framebuffer base address on gen4+
The tileoffset register only supports a limited offset in x/y of 4096,
so for giant screen configuration with a shared fb we wrap around.
Fix this by computing a linear offset in tiles (pages) and only use
the tileoffset register to offset within the tile.
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f8c24123dde0..ca1068bc892f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1973,6 +1973,22 @@ void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) | |||
1973 | i915_gem_object_unpin(obj); | 1973 | i915_gem_object_unpin(obj); |
1974 | } | 1974 | } |
1975 | 1975 | ||
1976 | /* Computes the linear offset to the base tile and adjusts x, y. bytes per pixel | ||
1977 | * is assumed to be a power-of-two. */ | ||
1978 | static unsigned long gen4_compute_dspaddr_offset_xtiled(int *x, int *y, | ||
1979 | unsigned int bpp, | ||
1980 | unsigned int pitch) | ||
1981 | { | ||
1982 | int tile_rows, tiles; | ||
1983 | |||
1984 | tile_rows = *y / 8; | ||
1985 | *y %= 8; | ||
1986 | tiles = *x / (512/bpp); | ||
1987 | *x %= 512/bpp; | ||
1988 | |||
1989 | return tile_rows * pitch * 8 + tiles * 4096; | ||
1990 | } | ||
1991 | |||
1976 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 1992 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, |
1977 | int x, int y) | 1993 | int x, int y) |
1978 | { | 1994 | { |
@@ -2031,16 +2047,22 @@ static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
2031 | 2047 | ||
2032 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 2048 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
2033 | 2049 | ||
2034 | if (INTEL_INFO(dev)->gen >= 4) | 2050 | if (INTEL_INFO(dev)->gen >= 4) { |
2035 | intel_crtc->dspaddr_offset = 0; | 2051 | intel_crtc->dspaddr_offset = |
2036 | else | 2052 | gen4_compute_dspaddr_offset_xtiled(&x, &y, |
2053 | fb->bits_per_pixel / 8, | ||
2054 | fb->pitches[0]); | ||
2055 | linear_offset -= intel_crtc->dspaddr_offset; | ||
2056 | } else { | ||
2037 | intel_crtc->dspaddr_offset = linear_offset; | 2057 | intel_crtc->dspaddr_offset = linear_offset; |
2058 | } | ||
2038 | 2059 | ||
2039 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", | 2060 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", |
2040 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); | 2061 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); |
2041 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); | 2062 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
2042 | if (INTEL_INFO(dev)->gen >= 4) { | 2063 | if (INTEL_INFO(dev)->gen >= 4) { |
2043 | I915_MODIFY_DISPBASE(DSPSURF(plane), obj->gtt_offset); | 2064 | I915_MODIFY_DISPBASE(DSPSURF(plane), |
2065 | obj->gtt_offset + intel_crtc->dspaddr_offset); | ||
2044 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 2066 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
2045 | I915_WRITE(DSPLINOFF(plane), linear_offset); | 2067 | I915_WRITE(DSPLINOFF(plane), linear_offset); |
2046 | } else | 2068 | } else |
@@ -2115,12 +2137,17 @@ static int ironlake_update_plane(struct drm_crtc *crtc, | |||
2115 | I915_WRITE(reg, dspcntr); | 2137 | I915_WRITE(reg, dspcntr); |
2116 | 2138 | ||
2117 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 2139 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); |
2118 | intel_crtc->dspaddr_offset = 0; | 2140 | intel_crtc->dspaddr_offset = |
2141 | gen4_compute_dspaddr_offset_xtiled(&x, &y, | ||
2142 | fb->bits_per_pixel / 8, | ||
2143 | fb->pitches[0]); | ||
2144 | linear_offset -= intel_crtc->dspaddr_offset; | ||
2119 | 2145 | ||
2120 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", | 2146 | DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", |
2121 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); | 2147 | obj->gtt_offset, linear_offset, x, y, fb->pitches[0]); |
2122 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); | 2148 | I915_WRITE(DSPSTRIDE(plane), fb->pitches[0]); |
2123 | I915_MODIFY_DISPBASE(DSPSURF(plane), obj->gtt_offset); | 2149 | I915_MODIFY_DISPBASE(DSPSURF(plane), |
2150 | obj->gtt_offset + intel_crtc->dspaddr_offset); | ||
2124 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 2151 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
2125 | I915_WRITE(DSPLINOFF(plane), linear_offset); | 2152 | I915_WRITE(DSPLINOFF(plane), linear_offset); |
2126 | POSTING_READ(reg); | 2153 | POSTING_READ(reg); |
@@ -6299,7 +6326,9 @@ static int intel_gen4_queue_flip(struct drm_device *dev, | |||
6299 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6326 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
6300 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6327 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
6301 | intel_ring_emit(ring, fb->pitches[0]); | 6328 | intel_ring_emit(ring, fb->pitches[0]); |
6302 | intel_ring_emit(ring, obj->gtt_offset | obj->tiling_mode); | 6329 | intel_ring_emit(ring, |
6330 | (obj->gtt_offset + intel_crtc->dspaddr_offset) | | ||
6331 | obj->tiling_mode); | ||
6303 | 6332 | ||
6304 | /* XXX Enabling the panel-fitter across page-flip is so far | 6333 | /* XXX Enabling the panel-fitter across page-flip is so far |
6305 | * untested on non-native modes, so ignore it for now. | 6334 | * untested on non-native modes, so ignore it for now. |
@@ -6339,7 +6368,7 @@ static int intel_gen6_queue_flip(struct drm_device *dev, | |||
6339 | intel_ring_emit(ring, MI_DISPLAY_FLIP | | 6368 | intel_ring_emit(ring, MI_DISPLAY_FLIP | |
6340 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | 6369 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); |
6341 | intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); | 6370 | intel_ring_emit(ring, fb->pitches[0] | obj->tiling_mode); |
6342 | intel_ring_emit(ring, obj->gtt_offset); | 6371 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
6343 | 6372 | ||
6344 | /* Contrary to the suggestions in the documentation, | 6373 | /* Contrary to the suggestions in the documentation, |
6345 | * "Enable Panel Fitter" does not seem to be required when page | 6374 | * "Enable Panel Fitter" does not seem to be required when page |
@@ -6402,7 +6431,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
6402 | 6431 | ||
6403 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); | 6432 | intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); |
6404 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); | 6433 | intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); |
6405 | intel_ring_emit(ring, (obj->gtt_offset)); | 6434 | intel_ring_emit(ring, obj->gtt_offset + intel_crtc->dspaddr_offset); |
6406 | intel_ring_emit(ring, (MI_NOOP)); | 6435 | intel_ring_emit(ring, (MI_NOOP)); |
6407 | intel_ring_advance(ring); | 6436 | intel_ring_advance(ring); |
6408 | return 0; | 6437 | return 0; |