summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@jsg.id.au>2013-03-09 13:31:55 +1100
committerJonathan Gray <jsg@jsg.id.au>2013-03-09 13:47:15 +1100
commit07bd0afb1d46fb6c48eda127580c44e060f7162d (patch)
treeea517cb72f310690abc65824a44d0ad5e14756ce
parentd576a5fc8c0d59545c71c2ceb7bddccb6afbad92 (diff)
add support for setting the addressing mode
-rw-r--r--sys/dev/pci/drm/i915_dma.c3
-rw-r--r--sys/dev/pci/drm/i915_drv.c2
-rw-r--r--sys/dev/pci/drm/i915_drv.h2
-rw-r--r--sys/dev/pci/drm/i915_gem_execbuffer.c42
4 files changed, 49 insertions, 0 deletions
diff --git a/sys/dev/pci/drm/i915_dma.c b/sys/dev/pci/drm/i915_dma.c
index 2a6ffcc250e..1d29dddda55 100644
--- a/sys/dev/pci/drm/i915_dma.c
+++ b/sys/dev/pci/drm/i915_dma.c
@@ -105,6 +105,9 @@ i915_getparam(struct inteldrm_softc *dev_priv, void *data)
return EINVAL;
#endif
break;
+ case I915_PARAM_HAS_EXEC_CONSTANTS:
+ value = INTEL_INFO(dev)->gen >= 4;
+ break;
case I915_PARAM_HAS_GEN7_SOL_RESET:
value = 1;
break;
diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c
index 68e98e78d07..18d88f03c55 100644
--- a/sys/dev/pci/drm/i915_drv.c
+++ b/sys/dev/pci/drm/i915_drv.c
@@ -993,6 +993,8 @@ inteldrm_attach(struct device *parent, struct device *self, void *aux)
}
}
+ dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
+
/* Old X drivers will take 0-2 for front, back, depth buffers */
if (!drm_core_check_feature(dev, DRIVER_MODESET))
dev_priv->fence_reg_start = 3;
diff --git a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h
index 01ce5f93dca..175aa3d5628 100644
--- a/sys/dev/pci/drm/i915_drv.h
+++ b/sys/dev/pci/drm/i915_drv.h
@@ -715,6 +715,8 @@ struct inteldrm_softc {
const struct intel_device_info *info;
+ int relative_constants_mode;
+
struct sdvo_device_mapping sdvo_mappings[2];
/* indicate whether the LVDS_BORDER should be enabled or not */
unsigned int lvds_border_bits;
diff --git a/sys/dev/pci/drm/i915_gem_execbuffer.c b/sys/dev/pci/drm/i915_gem_execbuffer.c
index a6dfcc5f6ec..793fb78b6d5 100644
--- a/sys/dev/pci/drm/i915_gem_execbuffer.c
+++ b/sys/dev/pci/drm/i915_gem_execbuffer.c
@@ -246,6 +246,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
uint32_t reloc_index;
uint32_t flags;
uint32_t exec_start, exec_len;
+ uint32_t mask;
+ int mode;
/*
* Check for valid execbuffer offset. We can do this early because
@@ -295,6 +297,31 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
return (EINVAL);
}
+ 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:
+ case I915_EXEC_CONSTANTS_REL_SURFACE:
+ if (ring == &dev_priv->rings[RCS] &&
+ mode != dev_priv->relative_constants_mode) {
+ if (INTEL_INFO(dev)->gen < 4)
+ return EINVAL;
+
+ if (INTEL_INFO(dev)->gen > 5 &&
+ mode == I915_EXEC_CONSTANTS_REL_SURFACE)
+ return EINVAL;
+
+ /* The HW changed the meaning on this bit on gen6 */
+ if (INTEL_INFO(dev)->gen >= 6)
+ mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE;
+ }
+ break;
+ default:
+ DRM_DEBUG("execbuf with unknown constants: %d\n", mode);
+ return EINVAL;
+ }
+
/* Copy in the exec list from userland, check for overflow */
oflow = SIZE_MAX / args->buffer_count;
if (oflow < sizeof(*exec_list) || oflow < sizeof(*object_list))
@@ -415,6 +442,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
if (ret)
goto err;
+ if (ring == &dev_priv->rings[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)