summaryrefslogtreecommitdiff
path: root/shared-core/i915_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core/i915_irq.c')
-rw-r--r--shared-core/i915_irq.c386
1 files changed, 322 insertions, 64 deletions
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index fd08b6e8..dad6ef86 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -31,9 +31,12 @@
#include "i915_drm.h"
#include "i915_drv.h"
+#include "intel_drv.h"
+
#define USER_INT_FLAG (1<<1)
#define VSYNC_PIPEB_FLAG (1<<5)
#define VSYNC_PIPEA_FLAG (1<<7)
+#define HOTPLUG_FLAG (1 << 17)
#define MAX_NOPID ((u32)~0)
@@ -49,7 +52,7 @@
static int
i915_get_pipe(struct drm_device *dev, int plane)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
u32 dspcntr;
dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
@@ -86,7 +89,7 @@ i915_get_plane(struct drm_device *dev, int pipe)
static int
i915_pipe_enabled(struct drm_device *dev, int pipe)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
@@ -104,8 +107,8 @@ static void
i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
int plane)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
+ struct drm_i915_sarea *sarea_priv = master_priv->sarea_priv;
u16 x1, y1, x2, y2;
int pf_planes = 1 << plane;
@@ -149,19 +152,19 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
*/
static void i915_vblank_tasklet(struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
struct list_head *list, *tmp, hits, *hit;
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
unsigned counter[2];
struct drm_drawable_info *drw;
- drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
+ struct drm_i915_sarea *sarea_priv;
u32 cpp = dev_priv->cpp, offsets[3];
u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB)
: XY_SRC_COPY_BLT_CMD;
- u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
- (cpp << 23) | (1 << 24);
+ u32 pitchropcpp;
RING_LOCALS;
counter[0] = drm_vblank_count(dev, 0);
@@ -182,13 +185,19 @@ static void i915_vblank_tasklet(struct drm_device *dev)
/* Find buffer swaps scheduled for this vertical blank */
list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
- drm_i915_vbl_swap_t *vbl_swap =
- list_entry(list, drm_i915_vbl_swap_t, head);
+ struct drm_i915_vbl_swap *vbl_swap =
+ list_entry(list, struct drm_i915_vbl_swap, head);
int pipe = i915_get_pipe(dev, vbl_swap->plane);
if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
continue;
+ master_priv = vbl_swap->minor->master->driver_priv;
+ sarea_priv = master_priv->sarea_priv;
+
+ pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) |
+ (cpp << 23) | (1 << 24);
+
list_del(list);
dev_priv->swaps_pending--;
drm_vblank_put(dev, pipe);
@@ -206,8 +215,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
}
list_for_each(hit, &hits) {
- drm_i915_vbl_swap_t *swap_cmp =
- list_entry(hit, drm_i915_vbl_swap_t, head);
+ struct drm_i915_vbl_swap *swap_cmp =
+ list_entry(hit, struct drm_i915_vbl_swap, head);
struct drm_drawable_info *drw_cmp =
drm_get_drawable_info(dev, swap_cmp->drw_id);
@@ -264,8 +273,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
lower[0] = lower[1] = sarea_priv->height;
list_for_each(hit, &hits) {
- drm_i915_vbl_swap_t *swap_hit =
- list_entry(hit, drm_i915_vbl_swap_t, head);
+ struct drm_i915_vbl_swap *swap_hit =
+ list_entry(hit, struct drm_i915_vbl_swap, head);
struct drm_clip_rect *rect;
int num_rects, plane, front, back;
unsigned short top, bottom;
@@ -303,7 +312,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
top = upper[plane];
bottom = lower[plane];
- front = (dev_priv->sarea_priv->pf_current_page >>
+ front = (master_priv->sarea_priv->pf_current_page >>
(2 * plane)) & 0x3;
back = (front + 1) % num_pages;
@@ -333,8 +342,8 @@ static void i915_vblank_tasklet(struct drm_device *dev)
DRM_SPINUNLOCK(&dev->drw_lock);
list_for_each_safe(hit, tmp, &hits) {
- drm_i915_vbl_swap_t *swap_hit =
- list_entry(hit, drm_i915_vbl_swap_t, head);
+ struct drm_i915_vbl_swap *swap_hit =
+ list_entry(hit, struct drm_i915_vbl_swap, head);
list_del(hit);
@@ -344,7 +353,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
#if 0
static int i915_in_vblank(struct drm_device *dev, int pipe)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
unsigned long pipedsl, vblank, vtotal;
unsigned long vbl_start, vbl_end, cur_line;
@@ -365,7 +374,7 @@ static int i915_in_vblank(struct drm_device *dev, int pipe)
#endif
u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
unsigned long high_frame;
unsigned long low_frame;
u32 high1, high2, low, count;
@@ -409,24 +418,196 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
return count;
}
+#define HOTPLUG_CMD_CRT 1
+#define HOTPLUG_CMD_CRT_DIS 2
+#define HOTPLUG_CMD_SDVOB 4
+#define HOTPLUG_CMD_SDVOC 8
+
+static struct drm_device *hotplug_dev;
+static int hotplug_cmd = 0;
+static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED;
+
+static void i915_hotplug_crt(struct drm_device *dev, bool connected)
+{
+ struct drm_output *output;
+ struct intel_output *iout;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ /* find the crt output */
+ list_for_each_entry(output, &dev->mode_config.output_list, head) {
+ iout = output->driver_private;
+ if (iout->type == INTEL_OUTPUT_ANALOG)
+ break;
+ else
+ iout = 0;
+ }
+
+ if (iout == 0)
+ goto unlock;
+
+ drm_hotplug_stage_two(dev, output, connected);
+
+unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+}
+
+static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
+{
+ struct drm_output *output = 0;
+ enum drm_output_status status;
+
+ mutex_lock(&dev->mode_config.mutex);
+
+ output = intel_sdvo_find(dev, sdvoB);
+
+ if (!output) {
+ DRM_ERROR("could not find sdvo%s output\n", sdvoB ? "B" : "C");
+ goto unlock;
+ }
+
+ status = output->funcs->detect(output);
+
+ if (status != output_status_connected)
+ drm_hotplug_stage_two(dev, output, false);
+ else
+ drm_hotplug_stage_two(dev, output, true);
+
+ /* wierd hw bug, sdvo stop sending interupts */
+ intel_sdvo_set_hotplug(output, 1);
+
+unlock:
+ mutex_unlock(&dev->mode_config.mutex);
+}
+/*
+ * This code is called in a more safe envirmoent to handle the hotplugs.
+ * Add code here for hotplug love to userspace.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static void i915_hotplug_work_func(void *work)
+#else
+static void i915_hotplug_work_func(struct work_struct *work)
+#endif
+{
+ struct drm_device *dev = hotplug_dev;
+ int crt;
+ int crtDis;
+ int sdvoB;
+ int sdvoC;
+
+ spin_lock(&hotplug_lock);
+ crt = hotplug_cmd & HOTPLUG_CMD_CRT;
+ crtDis = hotplug_cmd & HOTPLUG_CMD_CRT_DIS;
+ sdvoB = hotplug_cmd & HOTPLUG_CMD_SDVOB;
+ sdvoC = hotplug_cmd & HOTPLUG_CMD_SDVOC;
+ hotplug_cmd = 0;
+ spin_unlock(&hotplug_lock);
+
+ if (crt)
+ i915_hotplug_crt(dev, true);
+ if (crtDis)
+ i915_hotplug_crt(dev, false);
+
+ if (sdvoB)
+ i915_hotplug_sdvo(dev, 1);
+
+ if (sdvoC)
+ i915_hotplug_sdvo(dev, 0);
+
+}
+
+static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+ static DECLARE_WORK(hotplug, i915_hotplug_work_func, NULL);
+#else
+ static DECLARE_WORK(hotplug, i915_hotplug_work_func);
+#endif
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ hotplug_dev = dev;
+
+ if (stat & CRT_HOTPLUG_INT_STATUS) {
+ DRM_DEBUG("CRT event\n");
+
+ if (stat & CRT_HOTPLUG_MONITOR_MASK) {
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_CRT;
+ spin_unlock(&hotplug_lock);
+ } else {
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_CRT_DIS;
+ spin_unlock(&hotplug_lock);
+ }
+ }
+
+ if (stat & SDVOB_HOTPLUG_INT_STATUS) {
+ DRM_DEBUG("sDVOB event\n");
+
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_SDVOB;
+ spin_unlock(&hotplug_lock);
+ }
+
+ if (stat & SDVOC_HOTPLUG_INT_STATUS) {
+ DRM_DEBUG("sDVOC event\n");
+
+ spin_lock(&hotplug_lock);
+ hotplug_cmd |= HOTPLUG_CMD_SDVOC;
+ spin_unlock(&hotplug_lock);
+ }
+
+ queue_work(dev_priv->wq, &hotplug);
+
+ return 0;
+}
+
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u16 temp;
+ struct drm_i915_master_private *master_priv;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ u32 temp = 0;
+ u32 temp2;
u32 pipea_stats, pipeb_stats;
pipea_stats = I915_READ(I915REG_PIPEASTAT);
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
- temp = I915_READ16(I915REG_INT_IDENTITY_R);
+ /* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */
+ if (IS_I9XX(dev))
+ temp = I915_READ(I915REG_INT_IDENTITY_R);
+ else
+ temp = I915_READ16(I915REG_INT_IDENTITY_R);
+
+ temp2 = temp;
+ temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG);
#if 0
+ /* ugly despamification of pipeb event irq */
+ if (temp & (0xFFFFFFF ^ ((1 << 5) | (1 << 7)))) {
+ DRM_DEBUG("IIR %08x\n", temp2);
+ DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG);
+ DRM_DEBUG("M&I %08x\n", temp);
+ DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT));
+ }
+#else
+#if 0
DRM_DEBUG("flag=%08x\n", temp);
#endif
+#endif
+
if (temp == 0)
return IRQ_NONE;
+ if (IS_I9XX(dev)) {
+ I915_WRITE(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ(I915REG_INT_IDENTITY_R);
+ } else {
+ I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ16(I915REG_INT_IDENTITY_R);
+ }
+
/*
* Clear the PIPE(A|B)STAT regs before the IIR otherwise
* we may get extra interrupts.
@@ -437,6 +618,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
pipea_stats | I915_VBLANK_INTERRUPT_ENABLE |
I915_VBLANK_CLEAR);
}
+
if (temp & VSYNC_PIPEB_FLAG) {
drm_handle_vblank(dev, i915_get_plane(dev, 1));
I915_WRITE(I915REG_PIPEBSTAT,
@@ -447,12 +629,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
(void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */
+ DRM_READMEMORYBARRIER();
+
temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG |
VSYNC_PIPEB_FLAG);
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
+ if (dev->primary->master) {
+ master_priv = dev->primary->master->driver_priv;
+ master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+ }
if (temp & USER_INT_FLAG) {
DRM_WAKEUP(&dev_priv->irq_queue);
@@ -466,12 +651,23 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
drm_locked_tasklet(dev, i915_vblank_tasklet);
}
+ /* for now lest just ack it */
+ if (temp & (1 << 17)) {
+ DRM_DEBUG("Hotplug event received\n");
+
+ temp2 = I915_READ(PORT_HOTPLUG_STAT);
+
+ i915_run_hotplug_tasklet(dev, temp2);
+
+ I915_WRITE(PORT_HOTPLUG_STAT,temp2);
+ }
+
return IRQ_HANDLED;
}
int i915_emit_irq(struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_private *dev_priv = dev->dev_private;
RING_LOCALS;
i915_kernel_lost_context(dev);
@@ -488,7 +684,7 @@ int i915_emit_irq(struct drm_device *dev)
return dev_priv->counter;
}
-void i915_user_irq_on(drm_i915_private_t *dev_priv)
+void i915_user_irq_on(struct drm_i915_private *dev_priv)
{
DRM_SPINLOCK(&dev_priv->user_irq_lock);
if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){
@@ -498,8 +694,8 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv)
DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
}
-
-void i915_user_irq_off(drm_i915_private_t *dev_priv)
+
+void i915_user_irq_off(struct drm_i915_private *dev_priv)
{
DRM_SPINLOCK(&dev_priv->user_irq_lock);
if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
@@ -512,7 +708,8 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv)
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ struct drm_i915_master_private *master_priv;
int ret = 0;
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
@@ -530,10 +727,12 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
}
+
+ if (dev->primary->master) {
+ master_priv = dev->primary->master->driver_priv;
+ master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
+ }
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
return ret;
}
@@ -542,8 +741,8 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
int i915_irq_emit(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_irq_emit_t *emit = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_irq_emit *emit = data;
int result;
LOCK_TEST_WITH_RETURN(dev, file_priv);
@@ -568,8 +767,8 @@ int i915_irq_emit(struct drm_device *dev, void *data,
int i915_irq_wait(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_irq_wait_t *irqwait = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_irq_wait *irqwait = data;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
@@ -581,9 +780,9 @@ int i915_irq_wait(struct drm_device *dev, void *data,
int i915_enable_vblank(struct drm_device *dev, int plane)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
int pipe = i915_get_pipe(dev, plane);
-
+
switch (pipe) {
case 0:
dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG;
@@ -604,7 +803,7 @@ int i915_enable_vblank(struct drm_device *dev, int plane)
void i915_disable_vblank(struct drm_device *dev, int plane)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
int pipe = i915_get_pipe(dev, plane);
switch (pipe) {
@@ -623,13 +822,48 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
}
-static void i915_enable_interrupt (struct drm_device *dev)
+void i915_enable_interrupt (struct drm_device *dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ struct drm_output *o;
+
dev_priv->irq_enable_reg |= USER_INT_FLAG;
- I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ if (IS_I9XX(dev) && dev->mode_config.num_output) {
+ dev_priv->irq_enable_reg |= HOTPLUG_FLAG;
+
+ /* Activate the CRT */
+ I915_WRITE(PORT_HOTPLUG_EN, CRT_HOTPLUG_INT_EN);
+
+ /* SDVOB */
+ o = intel_sdvo_find(dev, 1);
+ if (o && intel_sdvo_supports_hotplug(o)) {
+ intel_sdvo_set_hotplug(o, 1);
+ I915_WRITE(PORT_HOTPLUG_EN, SDVOB_HOTPLUG_INT_EN);
+ }
+
+ /* SDVOC */
+ o = intel_sdvo_find(dev, 0);
+ if (o && intel_sdvo_supports_hotplug(o)) {
+ intel_sdvo_set_hotplug(o, 1);
+ I915_WRITE(PORT_HOTPLUG_EN, SDVOC_HOTPLUG_INT_EN);
+ }
+
+ }
+
+ if (IS_I9XX(dev)) {
+ I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ } else {
+ I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
+ }
+
+ DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN));
+ DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT));
+ DRM_DEBUG("IER %08x\n",I915_READ(I915REG_INT_ENABLE_R));
+ DRM_DEBUG("SDB %08x\n",I915_READ(SDVOB));
+
+ I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
+
dev_priv->irq_enabled = 1;
}
@@ -638,8 +872,8 @@ static void i915_enable_interrupt (struct drm_device *dev)
int i915_vblank_pipe_set(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_vblank_pipe_t *pipe = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_vblank_pipe *pipe = data;
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
@@ -659,8 +893,8 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
int i915_vblank_pipe_get(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_vblank_pipe_t *pipe = data;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_vblank_pipe *pipe = data;
u16 flag;
if (!dev_priv) {
@@ -684,9 +918,10 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
- drm_i915_private_t *dev_priv = dev->dev_private;
- drm_i915_vblank_swap_t *swap = data;
- drm_i915_vbl_swap_t *vbl_swap;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_master_private *master_priv;
+ struct drm_i915_vblank_swap *swap = data;
+ struct drm_i915_vbl_swap *vbl_swap;
unsigned int pipe, seqtype, curseq, plane;
unsigned long irqflags;
struct list_head *list;
@@ -697,7 +932,12 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
return -EINVAL;
}
- if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
+ if (!dev->primary->master)
+ return -EINVAL;
+
+ master_priv = dev->primary->master->driver_priv;
+
+ if (master_priv->sarea_priv->rotation) {
DRM_DEBUG("Rotation not supported\n");
return -EINVAL;
}
@@ -780,7 +1020,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
DRM_SPINLOCK_IRQSAVE(&dev_priv->swaps_lock, irqflags);
list_for_each(list, &dev_priv->vbl_swaps.head) {
- vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
+ vbl_swap = list_entry(list, struct drm_i915_vbl_swap, head);
if (vbl_swap->drw_id == swap->drawable &&
vbl_swap->plane == plane &&
@@ -818,6 +1058,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
vbl_swap->plane = plane;
vbl_swap->sequence = swap->sequence;
vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
+ vbl_swap->minor = file_priv->minor;
if (vbl_swap->flip)
swap->sequence++;
@@ -836,16 +1077,22 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
*/
void i915_driver_irq_preinstall(struct drm_device * dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
I915_WRITE16(I915REG_HWSTAM, 0xeffe);
- I915_WRITE16(I915REG_INT_MASK_R, 0x0);
- I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ if (IS_I9XX(dev)) {
+ I915_WRITE(I915REG_INT_MASK_R, 0x0);
+ I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
+ } else {
+ I915_WRITE16(I915REG_INT_MASK_R, 0x0);
+ I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+ }
+
}
int i915_driver_irq_postinstall(struct drm_device * dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
int ret, num_pipes = 2;
DRM_SPININIT(&dev_priv->swaps_lock, "swap");
@@ -875,17 +1122,28 @@ int i915_driver_irq_postinstall(struct drm_device * dev)
void i915_driver_irq_uninstall(struct drm_device * dev)
{
- drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u16 temp;
+ struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
+ u32 temp;
if (!dev_priv)
return;
dev_priv->irq_enabled = 0;
- I915_WRITE16(I915REG_HWSTAM, 0xffff);
- I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
- I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
- temp = I915_READ16(I915REG_INT_IDENTITY_R);
- I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+
+ if(IS_I9XX(dev)) {
+ I915_WRITE(I915REG_HWSTAM, 0xffffffff);
+ I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
+ I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
+
+ temp = I915_READ(I915REG_INT_IDENTITY_R);
+ I915_WRITE(I915REG_INT_IDENTITY_R, temp);
+ } else {
+ I915_WRITE16(I915REG_HWSTAM, 0xffff);
+ I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
+ I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
+
+ temp = I915_READ16(I915REG_INT_IDENTITY_R);
+ I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ }
}