summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/i915_dma.c14
-rw-r--r--shared-core/i915_drm.h2
-rw-r--r--shared-core/i915_drv.h39
-rw-r--r--shared-core/i915_irq.c164
-rw-r--r--shared-core/radeon_drv.h10
-rw-r--r--shared-core/radeon_irq.c75
6 files changed, 234 insertions, 70 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index ebb184cc..73972d56 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -833,6 +833,20 @@ static int i915_setparam(DRM_IOCTL_ARGS)
case I915_SETPARAM_ALLOW_BATCHBUFFER:
dev_priv->allow_batchbuffer = param.value;
break;
+ case I915_SETPARAM_PREMODESET:
+ if (param.value > 1) {
+ DRM_ERROR("bad crtc\n");
+ return -EINVAL;
+ }
+ i915_premodeset(dev, param.value);
+ break;
+ case I915_SETPARAM_POSTMODESET:
+ if (param.value > 1) {
+ DRM_ERROR("bad crtc\n");
+ return -EINVAL;
+ }
+ i915_postmodeset(dev, param.value);
+ break;
default:
DRM_ERROR("unknown parameter %d\n", param.param);
return DRM_ERR(EINVAL);
diff --git a/shared-core/i915_drm.h b/shared-core/i915_drm.h
index 1c6ff4d3..aea048fa 100644
--- a/shared-core/i915_drm.h
+++ b/shared-core/i915_drm.h
@@ -235,6 +235,8 @@ typedef struct drm_i915_getparam {
#define I915_SETPARAM_USE_MI_BATCHBUFFER_START 1
#define I915_SETPARAM_TEX_LRU_LOG_GRANULARITY 2
#define I915_SETPARAM_ALLOW_BATCHBUFFER 3
+#define I915_SETPARAM_PREMODESET 4
+#define I915_SETPARAM_POSTMODESET 5
typedef struct drm_i915_setparam {
int param;
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index 9deee8ec..88949ad0 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -132,6 +132,8 @@ typedef struct drm_i915_private {
spinlock_t swaps_lock;
drm_i915_vbl_swap_t vbl_swaps;
unsigned int swaps_pending;
+ unsigned long vblank_offset[2];
+ unsigned long vblank_premodeset[2];
} drm_i915_private_t;
enum intel_chip_family {
@@ -161,8 +163,6 @@ extern int i915_driver_firstopen(struct drm_device *dev);
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 int i915_driver_vblank_wait2(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);
@@ -173,6 +173,11 @@ extern int i915_emit_irq(drm_device_t * dev);
extern void i915_user_irq_on(drm_i915_private_t *dev_priv);
extern void i915_user_irq_off(drm_i915_private_t *dev_priv);
extern int i915_vblank_swap(DRM_IOCTL_ARGS);
+extern void i915_enable_vblank(drm_device_t *dev, int crtc);
+extern void i915_disable_vblank(drm_device_t *dev, int crtc);
+extern u32 i915_get_vblank_counter(drm_device_t *dev, int crtc);
+extern void i915_premodeset(drm_device_t *dev, int crtc);
+extern void i915_postmodeset(drm_device_t *dev, int crtc);
/* i915_mem.c */
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
@@ -271,6 +276,36 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller);
#define I915REG_PIPEASTAT 0x70024
#define I915REG_PIPEBSTAT 0x71024
+/*
+ * The two pipe frame counter registers are not synchronized, so
+ * reading a stable value is somewhat tricky. The following code
+ * should work:
+ *
+ * do {
+ * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ * PIPE_FRAME_HIGH_SHIFT;
+ * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
+ * PIPE_FRAME_LOW_SHIFT);
+ * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
+ * PIPE_FRAME_HIGH_SHIFT);
+ * } while (high1 != high2);
+ * frame = (high1 << 8) | low1;
+ */
+#define PIPEAFRAMEHIGH 0x70040
+#define PIPEBFRAMEHIGH 0x71040
+#define PIPE_FRAME_HIGH_MASK 0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT 0
+#define PIPEAFRAMEPIXEL 0x70044
+#define PIPEBFRAMEPIXEL 0x71044
+
+#define PIPE_FRAME_LOW_MASK 0xff000000
+#define PIPE_FRAME_LOW_SHIFT 24
+/*
+ * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
+ * and is 24 bits wide.
+ */
+#define PIPE_PIXEL_MASK 0x00ffffff
+#define PIPE_PIXEL_SHIFT 0
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
#define I915_VBLANK_CLEAR (1UL<<1)
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index dc00f983..1019c942 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -92,8 +92,8 @@ static void i915_vblank_tasklet(drm_device_t *dev)
unsigned long irqflags;
struct list_head *list, *tmp, hits, *hit;
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
- unsigned counter[2] = { atomic_read(&dev->vbl_received),
- atomic_read(&dev->vbl_received2) };
+ unsigned counter[2] = { atomic_read(&dev->vblank_count[0]),
+ atomic_read(&dev->vblank_count[1]) };
drm_drawable_info_t *drw;
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
u32 cpp = dev_priv->cpp, offsets[3];
@@ -313,14 +313,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
(DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
== (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
if (temp & VSYNC_PIPEA_FLAG)
- atomic_inc(&dev->vbl_received);
+ atomic_inc(&dev->vblank_count[0]);
if (temp & VSYNC_PIPEB_FLAG)
- atomic_inc(&dev->vbl_received2);
+ atomic_inc(&dev->vblank_count[1]);
} else if (((temp & VSYNC_PIPEA_FLAG) &&
(vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
((temp & VSYNC_PIPEB_FLAG) &&
(vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
- atomic_inc(&dev->vbl_received);
+ atomic_inc(&dev->vblank_count[0]);
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
@@ -410,37 +410,6 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
return ret;
}
-static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
- atomic_t *counter)
-{
- 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(counter))
- - *sequence) <= (1<<23)));
-
- *sequence = cur_vblank;
-
- return ret;
-}
-
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
-{
- return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
-}
-
-int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
-{
- return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
-}
-
/* Needs the lock as it touches the ring.
*/
int i915_irq_emit(DRM_IOCTL_ARGS)
@@ -489,15 +458,99 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
return i915_wait_irq(dev, irqwait.irq_seq);
}
-static void i915_enable_interrupt (drm_device_t *dev)
+void i915_enable_vblank(drm_device_t *dev, int crtc)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- dev_priv->irq_enable_reg = USER_INT_FLAG;
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+ switch (crtc) {
+ case 0:
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
- if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+ break;
+ case 1:
dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG;
+ break;
+ default:
+ DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
+ crtc);
+ break;
+ }
+
+ I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+}
+
+void i915_disable_vblank(drm_device_t *dev, int crtc)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+ switch (crtc) {
+ case 0:
+ dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG;
+ break;
+ case 1:
+ dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG;
+ break;
+ default:
+ DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
+ crtc);
+ break;
+ }
+
+ I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+}
+
+static u32 i915_vblank_counter(drm_device_t *dev, int crtc)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ unsigned long high_frame = crtc ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
+ unsigned long low_frame = crtc ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+ u32 high1, high2, low, count;
+
+ /*
+ * High & low register fields aren't synchronized, so make sure
+ * we get a low value that's stable across two reads of the high
+ * register.
+ */
+ do {
+ high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+ PIPE_FRAME_HIGH_SHIFT);
+ low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+ PIPE_FRAME_LOW_SHIFT);
+ high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+ PIPE_FRAME_HIGH_SHIFT);
+ } while (high1 != high2);
+
+ count = (high1 << 8) | low;
+
+ return count;
+}
+
+u32 i915_get_vblank_counter(drm_device_t *dev, int crtc)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ return i915_vblank_counter(dev, crtc) + dev_priv->vblank_offset[crtc];
+}
+
+void i915_premodeset(drm_device_t *dev, int crtc)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ dev_priv->vblank_premodeset[crtc] = i915_vblank_counter(dev, crtc);
+}
+
+void i915_postmodeset(drm_device_t *dev, int crtc)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ u32 new;
+
+ new = i915_vblank_counter(dev, crtc);
+ dev_priv->vblank_offset[crtc] = dev_priv->vblank_premodeset[crtc] - new;
+}
+
+static void i915_enable_interrupt (drm_device_t *dev)
+{
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+ dev_priv->irq_enable_reg |= USER_INT_FLAG;
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
dev_priv->irq_enabled = 1;
@@ -607,7 +660,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
- curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
+ curseq = atomic_read(&dev->vblank_count[pipe]);
if (seqtype == _DRM_VBLANK_RELATIVE)
swap.sequence += curseq;
@@ -714,6 +767,7 @@ void i915_driver_irq_preinstall(drm_device_t * dev)
void i915_driver_irq_postinstall(drm_device_t * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ int i;
spin_lock_init(&dev_priv->swaps_lock);
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
@@ -721,6 +775,34 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
dev_priv->user_irq_lock = SPIN_LOCK_UNLOCKED;
dev_priv->user_irq_refcount = 0;
+ dev_priv->irq_enable_reg = 0;
+ dev->vblank_count = kmalloc(sizeof(atomic_t) * 2, GFP_KERNEL);
+ if (!dev->vblank_count) {
+ DRM_ERROR("out of memory\n");
+ return;
+ }
+ dev->vbl_pending = kmalloc(sizeof(atomic_t) * 2, GFP_KERNEL);
+ if (!dev->vbl_pending) {
+ DRM_ERROR("out of memory\n");
+ kfree(dev->vblank_count);
+ return;
+ }
+ dev->last_vblank = kmalloc(sizeof(atomic_t) * 2, GFP_KERNEL);
+ if (!dev->last_vblank) {
+ DRM_ERROR("out of memory\n");
+ kfree(dev->vblank_count);
+ return;
+ }
+
+ /* Zero per-crtc vblank stuff */
+ for (i = 0; i < 2; i++) {
+ atomic_set(&dev->vbl_pending[i], 0);
+ atomic_set(&dev->vblank_count[i], 0);
+ dev->last_vblank[i] = 0;
+ dev_priv->vblank_offset[i] = 0;
+ }
+
+ dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
i915_enable_interrupt(dev);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h
index 92a9b65e..283dee33 100644
--- a/shared-core/radeon_drv.h
+++ b/shared-core/radeon_drv.h
@@ -299,6 +299,9 @@ typedef struct drm_radeon_private {
u32 scratch_ages[5];
+ unsigned int crtc_last_cnt;
+ unsigned int crtc2_last_cnt;
+
/* starting from here on, data is preserved accross an open */
uint32_t flags; /* see radeon_chip_flags */
@@ -364,9 +367,9 @@ extern int radeon_irq_wait(DRM_IOCTL_ARGS);
extern void radeon_do_release(drm_device_t * dev);
extern int radeon_driver_vblank_wait(drm_device_t * dev,
- unsigned int *sequence);
+ unsigned int *sequence, int relative);
extern int radeon_driver_vblank_wait2(drm_device_t * dev,
- unsigned int *sequence);
+ unsigned int *sequence, int relative);
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
extern void radeon_driver_irq_preinstall(drm_device_t * dev);
extern void radeon_driver_irq_postinstall(drm_device_t * dev);
@@ -507,6 +510,9 @@ extern int r300_do_cp_cmdbuf(drm_device_t *dev, DRMFILE filp,
? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
+#define RADEON_CRTC_CRNT_FRAME 0x0214
+#define RADEON_CRTC2_CRNT_FRAME 0x0314
+
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c
index 5151b4d6..2534ff10 100644
--- a/shared-core/radeon_irq.c
+++ b/shared-core/radeon_irq.c
@@ -35,6 +35,18 @@
#include "radeon_drm.h"
#include "radeon_drv.h"
+static void radeon_irq_set_state(drm_device_t *dev, u32 mask, int state)
+{
+ drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
+
+ if (state)
+ dev_priv->irq_enable_reg |= mask;
+ else
+ dev_priv->irq_enable_reg &= ~mask;
+
+ RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
+}
+
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
u32 mask)
{
@@ -141,14 +153,17 @@ static int radeon_wait_irq(drm_device_t * dev, int swi_nr)
}
int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
- int crtc)
+ int crtc, int relative)
{
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *) dev->dev_private;
- unsigned int cur_vblank;
+ unsigned int cur_vblank, diff, irqflags, current_cnt;
int ret = 0;
int ack = 0;
atomic_t *counter;
+ unsigned int *last_cnt;
+ int crtc_cnt_reg;
+
if (!dev_priv) {
DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
return DRM_ERR(EINVAL);
@@ -156,10 +171,14 @@ int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
if (crtc == DRM_RADEON_VBLANK_CRTC1) {
counter = &dev->vbl_received;
- ack |= RADEON_CRTC_VBLANK_STAT;
+ ack = RADEON_CRTC_VBLANK_STAT;
+ last_cnt = &dev_priv->crtc_last_cnt;
+ crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
counter = &dev->vbl_received2;
- ack |= RADEON_CRTC2_VBLANK_STAT;
+ ack = RADEON_CRTC2_VBLANK_STAT;
+ last_cnt = &dev_priv->crtc2_last_cnt;
+ crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
} else
return DRM_ERR(EINVAL);
@@ -167,27 +186,46 @@ int radeon_driver_vblank_do_wait(drm_device_t * dev, unsigned int *sequence,
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
+ if (!relative) {
+ /*
+ * Assume we haven't missed more than several hours of vblank
+ * events, or that it won't matter if they're not accounted
+ * for in the master counter.
+ */
+ spin_lock_irqsave(&dev->vbl_lock, irqflags);
+ current_cnt = RADEON_READ(crtc_cnt_reg);
+ if (current_cnt < *last_cnt) {
+ current_cnt += (1 << 21) - *last_cnt;
+ *last_cnt = 0;
+ }
+ diff = current_cnt - *last_cnt;
+ *last_cnt = RADEON_READ(crtc_cnt_reg);
+ spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+ atomic_add(diff, counter);
+ }
+
/* Assume that the user has missed the current sequence number
* by about a day rather than she wants to wait for years
* using vertical blanks...
*/
+ radeon_irq_set_state(dev, ack, 1);
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
(((cur_vblank = atomic_read(counter))
- *sequence) <= (1 << 23)));
-
+ radeon_irq_set_state(dev, ack, 0);
*sequence = cur_vblank;
return ret;
}
-int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence, int relative)
{
- return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
+ return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1, relative);
}
-int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+int radeon_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence, int relative)
{
- return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
+ return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2, relative);
}
/* Needs the lock as it touches the ring.
@@ -238,20 +276,7 @@ int radeon_irq_wait(DRM_IOCTL_ARGS)
return radeon_wait_irq(dev, irqwait.irq_seq);
}
-static void radeon_enable_interrupt(drm_device_t *dev)
-{
- drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
-
- dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
- if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
- dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
-
- if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
- dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
- RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
- dev_priv->irq_enabled = 1;
-}
/* drm_dma.h hooks
*/
@@ -265,7 +290,8 @@ void radeon_driver_irq_preinstall(drm_device_t * dev)
/* Clear bits if they're already high */
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
- RADEON_CRTC_VBLANK_STAT));
+ RADEON_CRTC_VBLANK_STAT |
+ RADEON_CRTC2_VBLANK_STAT));
}
void radeon_driver_irq_postinstall(drm_device_t * dev)
@@ -276,7 +302,7 @@ void radeon_driver_irq_postinstall(drm_device_t * dev)
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
- radeon_enable_interrupt(dev);
+ radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
}
void radeon_driver_irq_uninstall(drm_device_t * dev)
@@ -318,6 +344,5 @@ int radeon_vblank_crtc_set(drm_device_t *dev, int64_t value)
return DRM_ERR(EINVAL);
}
dev_priv->vblank_crtc = (unsigned int)value;
- radeon_enable_interrupt(dev);
return 0;
}