commit 48cb9aceed782a4e9c557f30429e65f845dd777d Author: Alan Hourihane Date: Tue Aug 8 15:05:54 2006 -0700 Add drm support for Intel i965G chipsets. This is a patch prepared by Guangdeng Liao based off of Tungsten Graphics's final code drop. backport taken from fedora tree. -maks --- drivers/char/drm/drm_pciids.h | 4 4 + 0 - 0 ! drivers/char/drm/i915_dma.c | 47 35 + 12 - 0 ! drivers/char/drm/i915_drm.h | 6 6 + 0 - 0 ! drivers/char/drm/i915_drv.h | 14 8 + 6 - 0 ! drivers/char/drm/i915_irq.c | 18 14 + 4 - 0 ! 5 files changed, 67 insertions(+), 22 deletions(-) Index: linux-2.6.17/drivers/char/drm/i915_dma.c =================================================================== --- linux-2.6.17.orig/drivers/char/drm/i915_dma.c 2006-08-10 11:43:30.000000000 +0200 +++ linux-2.6.17/drivers/char/drm/i915_dma.c 2006-08-10 11:50:44.000000000 +0200 @@ -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 * 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,24 +402,40 @@ static int i915_emit_box(drm_device_t * 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); Index: linux-2.6.17/drivers/char/drm/i915_drm.h =================================================================== --- linux-2.6.17.orig/drivers/char/drm/i915_drm.h 2006-08-10 11:43:30.000000000 +0200 +++ linux-2.6.17/drivers/char/drm/i915_drm.h 2006-08-10 11:46:31.000000000 +0200 @@ -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 Index: linux-2.6.17/drivers/char/drm/i915_drv.h =================================================================== --- linux-2.6.17.orig/drivers/char/drm/i915_drv.h 2006-08-10 11:43:30.000000000 +0200 +++ linux-2.6.17/drivers/char/drm/i915_drv.h 2006-08-10 11:50:44.000000000 +0200 @@ -137,14 +137,14 @@ extern void i915_mem_release(drm_device_ #define I915_VERBOSE 0 #define RING_LOCALS unsigned int outring, ringmask, outcount; \ - volatile char *virt; + volatile char *virt; #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; \ @@ -153,8 +153,8 @@ extern void i915_mem_release(drm_device_ #define OUT_RING(n) do { \ if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outcount++; \ + *(volatile unsigned int *)(virt + outring) = (n); \ + outcount++; \ outring += 4; \ outring &= ringmask; \ } while (0) @@ -250,6 +250,8 @@ extern int i915_wait_ring(drm_device_t * #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) Index: linux-2.6.17/drivers/char/drm/i915_irq.c =================================================================== --- linux-2.6.17.orig/drivers/char/drm/i915_irq.c 2006-08-10 11:43:30.000000000 +0200 +++ linux-2.6.17/drivers/char/drm/i915_irq.c 2006-08-10 11:50:54.000000000 +0200 @@ -69,22 +69,32 @@ irqreturn_t i915_driver_irq_handler(DRM_ static int i915_emit_irq(drm_device_t * dev) { + drm_i915_private_t *dev_priv = dev->dev_private; - u32 ret; RING_LOCALS; i915_kernel_lost_context(dev); 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(2); + 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 ret; + return dev_priv->counter; + + } static int i915_wait_irq(drm_device_t * dev, int irq_nr) Index: linux-2.6.17/drivers/char/drm/drm_pciids.h =================================================================== --- linux-2.6.17.orig/drivers/char/drm/drm_pciids.h 2006-06-18 03:49:35.000000000 +0200 +++ linux-2.6.17/drivers/char/drm/drm_pciids.h 2006-08-10 11:48:36.000000000 +0200 @@ -285,5 +285,9 @@ {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x8086, 0x27a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2972, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2982, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x2992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ + {0x8086, 0x29a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0, 0, 0}