From 48cb9aceed782a4e9c557f30429e65f845dd777d Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 8 Aug 2006 15:05:54 -0700 Subject: Add support for Intel i965G chipsets. This is a patch prepared by Guangdeng Liao based off of Tungsten Graphics's final code drop. --- shared-core/i915_dma.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'shared-core/i915_dma.c') 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); -- cgit v1.2.3