diff options
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/i915_dma.c | 5 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 30 | ||||
-rw-r--r-- | shared-core/i915_irq.c | 22 |
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; } |