drm: Add support for Intel i965G chipsets.
This is a patch prepared by Guangdeng Liao based off of Tungsten Graphics's final code drop. From: Alan Hourihane <alanh@tungstengraphics.com> Signed-off-by: Dave Airlie <airlied@linux.ie>
This commit is contained in:
parent
d000b486ea
commit
c29b669caa
5 changed files with 58 additions and 19 deletions
|
@ -287,5 +287,9 @@
|
||||||
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
|
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
|
||||||
{0x8086, 0x2772, 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, 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}
|
{0, 0, 0}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
if (IS_I965G(dev)) {
|
||||||
OUT_RING(GFX_OP_DRAWRECT_INFO);
|
BEGIN_LP_RING(4);
|
||||||
OUT_RING(DR1);
|
OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
|
||||||
OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
|
OUT_RING((box.x1 & 0xffff) | (box.y1 << 16));
|
||||||
OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16));
|
OUT_RING(((box.x2 - 1) & 0xffff) ((box.y2 - 1) << 16));
|
||||||
OUT_RING(DR4);
|
OUT_RING(DR4);
|
||||||
OUT_RING(0);
|
ADVANCE_LP_RING();
|
||||||
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);
|
||||||
|
|
|
@ -98,6 +98,12 @@ typedef struct _drm_i915_sarea {
|
||||||
int rotated_size;
|
int rotated_size;
|
||||||
int rotated_pitch;
|
int rotated_pitch;
|
||||||
int virtualX, virtualY;
|
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;
|
} drm_i915_sarea_t;
|
||||||
|
|
||||||
/* Flags for perf_boxes
|
/* Flags for perf_boxes
|
||||||
|
|
|
@ -146,9 +146,9 @@ extern void i915_mem_release(drm_device_t * dev,
|
||||||
#define BEGIN_LP_RING(n) do { \
|
#define BEGIN_LP_RING(n) do { \
|
||||||
if (I915_VERBOSE) \
|
if (I915_VERBOSE) \
|
||||||
DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
|
DRM_DEBUG("BEGIN_LP_RING(%d) in %s\n", \
|
||||||
n, __FUNCTION__); \
|
(n), __FUNCTION__); \
|
||||||
if (dev_priv->ring.space < n*4) \
|
if (dev_priv->ring.space < (n)*4) \
|
||||||
i915_wait_ring(dev, n*4, __FUNCTION__); \
|
i915_wait_ring(dev, (n)*4, __FUNCTION__); \
|
||||||
outcount = 0; \
|
outcount = 0; \
|
||||||
outring = dev_priv->ring.tail; \
|
outring = dev_priv->ring.tail; \
|
||||||
ringmask = dev_priv->ring.tail_mask; \
|
ringmask = dev_priv->ring.tail_mask; \
|
||||||
|
@ -157,7 +157,7 @@ extern void i915_mem_release(drm_device_t * dev,
|
||||||
|
|
||||||
#define OUT_RING(n) do { \
|
#define OUT_RING(n) do { \
|
||||||
if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
|
if (I915_VERBOSE) DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \
|
||||||
*(volatile unsigned int *)(virt + outring) = n; \
|
*(volatile unsigned int *)(virt + outring) = (n); \
|
||||||
outcount++; \
|
outcount++; \
|
||||||
outring += 4; \
|
outring += 4; \
|
||||||
outring &= ringmask; \
|
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_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 ((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 ((0x30<<23)|1)
|
||||||
#define MI_BATCH_BUFFER_START (0x31<<23)
|
#define MI_BATCH_BUFFER_START (0x31<<23)
|
||||||
#define MI_BATCH_BUFFER_END (0xA<<23)
|
#define MI_BATCH_BUFFER_END (0xA<<23)
|
||||||
|
|
|
@ -71,21 +71,27 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||||
static int i915_emit_irq(drm_device_t * dev)
|
static int i915_emit_irq(drm_device_t * dev)
|
||||||
{
|
{
|
||||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
u32 ret;
|
|
||||||
RING_LOCALS;
|
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;
|
||||||
|
|
||||||
BEGIN_LP_RING(2);
|
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(0);
|
||||||
OUT_RING(GFX_OP_USER_INTERRUPT);
|
OUT_RING(GFX_OP_USER_INTERRUPT);
|
||||||
ADVANCE_LP_RING();
|
ADVANCE_LP_RING();
|
||||||
|
|
||||||
return ret;
|
return dev_priv->counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i915_wait_irq(drm_device_t * dev, int irq_nr)
|
static int i915_wait_irq(drm_device_t * dev, int irq_nr)
|
||||||
|
|
Loading…
Reference in a new issue