drm/i915: Add ACPI OpRegion support for Ironlake
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 <yakui.zhao@intel.com> Tested-by: Zhao Yakui <yakui.zhao@intel.com> [zhenyuw: cleanups, fix typo for checking GSE irq and convert to current irq handling logic.] Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
1dc7546d1a
commit
01c66889c1
|
@ -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);
|
||||
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue