diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2009-10-28 01:10:00 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-11-05 17:49:13 -0500 |
commit | 01c66889c14aa163c49355b3be2ccfb214500599 (patch) | |
tree | 278e3e9a1fb0001d61d531804e8db6ea83bc712c | |
parent | 1dc7546d1a73664e5d117715b214bea9cae5951c (diff) |
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>
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_opregion.c | 74 |
4 files changed, 96 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 794ded2394cc..093146bacf84 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1492,9 +1492,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | /* Must be done after probing outputs */ | 1494 | /* Must be done after probing outputs */ |
1495 | /* FIXME: verify on IGDNG */ | 1495 | intel_opregion_init(dev, 0); |
1496 | if (!IS_IGDNG(dev)) | ||
1497 | intel_opregion_init(dev, 0); | ||
1498 | 1496 | ||
1499 | setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, | 1497 | setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, |
1500 | (unsigned long) dev); | 1498 | (unsigned long) dev); |
@@ -1538,8 +1536,7 @@ int i915_driver_unload(struct drm_device *dev) | |||
1538 | if (dev_priv->regs != NULL) | 1536 | if (dev_priv->regs != NULL) |
1539 | iounmap(dev_priv->regs); | 1537 | iounmap(dev_priv->regs); |
1540 | 1538 | ||
1541 | if (!IS_IGDNG(dev)) | 1539 | intel_opregion_free(dev, 0); |
1542 | intel_opregion_free(dev, 0); | ||
1543 | 1540 | ||
1544 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1541 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
1545 | intel_modeset_cleanup(dev); | 1542 | intel_modeset_cleanup(dev); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f9f339aafdee..210d0f690dbb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -733,6 +733,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); | |||
733 | void | 733 | void |
734 | i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); | 734 | i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); |
735 | 735 | ||
736 | void intel_enable_asle (struct drm_device *dev); | ||
737 | |||
736 | 738 | ||
737 | /* i915_mem.c */ | 739 | /* i915_mem.c */ |
738 | extern int i915_mem_alloc(struct drm_device *dev, void *data, | 740 | extern int i915_mem_alloc(struct drm_device *dev, void *data, |
@@ -861,11 +863,13 @@ extern int i915_restore_state(struct drm_device *dev); | |||
861 | extern int intel_opregion_init(struct drm_device *dev, int resume); | 863 | extern int intel_opregion_init(struct drm_device *dev, int resume); |
862 | extern void intel_opregion_free(struct drm_device *dev, int suspend); | 864 | extern void intel_opregion_free(struct drm_device *dev, int suspend); |
863 | extern void opregion_asle_intr(struct drm_device *dev); | 865 | extern void opregion_asle_intr(struct drm_device *dev); |
866 | extern void ironlake_opregion_gse_intr(struct drm_device *dev); | ||
864 | extern void opregion_enable_asle(struct drm_device *dev); | 867 | extern void opregion_enable_asle(struct drm_device *dev); |
865 | #else | 868 | #else |
866 | static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } | 869 | static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } |
867 | static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } | 870 | static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } |
868 | static inline void opregion_asle_intr(struct drm_device *dev) { return; } | 871 | static inline void opregion_asle_intr(struct drm_device *dev) { return; } |
872 | static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; } | ||
869 | static inline void opregion_enable_asle(struct drm_device *dev) { return; } | 873 | static inline void opregion_enable_asle(struct drm_device *dev) { return; } |
870 | #endif | 874 | #endif |
871 | 875 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0887581fa650..ce337be4bbcd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -157,6 +157,20 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) | |||
157 | } | 157 | } |
158 | 158 | ||
159 | /** | 159 | /** |
160 | * intel_enable_asle - enable ASLE interrupt for OpRegion | ||
161 | */ | ||
162 | void intel_enable_asle (struct drm_device *dev) | ||
163 | { | ||
164 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
165 | |||
166 | if (IS_IGDNG(dev)) | ||
167 | igdng_enable_display_irq(dev_priv, DE_GSE); | ||
168 | else | ||
169 | i915_enable_pipestat(dev_priv, 1, | ||
170 | I915_LEGACY_BLC_EVENT_ENABLE); | ||
171 | } | ||
172 | |||
173 | /** | ||
160 | * i915_pipe_enabled - check if a pipe is enabled | 174 | * i915_pipe_enabled - check if a pipe is enabled |
161 | * @dev: DRM device | 175 | * @dev: DRM device |
162 | * @pipe: pipe to check | 176 | * @pipe: pipe to check |
@@ -288,6 +302,9 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) | |||
288 | DRM_WAKEUP(&dev_priv->irq_queue); | 302 | DRM_WAKEUP(&dev_priv->irq_queue); |
289 | } | 303 | } |
290 | 304 | ||
305 | if (de_iir & DE_GSE) | ||
306 | ironlake_opregion_gse_intr(dev); | ||
307 | |||
291 | de_iir = new_de_iir; | 308 | de_iir = new_de_iir; |
292 | gt_iir = new_gt_iir; | 309 | gt_iir = new_gt_iir; |
293 | } | 310 | } |
@@ -992,7 +1009,7 @@ static int igdng_irq_postinstall(struct drm_device *dev) | |||
992 | { | 1009 | { |
993 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 1010 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
994 | /* enable kind of interrupts always enabled */ | 1011 | /* enable kind of interrupts always enabled */ |
995 | u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */; | 1012 | u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */; |
996 | u32 render_mask = GT_USER_INTERRUPT; | 1013 | u32 render_mask = GT_USER_INTERRUPT; |
997 | 1014 | ||
998 | dev_priv->irq_mask_reg = ~display_mask; | 1015 | dev_priv->irq_mask_reg = ~display_mask; |
diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 9032bda35e2a..313a1a11afab 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c | |||
@@ -118,6 +118,10 @@ struct opregion_asle { | |||
118 | #define ASLE_BACKLIGHT_FAIL (2<<12) | 118 | #define ASLE_BACKLIGHT_FAIL (2<<12) |
119 | #define ASLE_PFIT_FAIL (2<<14) | 119 | #define ASLE_PFIT_FAIL (2<<14) |
120 | #define ASLE_PWM_FREQ_FAIL (2<<16) | 120 | #define ASLE_PWM_FREQ_FAIL (2<<16) |
121 | #define ASLE_ALS_ILLUM_FAILED (1<<10) | ||
122 | #define ASLE_BACKLIGHT_FAILED (1<<12) | ||
123 | #define ASLE_PFIT_FAILED (1<<14) | ||
124 | #define ASLE_PWM_FREQ_FAILED (1<<16) | ||
121 | 125 | ||
122 | /* ASLE backlight brightness to set */ | 126 | /* ASLE backlight brightness to set */ |
123 | #define ASLE_BCLP_VALID (1<<31) | 127 | #define ASLE_BCLP_VALID (1<<31) |
@@ -243,6 +247,73 @@ void opregion_asle_intr(struct drm_device *dev) | |||
243 | asle->aslc = asle_stat; | 247 | asle->aslc = asle_stat; |
244 | } | 248 | } |
245 | 249 | ||
250 | static u32 asle_set_backlight_ironlake(struct drm_device *dev, u32 bclp) | ||
251 | { | ||
252 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
253 | struct opregion_asle *asle = dev_priv->opregion.asle; | ||
254 | u32 cpu_pwm_ctl, pch_pwm_ctl2; | ||
255 | u32 max_backlight, level; | ||
256 | |||
257 | if (!(bclp & ASLE_BCLP_VALID)) | ||
258 | return ASLE_BACKLIGHT_FAILED; | ||
259 | |||
260 | bclp &= ASLE_BCLP_MSK; | ||
261 | if (bclp < 0 || bclp > 255) | ||
262 | return ASLE_BACKLIGHT_FAILED; | ||
263 | |||
264 | cpu_pwm_ctl = I915_READ(BLC_PWM_CPU_CTL); | ||
265 | pch_pwm_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); | ||
266 | /* get the max PWM frequency */ | ||
267 | max_backlight = (pch_pwm_ctl2 >> 16) & BACKLIGHT_DUTY_CYCLE_MASK; | ||
268 | /* calculate the expected PMW frequency */ | ||
269 | level = (bclp * max_backlight) / 255; | ||
270 | /* reserve the high 16 bits */ | ||
271 | cpu_pwm_ctl &= ~(BACKLIGHT_DUTY_CYCLE_MASK); | ||
272 | /* write the updated PWM frequency */ | ||
273 | I915_WRITE(BLC_PWM_CPU_CTL, cpu_pwm_ctl | level); | ||
274 | |||
275 | asle->cblv = (bclp*0x64)/0xff | ASLE_CBLV_VALID; | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | void ironlake_opregion_gse_intr(struct drm_device *dev) | ||
281 | { | ||
282 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
283 | struct opregion_asle *asle = dev_priv->opregion.asle; | ||
284 | u32 asle_stat = 0; | ||
285 | u32 asle_req; | ||
286 | |||
287 | if (!asle) | ||
288 | return; | ||
289 | |||
290 | asle_req = asle->aslc & ASLE_REQ_MSK; | ||
291 | |||
292 | if (!asle_req) { | ||
293 | DRM_DEBUG_DRIVER("non asle set request??\n"); | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | if (asle_req & ASLE_SET_ALS_ILLUM) { | ||
298 | DRM_DEBUG_DRIVER("Illum is not supported\n"); | ||
299 | asle_stat |= ASLE_ALS_ILLUM_FAILED; | ||
300 | } | ||
301 | |||
302 | if (asle_req & ASLE_SET_BACKLIGHT) | ||
303 | asle_stat |= asle_set_backlight_ironlake(dev, asle->bclp); | ||
304 | |||
305 | if (asle_req & ASLE_SET_PFIT) { | ||
306 | DRM_DEBUG_DRIVER("Pfit is not supported\n"); | ||
307 | asle_stat |= ASLE_PFIT_FAILED; | ||
308 | } | ||
309 | |||
310 | if (asle_req & ASLE_SET_PWM_FREQ) { | ||
311 | DRM_DEBUG_DRIVER("PWM freq is not supported\n"); | ||
312 | asle_stat |= ASLE_PWM_FREQ_FAILED; | ||
313 | } | ||
314 | |||
315 | asle->aslc = asle_stat; | ||
316 | } | ||
246 | #define ASLE_ALS_EN (1<<0) | 317 | #define ASLE_ALS_EN (1<<0) |
247 | #define ASLE_BLC_EN (1<<1) | 318 | #define ASLE_BLC_EN (1<<1) |
248 | #define ASLE_PFIT_EN (1<<2) | 319 | #define ASLE_PFIT_EN (1<<2) |
@@ -258,8 +329,7 @@ void opregion_enable_asle(struct drm_device *dev) | |||
258 | unsigned long irqflags; | 329 | unsigned long irqflags; |
259 | 330 | ||
260 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); | 331 | spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); |
261 | i915_enable_pipestat(dev_priv, 1, | 332 | intel_enable_asle(dev); |
262 | I915_LEGACY_BLC_EVENT_ENABLE); | ||
263 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, | 333 | spin_unlock_irqrestore(&dev_priv->user_irq_lock, |
264 | irqflags); | 334 | irqflags); |
265 | } | 335 | } |