summaryrefslogtreecommitdiff
path: root/shared-core
diff options
context:
space:
mode:
Diffstat (limited to 'shared-core')
-rw-r--r--shared-core/i915_dma.c5
-rw-r--r--shared-core/i915_drv.h30
-rw-r--r--shared-core/i915_irq.c22
3 files changed, 57 insertions, 0 deletions
diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c
index 27d152cb..ad6e1293 100644
--- a/shared-core/i915_dma.c
+++ b/shared-core/i915_dma.c
@@ -1038,6 +1038,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
intel_init_chipset_flush_compat(dev);
#endif
+ intel_opregion_init(dev);
#endif
return ret;
@@ -1050,6 +1051,10 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->mmio_map)
drm_rmmap(dev, dev_priv->mmio_map);
+#ifdef __linux__
+ intel_opregion_free(dev);
+#endif
+
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
DRM_MEM_DRIVER);
#ifdef __linux__
diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index fa3305ba..421572cd 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -105,6 +105,22 @@ typedef struct _drm_i915_vbl_swap {
int flip;
} drm_i915_vbl_swap_t;
+#ifdef __linux__
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct intel_opregion {
+ struct opregion_header *header;
+ struct opregion_acpi *acpi;
+ struct opregion_swsci *swsci;
+ struct opregion_asle *asle;
+
+ int enabled;
+};
+#endif
+
typedef struct drm_i915_private {
drm_local_map_t *sarea;
drm_local_map_t *mmio_map;
@@ -158,6 +174,11 @@ typedef struct drm_i915_private {
struct drm_buffer_object *sarea_bo;
struct drm_bo_kmap_obj sarea_kmap;
#endif
+
+#ifdef __linux__
+ struct intel_opregion opregion;
+#endif
+
/* Register state */
u8 saveLBB;
u32 saveDSPACNTR;
@@ -343,6 +364,14 @@ int i915_execbuffer(struct drm_device *dev, void *data,
#endif
#ifdef __linux__
+/* i915_opregion.c */
+extern int intel_opregion_init(struct drm_device *dev);
+extern void intel_opregion_free(struct drm_device *dev);
+extern void opregion_asle_intr(struct drm_device *dev);
+extern void opregion_enable_asle(struct drm_device *dev);
+#endif
+
+#ifdef __linux__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
extern void intel_init_chipset_flush_compat(struct drm_device *dev);
extern void intel_fini_chipset_flush_compat(struct drm_device *dev);
@@ -613,6 +642,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
#define I915_DEBUG_INTERRUPT (1<<2)
#define I915_USER_INTERRUPT (1<<1)
+#define I915_ASLE_INTERRUPT (1<<0)
#define EIR 0x020b0
#define EMR 0x020b4
#define ESR 0x020b8
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index 28f9f6af..d7fa47d3 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -474,15 +474,33 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
}
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
pipeb_stats = I915_READ(PIPEBSTAT);
+ /* Ack the event */
+ I915_WRITE(PIPEBSTAT, pipeb_stats);
+
+ /* The vblank interrupt gets enabled even if we didn't ask for
+ it, so make sure it's shut down again */
+ if (!(dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B))
+ pipeb_stats &= ~(I915_VBLANK_INTERRUPT_ENABLE);
+
if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS|
PIPE_VBLANK_INTERRUPT_STATUS))
{
vblank++;
drm_handle_vblank(dev, i915_get_plane(dev, 1));
}
+
+#ifdef __linux__
+ if (pipeb_stats & I915_LEGACY_BLC_EVENT_ENABLE)
+ opregion_asle_intr(dev);
+#endif
I915_WRITE(PIPEBSTAT, pipeb_stats);
}
+#ifdef __linux__
+ if (iir & I915_ASLE_INTERRUPT)
+ opregion_asle_intr(dev);
+#endif
+
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
@@ -703,6 +721,10 @@ static void i915_enable_interrupt (struct drm_device *dev)
dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
+#ifdef __linux__
+ opregion_enable_asle(dev);
+#endif
+
I915_WRITE(IER, dev_priv->irq_enable_reg);
dev_priv->irq_enabled = 1;
}