aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-10-28 01:10:00 -0400
committerEric Anholt <eric@anholt.net>2009-11-05 17:49:13 -0500
commit01c66889c14aa163c49355b3be2ccfb214500599 (patch)
tree278e3e9a1fb0001d61d531804e8db6ea83bc712c
parent1dc7546d1a73664e5d117715b214bea9cae5951c (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.c7
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c19
-rw-r--r--drivers/gpu/drm/i915/i915_opregion.c74
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);
733void 733void
734i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); 734i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
735 735
736void intel_enable_asle (struct drm_device *dev);
737
736 738
737/* i915_mem.c */ 739/* i915_mem.c */
738extern int i915_mem_alloc(struct drm_device *dev, void *data, 740extern int i915_mem_alloc(struct drm_device *dev, void *data,
@@ -861,11 +863,13 @@ extern int i915_restore_state(struct drm_device *dev);
861extern int intel_opregion_init(struct drm_device *dev, int resume); 863extern int intel_opregion_init(struct drm_device *dev, int resume);
862extern void intel_opregion_free(struct drm_device *dev, int suspend); 864extern void intel_opregion_free(struct drm_device *dev, int suspend);
863extern void opregion_asle_intr(struct drm_device *dev); 865extern void opregion_asle_intr(struct drm_device *dev);
866extern void ironlake_opregion_gse_intr(struct drm_device *dev);
864extern void opregion_enable_asle(struct drm_device *dev); 867extern void opregion_enable_asle(struct drm_device *dev);
865#else 868#else
866static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; } 869static inline int intel_opregion_init(struct drm_device *dev, int resume) { return 0; }
867static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; } 870static inline void intel_opregion_free(struct drm_device *dev, int suspend) { return; }
868static inline void opregion_asle_intr(struct drm_device *dev) { return; } 871static inline void opregion_asle_intr(struct drm_device *dev) { return; }
872static inline void ironlake_opregion_gse_intr(struct drm_device *dev) { return; }
869static inline void opregion_enable_asle(struct drm_device *dev) { return; } 873static 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 */
162void 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
250static 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
280void 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 }