Merge branch 'drm-core-next' of git://people.freedesktop.org/~airlied/linux
[pandora-kernel.git] / drivers / gpu / drm / i915 / i915_gem_execbuffer.c
index b9da890..65e1f00 100644 (file)
@@ -970,6 +970,31 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
        }
 }
 
+static int
+i915_reset_gen7_sol_offsets(struct drm_device *dev,
+                           struct intel_ring_buffer *ring)
+{
+       drm_i915_private_t *dev_priv = dev->dev_private;
+       int ret, i;
+
+       if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS])
+               return 0;
+
+       ret = intel_ring_begin(ring, 4 * 3);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < 4; i++) {
+               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i));
+               intel_ring_emit(ring, 0);
+       }
+
+       intel_ring_advance(ring);
+
+       return 0;
+}
+
 static int
 i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                       struct drm_file *file,
@@ -984,6 +1009,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        struct intel_ring_buffer *ring;
        u32 exec_start, exec_len;
        u32 seqno;
+       u32 mask;
        int ret, mode, i;
 
        if (!i915_gem_check_execbuffer(args)) {
@@ -1021,6 +1047,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
        }
 
        mode = args->flags & I915_EXEC_CONSTANTS_MASK;
+       mask = I915_EXEC_CONSTANTS_MASK;
        switch (mode) {
        case I915_EXEC_CONSTANTS_REL_GENERAL:
        case I915_EXEC_CONSTANTS_ABSOLUTE:
@@ -1034,18 +1061,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                            mode == I915_EXEC_CONSTANTS_REL_SURFACE)
                                return -EINVAL;
 
-                       ret = intel_ring_begin(ring, 4);
-                       if (ret)
-                               return ret;
-
-                       intel_ring_emit(ring, MI_NOOP);
-                       intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-                       intel_ring_emit(ring, INSTPM);
-                       intel_ring_emit(ring,
-                                       I915_EXEC_CONSTANTS_MASK << 16 | mode);
-                       intel_ring_advance(ring);
-
-                       dev_priv->relative_constants_mode = mode;
+                       /* The HW changed the meaning on this bit on gen6 */
+                       if (INTEL_INFO(dev)->gen >= 6)
+                               mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
                }
                break;
        default:
@@ -1176,6 +1194,27 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                }
        }
 
+       if (ring == &dev_priv->ring[RCS] &&
+           mode != dev_priv->relative_constants_mode) {
+               ret = intel_ring_begin(ring, 4);
+               if (ret)
+                               goto err;
+
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+               intel_ring_emit(ring, INSTPM);
+               intel_ring_emit(ring, mask << 16 | mode);
+               intel_ring_advance(ring);
+
+               dev_priv->relative_constants_mode = mode;
+       }
+
+       if (args->flags & I915_EXEC_GEN7_SOL_RESET) {
+               ret = i915_reset_gen7_sol_offsets(dev, ring);
+               if (ret)
+                       goto err;
+       }
+
        trace_i915_gem_ring_dispatch(ring, seqno);
 
        exec_start = batch_obj->gtt_offset + args->batch_start_offset;