|
@@ -31,6 +31,11 @@
|
|
#include "i915_drm.h"
|
|
#include "i915_drm.h"
|
|
#include "i915_drv.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
|
|
/* 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
|
|
* 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
|
|
* the head pointer changes, so that EBUSY only happens if the ring
|
|
@@ -347,7 +352,7 @@ static int i915_emit_cmds(drm_device_t * dev, int __user * buffer, int dwords)
|
|
if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
|
|
if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8)
|
|
return DRM_ERR(EINVAL);
|
|
return DRM_ERR(EINVAL);
|
|
|
|
|
|
- BEGIN_LP_RING(((dwords+1)&~1));
|
|
|
|
|
|
+ BEGIN_LP_RING((dwords+1)&~1);
|
|
|
|
|
|
for (i = 0; i < dwords;) {
|
|
for (i = 0; i < dwords;) {
|
|
int cmd, sz;
|
|
int cmd, sz;
|
|
@@ -395,24 +400,40 @@ static int i915_emit_box(drm_device_t * dev,
|
|
return DRM_ERR(EINVAL);
|
|
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;
|
|
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)
|
|
static void i915_emit_breadcrumb(drm_device_t *dev)
|
|
{
|
|
{
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
RING_LOCALS;
|
|
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);
|
|
BEGIN_LP_RING(4);
|
|
OUT_RING(CMD_STORE_DWORD_IDX);
|
|
OUT_RING(CMD_STORE_DWORD_IDX);
|