aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-10-14 20:20:35 -0400
committerDave Airlie <airlied@linux.ie>2008-10-17 17:10:53 -0400
commit50aa253d820ad4577e2231202f2c8fd89f9dc4e6 (patch)
tree2357e6f184456b44a9c38f57d5f2f16345219ba5 /drivers/gpu
parent0cdad7e88a23910a911a3339ff2d70f8f952d7b8 (diff)
i915: Fix up ring initialization to cover G45 oddities
G45 appears quite sensitive to ring initialization register writes, sometimes leaving the HEAD register with the START register contents. Check to make sure HEAD is reset correctly when START is written, and fix it up, screaming loudly. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a31ee3202f17..94b9bdce0c75 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2350,6 +2350,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
2350 struct drm_gem_object *obj; 2350 struct drm_gem_object *obj;
2351 struct drm_i915_gem_object *obj_priv; 2351 struct drm_i915_gem_object *obj_priv;
2352 int ret; 2352 int ret;
2353 u32 head;
2353 2354
2354 ret = i915_gem_init_hws(dev); 2355 ret = i915_gem_init_hws(dev);
2355 if (ret != 0) 2356 if (ret != 0)
@@ -2390,17 +2391,49 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
2390 2391
2391 /* Stop the ring if it's running. */ 2392 /* Stop the ring if it's running. */
2392 I915_WRITE(PRB0_CTL, 0); 2393 I915_WRITE(PRB0_CTL, 0);
2393 I915_WRITE(PRB0_HEAD, 0);
2394 I915_WRITE(PRB0_TAIL, 0); 2394 I915_WRITE(PRB0_TAIL, 0);
2395 I915_WRITE(PRB0_START, 0); 2395 I915_WRITE(PRB0_HEAD, 0);
2396 2396
2397 /* Initialize the ring. */ 2397 /* Initialize the ring. */
2398 I915_WRITE(PRB0_START, obj_priv->gtt_offset); 2398 I915_WRITE(PRB0_START, obj_priv->gtt_offset);
2399 head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
2400
2401 /* G45 ring initialization fails to reset head to zero */
2402 if (head != 0) {
2403 DRM_ERROR("Ring head not reset to zero "
2404 "ctl %08x head %08x tail %08x start %08x\n",
2405 I915_READ(PRB0_CTL),
2406 I915_READ(PRB0_HEAD),
2407 I915_READ(PRB0_TAIL),
2408 I915_READ(PRB0_START));
2409 I915_WRITE(PRB0_HEAD, 0);
2410
2411 DRM_ERROR("Ring head forced to zero "
2412 "ctl %08x head %08x tail %08x start %08x\n",
2413 I915_READ(PRB0_CTL),
2414 I915_READ(PRB0_HEAD),
2415 I915_READ(PRB0_TAIL),
2416 I915_READ(PRB0_START));
2417 }
2418
2399 I915_WRITE(PRB0_CTL, 2419 I915_WRITE(PRB0_CTL,
2400 ((obj->size - 4096) & RING_NR_PAGES) | 2420 ((obj->size - 4096) & RING_NR_PAGES) |
2401 RING_NO_REPORT | 2421 RING_NO_REPORT |
2402 RING_VALID); 2422 RING_VALID);
2403 2423
2424 head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
2425
2426 /* If the head is still not zero, the ring is dead */
2427 if (head != 0) {
2428 DRM_ERROR("Ring initialization failed "
2429 "ctl %08x head %08x tail %08x start %08x\n",
2430 I915_READ(PRB0_CTL),
2431 I915_READ(PRB0_HEAD),
2432 I915_READ(PRB0_TAIL),
2433 I915_READ(PRB0_START));
2434 return -EIO;
2435 }
2436
2404 /* Update our cache of the ring state */ 2437 /* Update our cache of the ring state */
2405 i915_kernel_lost_context(dev); 2438 i915_kernel_lost_context(dev);
2406 2439