diff options
author | Keith Packard <keithp@keithp.com> | 2008-10-14 20:20:35 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2008-10-17 17:10:53 -0400 |
commit | 50aa253d820ad4577e2231202f2c8fd89f9dc4e6 (patch) | |
tree | 2357e6f184456b44a9c38f57d5f2f16345219ba5 /drivers/gpu/drm | |
parent | 0cdad7e88a23910a911a3339ff2d70f8f952d7b8 (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/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 37 |
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 | ||