From patchwork Tue Jan 7 16:01:34 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jani Nikula X-Patchwork-Id: 3449071 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 7DD5CC02DC for ; Tue, 7 Jan 2014 16:07:28 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 30D4720114 for ; Tue, 7 Jan 2014 16:07:27 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id D055520109 for ; Tue, 7 Jan 2014 16:07:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A8944FA82D for ; Tue, 7 Jan 2014 08:07:25 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id D127CFAC05 for ; Tue, 7 Jan 2014 08:07:13 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 07 Jan 2014 08:06:02 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,619,1384329600"; d="scan'208";a="462962073" Received: from unknown (HELO localhost) ([10.252.122.126]) by orsmga002.jf.intel.com with ESMTP; 07 Jan 2014 08:05:21 -0800 From: Jani Nikula To: intel-gfx@lists.freedesktop.org, vathsala.nagaraju@intel.com Date: Tue, 7 Jan 2014 18:01:34 +0200 Message-Id: X-Mailer: git-send-email 1.7.10.4 In-Reply-To: References: In-Reply-To: References: Organization: Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo Cc: jani.nikula@intel.com, rajneesh.bhardwaj@intel.com, naveen.m@intel.com Subject: [Intel-gfx] [PATCH 2/2] drm/i915: initialize backlight max from vbt X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_panel.c | 197 +++++++++++++++++++++++++++++++----- 2 files changed, 170 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a699efd..344f717 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4531,6 +4531,7 @@ #define SOUTH_CHICKEN2 0xc2004 #define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13) #define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define PWM_GRANULARITY (1<<5) /* LPT */ #define DPLS_EDP_PPS_FIX_DIS (1<<0) #define _FDI_RXA_CHICKEN 0xc200c diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 1cf8085f..c020ab0 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -916,10 +916,93 @@ static void intel_backlight_device_unregister(struct intel_connector *connector) #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ /* - * Note: The setup hooks can't assume pipe is set! + * HSW/BDW: This value represents the period of the PWM stream in clock periods + * multiplied by 128 (default increment) or 16 (alternate increment, selected in + * LPT SOUTH_CHICKEN2 register bit 5). * - * XXX: Query mode clock or hardware clock and program PWM modulation frequency - * appropriately when it's 0. Use VBT and/or sane defaults. + * XXX: This only works when driving the PCH PWM. When driving the CPU PWM on + * the utility pin, the granularity needs to be determined by BLC_PWM_CTL bit + * 27. + */ +static int hsw_hz_to_pwm(struct drm_device *dev, u16 pwm_freq_hz) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 mul, clock; + + if (I915_READ(SOUTH_CHICKEN2) & PWM_GRANULARITY) + mul = 16; + else + mul = 128; + + if (dev_priv->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) + clock = MHz(135); /* LPT:H */ + else + clock = MHz(24); /* LPT:LP */ + + return clock / (pwm_freq_hz * mul); +} + +/* + * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH + * display raw clocks multiplied by 128. + */ +static int pch_hz_to_pwm(struct drm_device *dev, u16 pwm_freq_hz) +{ + int clock = MHz(intel_pch_rawclk(dev)); + + return clock / (pwm_freq_hz * 128); +} + +/* + * Gen2: This field determines the number of time base events (display core + * clock frequency/32) in total for a complete cycle of modulated backlight + * control. + * + * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock) + * divided by 32. + */ +static int i9xx_hz_to_pwm(struct drm_device *dev, u16 pwm_freq_hz) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int clock; + + if (IS_PINEVIEW(dev)) + clock = intel_hrawclk(dev); + else + clock = 1000 * dev_priv->display.get_display_clock_speed(dev); + + return clock / (pwm_freq_hz * 32); +} + +/* + * Gen4: This value represents the period of the PWM stream in display core + * clocks multiplied by 128. + */ +static int i965_hz_to_pwm(struct drm_device *dev, u16 pwm_freq_hz) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int clock = 1000 * dev_priv->display.get_display_clock_speed(dev); + + return clock / (pwm_freq_hz * 128); +} + +/* + * VLV: This value represents the period of the PWM stream in display core + * clocks ([DevCTG] 100MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks + * multiplied by 16. + * + * XXX: Where is this selected??? + */ +static int vlv_hz_to_pwm(struct drm_device *dev, u16 pwm_freq_hz) +{ + if (1) + return MHz(25) / (pwm_freq_hz * 16); + else + return MHz(100) / (pwm_freq_hz * 128); +} + +/* + * Note: The setup hooks can't assume pipe is set! */ static int bdw_setup_backlight(struct intel_connector *connector) { @@ -933,8 +1016,18 @@ static int bdw_setup_backlight(struct intel_connector *connector) pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); panel->backlight.max = pch_ctl2 >> 16; - if (!panel->backlight.max) - return -ENODEV; + + if (!panel->backlight.max) { + u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + + if (!pwm_freq_hz) + return -ENODEV; + + DRM_DEBUG_KMS("setting backlight frequency to %u Hz from VBT\n", + pwm_freq_hz); + + panel->backlight.max = hsw_hz_to_pwm(dev, pwm_freq_hz); + } val = bdw_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); @@ -957,8 +1050,21 @@ static int pch_setup_backlight(struct intel_connector *connector) pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2); panel->backlight.max = pch_ctl2 >> 16; - if (!panel->backlight.max) - return -ENODEV; + + if (!panel->backlight.max) { + u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + + if (!pwm_freq_hz) + return -ENODEV; + + DRM_DEBUG_KMS("setting backlight frequency to %u Hz from VBT\n", + pwm_freq_hz); + + if (IS_HASWELL(dev)) + panel->backlight.max = hsw_hz_to_pwm(dev, pwm_freq_hz); + else + panel->backlight.max = pch_hz_to_pwm(dev, pwm_freq_hz); + } val = pch_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); @@ -986,12 +1092,23 @@ static int i9xx_setup_backlight(struct intel_connector *connector) panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV; panel->backlight.max = ctl >> 17; + + if (!panel->backlight.max) { + u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + + if (!pwm_freq_hz) + return -ENODEV; + + DRM_DEBUG_KMS("setting backlight frequency to %u Hz from VBT\n", + pwm_freq_hz); + + panel->backlight.max = i9xx_hz_to_pwm(dev, pwm_freq_hz); + panel->backlight.max >>= 1; + } + if (panel->backlight.combination_mode) panel->backlight.max *= 0xff; - if (!panel->backlight.max) - return -ENODEV; - val = i9xx_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); @@ -1013,12 +1130,22 @@ static int i965_setup_backlight(struct intel_connector *connector) ctl = I915_READ(BLC_PWM_CTL); panel->backlight.max = ctl >> 16; + + if (!panel->backlight.max) { + u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + + if (!pwm_freq_hz) + return -ENODEV; + + DRM_DEBUG_KMS("setting backlight frequency to %u Hz from VBT\n", + pwm_freq_hz); + + panel->backlight.max = i965_hz_to_pwm(dev, pwm_freq_hz); + } + if (panel->backlight.combination_mode) panel->backlight.max *= 0xff; - if (!panel->backlight.max) - return -ENODEV; - val = i9xx_get_backlight(connector); panel->backlight.level = intel_panel_compute_brightness(connector, val); @@ -1033,30 +1160,44 @@ static int vlv_setup_backlight(struct intel_connector *connector) struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_panel *panel = &connector->panel; - enum pipe pipe; + enum pipe p, pipe = PIPE_A; u32 ctl, ctl2, val; - for_each_pipe(pipe) { - u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); - - /* Skip if the modulation freq is already set */ - if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) - continue; + /* prefer a pipe that's configured and enabled, fall back to A */ + for_each_pipe(p) { + ctl = I915_READ(VLV_BLC_PWM_CTL(p)); + if (ctl >> 16) { + pipe = p; - cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | - cur_val); + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(p)); + if (ctl2 & BLM_PWM_ENABLE) + break; + } } - ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); + ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe)); panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965; - ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); + ctl = I915_READ(VLV_BLC_PWM_CTL(pipe)); panel->backlight.max = ctl >> 16; - if (!panel->backlight.max) - return -ENODEV; - val = _vlv_get_backlight(dev, PIPE_A); + if (!panel->backlight.max) { + u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz; + + if (!pwm_freq_hz) { + pwm_freq_hz = 400; + DRM_DEBUG_KMS("defaulting to %u Hz backlight on %s\n", + pwm_freq_hz, + drm_get_connector_name(&connector->base)); + } else { + DRM_DEBUG_KMS("setting backlight frequency to %u Hz from VBT\n", + pwm_freq_hz); + } + + panel->backlight.max = vlv_hz_to_pwm(dev, pwm_freq_hz); + } + + val = _vlv_get_backlight(dev, pipe); panel->backlight.level = intel_panel_compute_brightness(connector, val); panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&