summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-core/i915_drv.c3
-rw-r--r--shared-core/i915_dma.c3
-rw-r--r--shared-core/i915_drm.h1
-rw-r--r--shared-core/i915_drv.h8
-rw-r--r--shared-core/i915_irq.c41
5 files changed, 48 insertions, 8 deletions
diff --git a/linux-core/i915_drv.c b/linux-core/i915_drv.c
index 5efa4420..a28bce7e 100644
--- a/linux-core/i915_drv.c
+++ b/linux-core/i915_drv.c
@@ -45,11 +45,12 @@ static struct drm_driver driver = {
*/
.driver_features =
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR | */
- DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
+ DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
.load = i915_driver_load,
.lastclose = i915_driver_lastclose,
.preclose = i915_driver_preclose,
.device_is_agp = i915_driver_device_is_agp,
+ .vblank_wait = i915_driver_vblank_wait,
.irq_preinstall = i915_driver_irq_preinstall,
.irq_postinstall = i915_driver_irq_postinstall,
.irq_uninstall = i915_driver_irq_uninstall,
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index ee8dbcd7..3d2eae2b 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -664,6 +664,9 @@ static int i915_getparam(DRM_IOCTL_ARGS)
case I915_PARAM_ALLOW_BATCHBUFFER:
value = dev_priv->allow_batchbuffer ? 1 : 0;
break;
+ case I915_PARAM_LAST_DISPATCH:
+ value = READ_BREADCRUMB(dev_priv);
+ break;
default:
DRM_ERROR("Unkown parameter %d\n", param.param);
return DRM_ERR(EINVAL);
diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h
index 42d726c5..0e718aec 100644
--- a/shared-core/i915_drm.h
+++ b/shared-core/i915_drm.h
@@ -151,6 +151,7 @@ typedef struct drm_i915_irq_wait {
*/
#define I915_PARAM_IRQ_ACTIVE 1
#define I915_PARAM_ALLOW_BATCHBUFFER 2
+#define I915_PARAM_LAST_DISPATCH 3
typedef struct drm_i915_getparam {
int param;
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 7107d45c..e5bda46d 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -37,15 +37,16 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
-#define DRIVER_DATE "20041217"
+#define DRIVER_DATE "20051209"
/* Interface history:
*
* 1.1: Original.
* 1.2: Add Power Management
+ * 1.3: Add vblank support
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 2
+#define DRIVER_MINOR 3
#define DRIVER_PATCHLEVEL 0
typedef struct _drm_i915_ring_buffer {
@@ -112,6 +113,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
extern int i915_irq_emit(DRM_IOCTL_ARGS);
extern int i915_irq_wait(DRM_IOCTL_ARGS);
+extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
@@ -262,4 +264,6 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
+#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
+
#endif
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index 2ec75f51..d5780d58 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -31,9 +31,11 @@
#include "i915_drm.h"
#include "i915_drv.h"
-#define USER_INT_FLAG 0x2
+#define USER_INT_FLAG (1<<1)
+#define VSYNC_PIPEB_FLAG (1<<5)
+#define VSYNC_PIPEA_FLAG (1<<7)
+
#define MAX_NOPID ((u32)~0)
-#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5])
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
@@ -42,7 +44,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
u16 temp;
temp = I915_READ16(I915REG_INT_IDENTITY_R);
- temp &= USER_INT_FLAG;
+
+ temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG);
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
@@ -50,7 +53,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
- DRM_WAKEUP(&dev_priv->irq_queue);
+
+ if (temp & USER_INT_FLAG)
+ DRM_WAKEUP(&dev_priv->irq_queue);
+
+ if (temp & VSYNC_PIPEA_FLAG) {
+ atomic_inc(&dev->vbl_received);
+ DRM_WAKEUP(&dev->vbl_queue);
+ drm_vbl_send_signals(dev);
+ }
return IRQ_HANDLED;
}
@@ -101,6 +112,26 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
return ret;
}
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned int cur_vblank;
+ int ret = 0;
+
+ if (!dev_priv) {
+ DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+ return DRM_ERR(EINVAL);
+ }
+
+ DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+ (((cur_vblank = atomic_read(&dev->vbl_received))
+ - *sequence) <= (1<<23)));
+
+ *sequence = cur_vblank;
+
+ return ret;
+}
+
/* Needs the lock as it touches the ring.
*/
int i915_irq_emit(DRM_IOCTL_ARGS)
@@ -164,7 +195,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG);
+ I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}