Skip to content

Commit

Permalink
drm/i915: Add ACPI OpRegion support for Ironlake
Browse files Browse the repository at this point in the history
Add the support of ACPI opregion on Ironlake so that the backlight
brightness can be adjusted by using ACPI interface
   >/sys/class/backlight/acpi_video0/brightness

Signed-off-by: Zhao Yakui <[email protected]>
Tested-by: Zhao Yakui <[email protected]>
[zhenyuw: cleanups, fix typo for checking GSE irq and convert to
current irq handling logic.]
Signed-off-by: Zhenyu Wang <[email protected]>
Signed-off-by: Eric Anholt <[email protected]>
  • Loading branch information
yakuizhao authored and anholt committed Nov 5, 2009
1 parent 1dc7546 commit 01c6688
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 8 deletions.
7 changes: 2 additions & 5 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,9 +1492,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
}

/* Must be done after probing outputs */
/* FIXME: verify on IGDNG */
if (!IS_IGDNG(dev))
intel_opregion_init(dev, 0);
intel_opregion_init(dev, 0);

setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev);
Expand Down Expand Up @@ -1538,8 +1536,7 @@ int i915_driver_unload(struct drm_device *dev)
if (dev_priv->regs != NULL)
iounmap(dev_priv->regs);

if (!IS_IGDNG(dev))
intel_opregion_free(dev, 0);
intel_opregion_free(dev, 0);

if (drm_core_check_feature(dev, DRIVER_MODESET)) {
intel_modeset_cleanup(dev);
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
void
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);

void intel_enable_asle (struct drm_device *dev);


/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
Expand Down Expand Up @@ -861,11 +863,13 @@ extern int i915_restore_state(struct drm_device *dev);
extern int intel_opregion_init(struct drm_device *dev, int resume);
extern void intel_opregion_free(struct drm_device *dev, int suspend);
extern void opregion_asle_intr(struct drm_device *dev);
extern void ironlake_opregion_gse_intr(struct drm_device *dev);
extern void opregion_enable_asle(struct drm_device *dev);
#else
static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
static inline void opregion_asle_intr(struct drm_device *dev) { return; }
static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
static inline void opregion_enable_asle(struct drm_device *dev) { return; }
#endif

Expand Down
19 changes: 18 additions & 1 deletion drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,20 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
}
}

/**
* intel_enable_asle - enable ASLE interrupt for OpRegion
*/
void intel_enable_asle (struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;

if (IS_IGDNG(dev))
igdng_enable_display_irq(dev_priv, DE_GSE);
else
i915_enable_pipestat(dev_priv, 1,
I915_LEGACY_BLC_EVENT_ENABLE);
}

/**
* i915_pipe_enabled - check if a pipe is enabled
* @dev: DRM device
Expand Down Expand Up @@ -288,6 +302,9 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
DRM_WAKEUP(&dev_priv->irq_queue);
}

if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev);

de_iir = new_de_iir;
gt_iir = new_gt_iir;
}
Expand Down Expand Up @@ -992,7 +1009,7 @@ static int igdng_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
/* enable kind of interrupts always enabled */
u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */;
u32 render_mask = GT_USER_INTERRUPT;

dev_priv->irq_mask_reg = ~display_mask;
Expand Down
74 changes: 72 additions & 2 deletions drivers/gpu/drm/i915/i915_opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ struct opregion_asle {
#define ASLE_BACKLIGHT_FAIL (2<<12)
#define ASLE_PFIT_FAIL (2<<14)
#define ASLE_PWM_FREQ_FAIL (2<<16)
#define ASLE_ALS_ILLUM_FAILED (1<<10)
#define ASLE_BACKLIGHT_FAILED (1<<12)
#define ASLE_PFIT_FAILED (1<<14)
#define ASLE_PWM_FREQ_FAILED (1<<16)

/* ASLE backlight brightness to set */
#define ASLE_BCLP_VALID (1<<31)
Expand Down Expand Up @@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_device *dev)
asle->aslc = asle_stat;
}

static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle;
u32 cpu_pwm_ctl, pch_pwm_ctl2;
u32 max_backlight, level;

if (!(bclp & ASLE_BCLP_VALID))
return ASLE_BACKLIGHT_FAILED;

bclp &= ASLE_BCLP_MSK;
if (bclp < 0 || bclp > 255)
return ASLE_BACKLIGHT_FAILED;

cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL);
pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
/* get the max PWM frequency */
max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK;
/* calculate the expected PMW frequency */
level = (bclp * max_backlight) / 255;
/* reserve the high 16 bits */
cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK);
/* write the updated PWM frequency */
I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level);

asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID;

return 0;
}

void ironlake_opregion_gse_intr(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_asle *asle = dev_priv->opregion.asle;
u32 asle_stat = 0;
u32 asle_req;

if (!asle)
return;

asle_req = asle->aslc & ASLE_REQ_MSK;

if (!asle_req) {
DRM_DEBUG_DRIVER("non asle set request??\n");
return;
}

if (asle_req & ASLE_SET_ALS_ILLUM) {
DRM_DEBUG_DRIVER("Illum is not supported\n");
asle_stat |= ASLE_ALS_ILLUM_FAILED;
}

if (asle_req & ASLE_SET_BACKLIGHT)
asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp);

if (asle_req & ASLE_SET_PFIT) {
DRM_DEBUG_DRIVER("Pfit is not supported\n");
asle_stat |= ASLE_PFIT_FAILED;
}

if (asle_req & ASLE_SET_PWM_FREQ) {
DRM_DEBUG_DRIVER("PWM freq is not supported\n");
asle_stat |= ASLE_PWM_FREQ_FAILED;
}

asle->aslc = asle_stat;
}
#define ASLE_ALS_EN (1<<0)
#define ASLE_BLC_EN (1<<1)
#define ASLE_PFIT_EN (1<<2)
Expand All @@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_device *dev)
unsigned long irqflags;

spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
i915_enable_pipestat(dev_priv, 1,
I915_LEGACY_BLC_EVENT_ENABLE);
intel_enable_asle(dev);
spin_unlock_irqrestore(&dev_priv->user_irq_lock,
irqflags);
}
Expand Down

0 comments on commit 01c6688

Please sign in to comment.