Skip to content

Commit

Permalink
Add Intel ACPI IGD OpRegion support
Browse files Browse the repository at this point in the history
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: Matthew Garrett <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
  • Loading branch information
mjg59 authored and airlied committed Oct 17, 2008
1 parent 398c9cb commit 8ee1c3d
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 9 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -532,6 +534,8 @@ static int i915_resume(struct drm_device *dev)

i915_restore_vga(dev);

intel_opregion_init(dev);

return 0;
}

Expand Down
17 changes: 17 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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))
Expand Down
25 changes: 17 additions & 8 deletions drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}

Expand Down
Loading

0 comments on commit 8ee1c3d

Please sign in to comment.