diff options
-rw-r--r-- | shared-core/drm_pciids.txt | 4 | ||||
-rw-r--r-- | shared-core/i915_dma.c | 46 | ||||
-rw-r--r-- | shared-core/i915_drm.h | 6 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 10 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 32 |
5 files changed, 71 insertions, 27 deletions
diff --git a/shared-core/drm_pciids.txt b/shared-core/drm_pciids.txt index e4415c16..9ef2c001 100644 --- a/shared-core/drm_pciids.txt +++ b/shared-core/drm_pciids.txt @@ -271,6 +271,10 @@ 0x8086 0x2592 0 "Intel i915GM" 0x8086 0x2772 0 "Intel i945G" 0x8086 0x27A2 0 "Intel i945GM" +0x8086 0x2972 0 "Intel i946GZ" +0x8086 0x2982 0 "Intel i965G" +0x8086 0x2992 0 "Intel i965Q" +0x8086 0x29A2 0 "Intel i965G" [imagine] 0x105d 0x2309 IMAGINE_128 "Imagine 128" 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); diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h index 999b567c..41acd4e6 100644 --- a/shared-core/i915_drm.h +++ b/shared-core/i915_drm.h @@ -98,6 +98,12 @@ typedef struct _drm_i915_sarea { int rotated_size; int rotated_pitch; int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; } drm_i915_sarea_t; /* Flags for perf_boxes diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 0c3281d4..550e386f 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -146,9 +146,9 @@ extern void i915_mem_release(drm_device_t * dev, #define BEGIN_LP_RING(n) do { \ if (I915_VERBOSE) \ DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \ - n, __FUNCTION__); \ - if (dev_priv->ring.space < n*4) \ - i915_wait_ring(dev, n*4, __FUNCTION__); \ + (n), __FUNCTION__); \ + if (dev_priv->ring.space < (n)*4) \ + i915_wait_ring(dev, (n)*4, __FUNCTION__); \ outcount = 0; \ outring = dev_priv->ring.tail; \ ringmask = dev_priv->ring.tail_mask; \ @@ -157,7 +157,7 @@ extern void i915_mem_release(drm_device_t * dev, #define OUT_RING(n) do { \ if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ + *(volatile unsigned int *)(virt + outring) = (n); \ outcount++; \ outring += 4; \ outring &= ringmask; \ @@ -254,6 +254,8 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); #define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) #define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) +#define GFX_OP_DRAWRECT_INFO_I965 ((0x7900<<16)|0x2) + #define MI_BATCH_BUFFER ((0x30<<23)|1) #define MI_BATCH_BUFFER_START (0x31<<23) #define MI_BATCH_BUFFER_END (0xA<<23) diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index df4ce4e2..64d89a75 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -70,22 +70,32 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) static int i915_emit_irq(drm_device_t * dev) { - drm_i915_private_t *dev_priv = dev->dev_private; - u32 ret; - RING_LOCALS; + + drm_i915_private_t *dev_priv = dev->dev_private; + RING_LOCALS; - i915_kernel_lost_context(dev); + i915_kernel_lost_context(dev); - DRM_DEBUG("%s\n", __FUNCTION__); + DRM_DEBUG("%s\n", __FUNCTION__); - ret = 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(6); + OUT_RING(CMD_STORE_DWORD_IDX); + OUT_RING(20); + OUT_RING(dev_priv->counter); + + OUT_RING(0); + OUT_RING(0); + OUT_RING(GFX_OP_USER_INTERRUPT); + ADVANCE_LP_RING(); + + return dev_priv->counter; - BEGIN_LP_RING(2); - OUT_RING(0); - OUT_RING(GFX_OP_USER_INTERRUPT); - ADVANCE_LP_RING(); - return ret; } static int i915_wait_irq(drm_device_t * dev, int irq_nr) |