From patchwork Fri Jan 29 19:10:20 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Conklin X-Patchwork-Id: 44014 X-Patchwork-Delegate: apw@canonical.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 24E88B7D2B for ; Sat, 30 Jan 2010 06:10:42 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1NawEl-0004DC-Iu; Fri, 29 Jan 2010 19:10:35 +0000 Received: from mail-vw0-f49.google.com ([209.85.212.49]) by chlorine.canonical.com with esmtp (Exim 4.69) (envelope-from ) id 1NawEj-00048f-De for kernel-team@lists.ubuntu.com; Fri, 29 Jan 2010 19:10:33 +0000 Received: by mail-vw0-f49.google.com with SMTP id 3so621748vws.8 for ; Fri, 29 Jan 2010 11:10:33 -0800 (PST) Received: by 10.220.126.194 with SMTP id d2mr1131380vcs.78.1264792231282; Fri, 29 Jan 2010 11:10:31 -0800 (PST) Received: from localhost (ip-64-32-163-20.atl.megapath.net [64.32.163.20]) by mx.google.com with ESMTPS id 33sm29863243vws.11.2010.01.29.11.10.29 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 29 Jan 2010 11:10:30 -0800 (PST) From: Steve Conklin To: kernel-team@lists.ubuntu.com Subject: [LUCID][PATCH 2/2] drm/i915: Add ACPI OpRegion support for Ironlake Date: Fri, 29 Jan 2010 13:10:20 -0600 Message-Id: <1264792220-8478-3-git-send-email-sconklin@canonical.com> X-Mailer: git-send-email 1.6.3.3 In-Reply-To: <1264792220-8478-2-git-send-email-sconklin@canonical.com> References: <1264792220-8478-1-git-send-email-sconklin@canonical.com> <1264792220-8478-2-git-send-email-sconklin@canonical.com> Cc: Steve Conklin X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.9 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com 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 Tested-by: Zhao Yakui [zhenyuw: cleanups, fix typo for checking GSE irq and convert to current irq handling logic.] Signed-off-by: Zhenyu Wang Signed-off-by: Eric Anholt Signed-off-by: Steve Conklin --- drivers/gpu/drm/i915/i915_dma.c | 7 +-- drivers/gpu/drm/i915/i915_drv.h | 4 ++ drivers/gpu/drm/i915/i915_irq.c | 21 +++++++++- drivers/gpu/drm/i915/i915_opregion.c | 74 +++++++++++++++++++++++++++++++++- 4 files changed, 97 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bc2db7d..f419c45 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1490,9 +1490,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); @@ -1536,8 +1534,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); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d125e86..7e76565 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -741,6 +741,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, @@ -866,11 +868,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 diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c5742bd..500474b 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) } /** + * 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 * @pipe: pipe to check @@ -285,10 +299,13 @@ 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); + /* check event from PCH */ if ((de_iir & DE_PCH_EVENT) && (pch_iir & SDE_HOTPLUG_MASK)) { - queue_work(dev_priv->wq, &dev_priv->hotplug_work); + queue_work(dev_priv->wq, &dev_priv->hotplug_work); } I915_WRITE(SDEIIR, pch_iir); @@ -1004,7 +1021,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; u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; diff --git a/drivers/gpu/drm/i915/i915_opregion.c b/drivers/gpu/drm/i915/i915_opregion.c index 2d51935..074cfce 100644 --- a/drivers/gpu/drm/i915/i915_opregion.c +++ b/drivers/gpu/drm/i915/i915_opregion.c @@ -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); }