summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c51
1 files changed, 36 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 69b9a42da95e..0cadafbef411 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -30,6 +30,7 @@
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
+#include "intel_drv.h"
#define MAX_NOPID ((u32)~0)
@@ -51,6 +52,15 @@
#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
I915_INTERRUPT_ENABLE_VAR)
+#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\
+ PIPE_VBLANK_INTERRUPT_STATUS)
+
+#define I915_PIPE_VBLANK_ENABLE (PIPE_START_VBLANK_INTERRUPT_ENABLE |\
+ PIPE_VBLANK_INTERRUPT_ENABLE)
+
+#define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \
+ DRM_I915_VBLANK_PIPE_B)
+
void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
@@ -168,6 +178,7 @@ 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;
+ struct drm_i915_master_private *master_priv;
u32 iir, new_iir;
u32 pipea_stats, pipeb_stats;
u32 vblank_status;
@@ -200,6 +211,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
pipea_stats = I915_READ(PIPEASTAT);
pipeb_stats = I915_READ(PIPEBSTAT);
+
/*
* Clear the PIPE(A|B)STAT regs before the IIR
*/
@@ -222,9 +234,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
I915_WRITE(IIR, iir);
new_iir = I915_READ(IIR); /* Flush posted writes */
- 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;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->last_dispatch =
+ READ_BREADCRUMB(dev_priv);
+ }
if (iir & I915_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
@@ -269,6 +284,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
static int i915_emit_irq(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
RING_LOCALS;
i915_kernel_lost_context(dev);
@@ -278,8 +294,8 @@ static int i915_emit_irq(struct drm_device * dev)
dev_priv->counter++;
if (dev_priv->counter > 0x7FFFFFFFUL)
dev_priv->counter = 1;
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->last_enqueue = dev_priv->counter;
BEGIN_LP_RING(4);
OUT_RING(MI_STORE_DWORD_INDEX);
@@ -317,21 +333,20 @@ void i915_user_irq_put(struct drm_device *dev)
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_master_private *master_priv = dev->primary->master->driver_priv;
int ret = 0;
DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
READ_BREADCRUMB(dev_priv));
if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
- if (dev_priv->sarea_priv) {
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
- }
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
return 0;
}
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+ if (master_priv->sarea_priv)
+ master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
i915_user_irq_get(dev);
DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
@@ -343,10 +358,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
}
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
-
return ret;
}
@@ -427,6 +438,14 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}
+void i915_enable_interrupt (struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ opregion_enable_asle(dev);
+ dev_priv->irq_enabled = 1;
+}
+
+
/* Set the vblank monitor pipe
*/
int i915_vblank_pipe_set(struct drm_device *dev, void *data,
@@ -487,6 +506,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ atomic_set(&dev_priv->irq_received, 0);
+
I915_WRITE(HWSTAM, 0xeffe);
I915_WRITE(PIPEASTAT, 0);
I915_WRITE(PIPEBSTAT, 0);