drm/i915: Fix PIPE_CONTROL command on Sandybridge
authorZhenyu Wang <zhenyuw@linux.intel.com>
Thu, 27 May 2010 02:26:42 +0000 (10:26 +0800)
committerEric Anholt <eric@anholt.net>
Fri, 28 May 2010 18:11:23 +0000 (11:11 -0700)
Sandybridge(Gen6) has new format for PIPE_CONTROL command,
the flush and post-op control are in dword 1 now. This
changes command length field for difference between Ironlake
and Sandybridge.

I tried to test this with noop request and issue PIPE_CONTROL
command for each sequence and track notify interrupts, which
seems work fine. Hopefully we don't need workaround like on
Ironlake for Sandybridge.

Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/intel_ringbuffer.c

index f6b84fe8099a7cfb14386e284da5c6b6b18b057f..cea4f1a8709ec775913fda1bab17d7868c944be4 100644 (file)
@@ -213,7 +213,7 @@ static int init_render_ring(struct drm_device *dev,
 #define PIPE_CONTROL_FLUSH(addr)                                       \
 do {                                                                   \
        OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |          \
-                PIPE_CONTROL_DEPTH_STALL);                             \
+                PIPE_CONTROL_DEPTH_STALL | 2);                         \
        OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT);                       \
        OUT_RING(0);                                                    \
        OUT_RING(0);                                                    \
@@ -236,7 +236,19 @@ render_ring_add_request(struct drm_device *dev,
        u32 seqno;
        drm_i915_private_t *dev_priv = dev->dev_private;
        seqno = intel_ring_get_seqno(dev, ring);
-       if (HAS_PIPE_CONTROL(dev)) {
+
+       if (IS_GEN6(dev)) {
+               BEGIN_LP_RING(6);
+               OUT_RING(GFX_OP_PIPE_CONTROL | 3);
+               OUT_RING(PIPE_CONTROL_QW_WRITE |
+                        PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
+                        PIPE_CONTROL_NOTIFY);
+               OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+               OUT_RING(seqno);
+               OUT_RING(0);
+               OUT_RING(0);
+               ADVANCE_LP_RING();
+       } else if (HAS_PIPE_CONTROL(dev)) {
                u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
 
                /*