summaryrefslogtreecommitdiff
path: root/shared-core/i915_dma.c
diff options
context:
space:
mode:
authorAlan Hourihane <alanh@tungstengraphics.com>2006-08-08 15:05:54 -0700
committerEric Anholt <anholt@FreeBSD.org>2006-08-08 15:05:54 -0700
commit48cb9aceed782a4e9c557f30429e65f845dd777d (patch)
tree4848dc90ea0f50265f4c2ddd4f0161163efbf54c /shared-core/i915_dma.c
parente524028630013bb0f436bcdca0396289745843cf (diff)
Add support for Intel i965G chipsets.
This is a patch prepared by Guangdeng Liao based off of Tungsten Graphics's final code drop.
Diffstat (limited to 'shared-core/i915_dma.c')
-rw-r--r--shared-core/i915_dma.c46
1 files changed, 34 insertions, 12 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index ae0f55a2..39f7b407 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -31,6 +31,12 @@
#include "i915_drm.h"
#include "i915_drv.h"
+#define IS_I965G(dev) (dev->pdev->device == 0x2972 || \
+ dev->pdev->device == 0x2982 || \
+ dev->pdev->device == 0x2992 || \
+ dev->pdev->device == 0x29A2)
+
+
/* Really want an OS-independent resettable timer. Would like to have
* this loop run for (eg) 3 sec, but have the timer reset every time
* the head pointer changes, so that EBUSY only happens if the ring
@@ -347,14 +353,15 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
return DRM_ERR(EINVAL);
- BEGIN_LP_RING(((dwords+1)&~1));
+ BEGIN_LP_RING((dwords+1)&~1);
for (i = 0; i < dwords;) {
int cmd, sz;
- if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
- return DRM_ERR(EINVAL);
+ if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) {
+ return DRM_ERR(EINVAL);
+ }
if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
return DRM_ERR(EINVAL);
@@ -395,25 +402,40 @@ static int i915_emit_box(drm_device_t * dev,
return DRM_ERR(EINVAL);
}
- BEGIN_LP_RING(6);
- OUT_RING(GFX_OP_DRAWRECT_INFO);
- OUT_RING(DR1);
- OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
- OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
- OUT_RING(DR4);
- OUT_RING(0);
- ADVANCE_LP_RING();
+ if (IS_I965G(dev)) {
+ BEGIN_LP_RING(4);
+ OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
+ OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+ OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+ OUT_RING(DR4);
+ ADVANCE_LP_RING();
+ } else {
+ BEGIN_LP_RING(6);
+ OUT_RING(GFX_OP_DRAWRECT_INFO);
+ OUT_RING(DR1);
+ OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
+ OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
+ OUT_RING(DR4);
+ OUT_RING(0);
+ ADVANCE_LP_RING();
+ }
return 0;
}
+/* XXX: Emitting the counter should really be moved to part of the IRQ
+ * emit. For now, do it in both places:
+ */
static void i915_emit_breadcrumb(drm_device_t *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+ dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
+
+ if (dev_priv->counter > 0x7FFFFFFFUL)
+ dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
BEGIN_LP_RING(4);
OUT_RING(CMD_STORE_DWORD_IDX);