Commit 8ee1c3db authored by Matthew Garrett's avatar Matthew Garrett Committed by Dave Airlie

Add Intel ACPI IGD OpRegion support

This adds the support necessary for allowing ACPI backlight control to
work on some newer Intel-based graphics systems. Tested on Thinkpad T61
and HP 2510p hardware.
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@linux.ie>
parent 398c9cb2
......@@ -3,7 +3,7 @@
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
ccflags-y := -Iinclude/drm
i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o i915_opregion.o
i915-$(CONFIG_COMPAT) += i915_ioc32.o
......
......@@ -810,6 +810,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
if (!IS_I945G(dev) && !IS_I945GM(dev))
pci_enable_msi(dev->pdev);
intel_opregion_init(dev);
spin_lock_init(&dev_priv->user_irq_lock);
return ret;
......@@ -827,6 +829,8 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->mmio_map)
drm_rmmap(dev, dev_priv->mmio_map);
intel_opregion_free(dev);
drm_free(dev->dev_private, sizeof(drm_i915_private_t),
DRM_MEM_DRIVER);
......
......@@ -371,6 +371,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
i915_save_vga(dev);
intel_opregion_free(dev);
if (state.event == PM_EVENT_SUSPEND) {
/* Shut down the device */
pci_disable_device(dev->pdev);
......@@ -532,6 +534,8 @@ static int i915_resume(struct drm_device *dev)
i915_restore_vga(dev);
intel_opregion_init(dev);
return 0;
}
......
......@@ -82,6 +82,14 @@ typedef struct _drm_i915_vbl_swap {
unsigned int sequence;
} drm_i915_vbl_swap_t;
struct intel_opregion {
struct opregion_header *header;
struct opregion_acpi *acpi;
struct opregion_swsci *swsci;
struct opregion_asle *asle;
int enabled;
};
typedef struct drm_i915_private {
drm_local_map_t *sarea;
drm_local_map_t *mmio_map;
......@@ -122,6 +130,8 @@ typedef struct drm_i915_private {
drm_i915_vbl_swap_t vbl_swaps;
unsigned int swaps_pending;
struct intel_opregion opregion;
/* Register state */
u8 saveLBB;
u32 saveDSPACNTR;
......@@ -244,6 +254,7 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int i915_vblank_swap(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);
/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
......@@ -258,6 +269,12 @@ extern void i915_mem_takedown(struct mem_block **heap);
extern void i915_mem_release(struct drm_device * dev,
struct drm_file *file_priv, struct mem_block *heap);
/* 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);
#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg))
#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val))
#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg))
......
......@@ -36,9 +36,11 @@
/** These are the interrupts used by the driver */
#define I915_INTERRUPT_ENABLE_MASK (I915_USER_INTERRUPT | \
I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | \
I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT)
I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT | \
I915_ASLE_INTERRUPT | \
I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
static inline void
void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->irq_mask_reg & mask) != 0) {
......@@ -274,6 +276,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
}
I915_WRITE(PIPEASTAT, pipea_stats);
I915_WRITE(PIPEBSTAT, pipeb_stats);
I915_WRITE(IIR, iir);
if (dev->pdev->msi_enabled)
I915_WRITE(IMR, dev_priv->irq_mask_reg);
......@@ -306,14 +311,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (dev_priv->swaps_pending > 0)
drm_locked_tasklet(dev, i915_vblank_tasklet);
I915_WRITE(PIPEASTAT,
pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
PIPE_VBLANK_INTERRUPT_STATUS);
I915_WRITE(PIPEBSTAT,
pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
PIPE_VBLANK_INTERRUPT_STATUS);
}
if (iir & I915_ASLE_INTERRUPT)
opregion_asle_intr(dev);
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
opregion_asle_intr(dev);
return IRQ_HANDLED;
}
......@@ -661,10 +666,14 @@ void i915_driver_irq_postinstall(struct drm_device * dev)
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
dev_priv->irq_mask_reg &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
dev_priv->irq_mask_reg &= I915_INTERRUPT_ENABLE_MASK;
I915_WRITE(IMR, dev_priv->irq_mask_reg);
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
(void) I915_READ(IER);
opregion_enable_asle(dev);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}
......
This diff is collapsed.
......@@ -740,6 +740,7 @@
#define BLC_PWM_CTL 0x61254
#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
#define BLC_PWM_CTL2 0x61250 /* 965+ only */
#define BLM_COMBINATION_MODE (1 << 30)
/*
* This is the most significant 15 bits of the number of backlight cycles in a
* complete cycle of the modulated backlight control.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment