| From 68449b3aaa8c55dd83dc7f21f0c2496238961987 Mon Sep 17 00:00:00 2001 |
| From: Rodrigo Vivi <rodrigo.vivi@gmail.com> |
| Date: Thu, 6 Jun 2013 16:58:16 -0300 |
| Subject: drm/i915: WA: FBC Render Nuke. |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| WaFbcNukeOn3DBlt for IVB, HSW. |
| |
| According BSPec: "Workaround: Do not enable Render Command Streamer tracking for FBC. |
| Instead insert a LRI to address 0x50380 with data 0x00000004 after the PIPE_CONTROL that |
| follows each render submission." |
| |
| v2: Chris noticed that flush_domains check was missing here and also suggested to do |
| LRI only when fbc is enabled. To avoid do a I915_READ on every flush lets use the |
| module parameter check. |
| |
| v3: Adding Wa name as Damien suggested. |
| |
| v4: Ville noticed VLV doesn't support fbc at all and comment came wrong from spec. |
| |
| v5: Ville noticed than on blt a Cache Clean LRI should be used instead the Nuke one. |
| |
| v6: Check for flush domain on blt (by Ville). |
| Check for scanout dirty (by Chris). |
| |
| v7: Apply proper fbc_dirty implemented by Chris. |
| |
| v8: remove unused variables. |
| |
| Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Cc: Chris Wilson <chris@chris-wilson.co.uk> |
| Signed-off-by: Rodrigo Vivi <rodrigo.vivi@gmail.com> |
| Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit fd3da6c95b6d865446fa9b29df6edff4343e385a) |
| Signed-off-by: Darren Hart <dvhart@linux.intel.com> |
| --- |
| drivers/gpu/drm/i915/i915_reg.h | 4 ++++ |
| drivers/gpu/drm/i915/intel_pm.c | 2 +- |
| drivers/gpu/drm/i915/intel_ringbuffer.c | 29 +++++++++++++++++++++++++++++ |
| 3 files changed, 34 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/gpu/drm/i915/i915_reg.h |
| +++ b/drivers/gpu/drm/i915/i915_reg.h |
| @@ -1023,6 +1023,10 @@ |
| #define IPS_CTL 0x43408 |
| #define IPS_ENABLE (1 << 31) |
| |
| +#define MSG_FBC_REND_STATE 0x50380 |
| +#define FBC_REND_NUKE (1<<2) |
| +#define FBC_REND_CACHE_CLEAN (1<<1) |
| + |
| #define _HSW_PIPE_SLICE_CHICKEN_1_A 0x420B0 |
| #define _HSW_PIPE_SLICE_CHICKEN_1_B 0x420B4 |
| #define HSW_BYPASS_FBC_QUEUE (1<<22) |
| --- a/drivers/gpu/drm/i915/intel_pm.c |
| +++ b/drivers/gpu/drm/i915/intel_pm.c |
| @@ -274,7 +274,7 @@ static void gen7_enable_fbc(struct drm_c |
| struct drm_i915_gem_object *obj = intel_fb->obj; |
| struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| |
| - I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID); |
| + I915_WRITE(IVB_FBC_RT_BASE, obj->gtt_offset); |
| |
| I915_WRITE(ILK_DPFC_CONTROL, DPFC_CTL_EN | DPFC_CTL_LIMIT_1X | |
| IVB_DPFC_CTL_FENCE_EN | |
| --- a/drivers/gpu/drm/i915/intel_ringbuffer.c |
| +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c |
| @@ -280,6 +280,27 @@ gen7_render_ring_cs_stall_wa(struct inte |
| return 0; |
| } |
| |
| +static int gen7_ring_fbc_flush(struct intel_ring_buffer *ring, u32 value) |
| +{ |
| + int ret; |
| + |
| + if (!ring->fbc_dirty) |
| + return 0; |
| + |
| + ret = intel_ring_begin(ring, 4); |
| + if (ret) |
| + return ret; |
| + intel_ring_emit(ring, MI_NOOP); |
| + /* WaFbcNukeOn3DBlt:ivb/hsw */ |
| + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); |
| + intel_ring_emit(ring, MSG_FBC_REND_STATE); |
| + intel_ring_emit(ring, value); |
| + intel_ring_advance(ring); |
| + |
| + ring->fbc_dirty = false; |
| + return 0; |
| +} |
| + |
| static int |
| gen7_render_ring_flush(struct intel_ring_buffer *ring, |
| u32 invalidate_domains, u32 flush_domains) |
| @@ -339,6 +360,9 @@ gen7_render_ring_flush(struct intel_ring |
| intel_ring_emit(ring, 0); |
| intel_ring_advance(ring); |
| |
| + if (flush_domains) |
| + return gen7_ring_fbc_flush(ring, FBC_REND_NUKE); |
| + |
| return 0; |
| } |
| |
| @@ -1706,6 +1730,7 @@ gen6_ring_dispatch_execbuffer(struct int |
| static int gen6_ring_flush(struct intel_ring_buffer *ring, |
| u32 invalidate, u32 flush) |
| { |
| + struct drm_device *dev = ring->dev; |
| uint32_t cmd; |
| int ret; |
| |
| @@ -1728,6 +1753,10 @@ static int gen6_ring_flush(struct intel_ |
| intel_ring_emit(ring, 0); |
| intel_ring_emit(ring, MI_NOOP); |
| intel_ring_advance(ring); |
| + |
| + if (IS_GEN7(dev) && flush) |
| + return gen7_ring_fbc_flush(ring, FBC_REND_CACHE_CLEAN); |
| + |
| return 0; |
| } |
| |