From patchwork Tue Dec 21 21:10:23 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jesse Barnes X-Patchwork-Id: 425121 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oBLLHa3J024826 for ; Tue, 21 Dec 2010 21:17:56 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 91D2A9ED8C for ; Tue, 21 Dec 2010 13:17:36 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 21 Dec 2010 21:17:56 +0000 (UTC) X-Greylist: delayed 402 seconds by postgrey-1.31 at gabe; Tue, 21 Dec 2010 13:17:13 PST Received: from oproxy3-pub.bluehost.com (oproxy3-pub.bluehost.com [69.89.21.8]) by gabe.freedesktop.org (Postfix) with SMTP id F0DAC9E966 for ; Tue, 21 Dec 2010 13:17:13 -0800 (PST) Received: (qmail 7569 invoked by uid 0); 21 Dec 2010 21:10:26 -0000 Received: from unknown (HELO box514.bluehost.com) (74.220.219.114) by oproxy3.bluehost.com with SMTP; 21 Dec 2010 21:10:26 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=virtuousgeek.org; h=Received:Date:From:To:Subject:Message-ID:X-Mailer:Mime-Version:Content-Type:Content-Transfer-Encoding:X-Identified-User; b=er2QFLA8LwHR5wv3AKiDBQYSoT2WClSstxxLB+gunL/guyLsOZHhENCeYNa96tzKn0hMI+68tuO0R3T80n2CCirnpya6DJM9IubBL09YPFwfXpqxNXEamFUEg8JVRiKj; Received: from c-67-174-193-198.hsd1.ca.comcast.net ([67.174.193.198] helo=jbarnes-desktop) by box514.bluehost.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.69) (envelope-from ) id 1PV9TW-0006gZ-7c for intel-gfx@lists.freedesktop.org; Tue, 21 Dec 2010 14:10:26 -0700 Date: Tue, 21 Dec 2010 13:10:23 -0800 From: Jesse Barnes To: intel-gfx@lists.freedesktop.org Message-ID: <20101221131023.2f94306e@jbarnes-desktop> X-Mailer: Claws Mail 3.7.6 (GTK+ 2.18.9; x86_64-redhat-linux-gnu) Mime-Version: 1.0 X-Identified-User: {10642:box514.bluehost.com:virtuous:virtuousgeek.org} {sentby:smtp auth 67.174.193.198 authed with jbarnes@virtuousgeek.org} Subject: [Intel-gfx] [PATCH] drm/i915: support low power watermarks on Ironlake X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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 diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d60860e..20821e6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2345,8 +2345,13 @@ /* Memory latency timer register */ #define MLTR_ILK 0x11222 +#define MLTR_WM1_SHIFT 0 +#define MLTR_WM2_SHIFT 8 /* the unit of memory self-refresh latency time is 0.5us */ #define ILK_SRLT_MASK 0x3f +#define ILK_LATENCY(shift) (I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK) +#define ILK_READ_WM1_LATENCY() ILK_LATENCY(MLTR_WM1_SHIFT) +#define ILK_READ_WM2_LATENCY() ILK_LATENCY(MLTR_WM2_SHIFT) /* define the fifo size on Ironlake */ #define ILK_DISPLAY_FIFO 128 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8806596..49f423d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3456,101 +3456,6 @@ static bool ironlake_compute_wm0(struct drm_device *dev, return true; } -static void ironlake_update_wm(struct drm_device *dev, - int planea_clock, int planeb_clock, - int sr_hdisplay, int sr_htotal, - int pixel_size) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int plane_wm, cursor_wm, enabled; - int tmp; - - enabled = 0; - if (ironlake_compute_wm0(dev, 0, - &ironlake_display_wm_info, - ILK_LP0_PLANE_LATENCY, - &ironlake_cursor_wm_info, - ILK_LP0_CURSOR_LATENCY, - &plane_wm, &cursor_wm)) { - I915_WRITE(WM0_PIPEA_ILK, - (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); - DRM_DEBUG_KMS("FIFO watermarks For pipe A -" - " plane %d, " "cursor: %d\n", - plane_wm, cursor_wm); - enabled++; - } - - if (ironlake_compute_wm0(dev, 1, - &ironlake_display_wm_info, - ILK_LP0_PLANE_LATENCY, - &ironlake_cursor_wm_info, - ILK_LP0_CURSOR_LATENCY, - &plane_wm, &cursor_wm)) { - I915_WRITE(WM0_PIPEB_ILK, - (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); - DRM_DEBUG_KMS("FIFO watermarks For pipe B -" - " plane %d, cursor: %d\n", - plane_wm, cursor_wm); - enabled++; - } - - /* - * Calculate and update the self-refresh watermark only when one - * display plane is used. - */ - tmp = 0; - if (enabled == 1) { - unsigned long line_time_us; - int small, large, plane_fbc; - int sr_clock, entries; - int line_count, line_size; - /* Read the self-refresh latency. The unit is 0.5us */ - int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; - - sr_clock = planea_clock ? planea_clock : planeb_clock; - line_time_us = (sr_htotal * 1000) / sr_clock; - - /* Use ns/us then divide to preserve precision */ - line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) - / 1000; - line_size = sr_hdisplay * pixel_size; - - /* Use the minimum of the small and large buffer method for primary */ - small = ((sr_clock * pixel_size / 1000) * (ilk_sr_latency * 500)) / 1000; - large = line_count * line_size; - - entries = DIV_ROUND_UP(min(small, large), - ironlake_display_srwm_info.cacheline_size); - - plane_fbc = entries * 64; - plane_fbc = DIV_ROUND_UP(plane_fbc, line_size); - - plane_wm = entries + ironlake_display_srwm_info.guard_size; - if (plane_wm > (int)ironlake_display_srwm_info.max_wm) - plane_wm = ironlake_display_srwm_info.max_wm; - - /* calculate the self-refresh watermark for display cursor */ - entries = line_count * pixel_size * 64; - entries = DIV_ROUND_UP(entries, - ironlake_cursor_srwm_info.cacheline_size); - - cursor_wm = entries + ironlake_cursor_srwm_info.guard_size; - if (cursor_wm > (int)ironlake_cursor_srwm_info.max_wm) - cursor_wm = ironlake_cursor_srwm_info.max_wm; - - /* configure watermark and enable self-refresh */ - tmp = (WM1_LP_SR_EN | - (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | - (plane_fbc << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - DRM_DEBUG_KMS("self-refresh watermark: display plane %d, fbc lines %d," - " cursor %d\n", plane_wm, plane_fbc, cursor_wm); - } - I915_WRITE(WM1_LP_ILK, tmp); - /* XXX setup WM2 and WM3 */ -} - /* * Check the wm result. * @@ -3559,9 +3464,9 @@ static void ironlake_update_wm(struct drm_device *dev, * must be disabled. * * Also return true if all of those watermark values is 0, which is set by - * sandybridge_compute_srwm, to indicate the latency is ZERO. + * ironlake_compute_srwm, to indicate the latency is ZERO. */ -static bool sandybridge_check_srwm(struct drm_device *dev, int level, +static bool ironlake_check_srwm(struct drm_device *dev, int level, int fbc_wm, int display_wm, int cursor_wm) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -3602,7 +3507,7 @@ static bool sandybridge_check_srwm(struct drm_device *dev, int level, /* * Compute watermark values of WM[1-3], */ -static bool sandybridge_compute_srwm(struct drm_device *dev, int level, +static bool ironlake_compute_srwm(struct drm_device *dev, int level, int hdisplay, int htotal, int pixel_size, int clock, int latency_ns, int *fbc_wm, int *display_wm, int *cursor_wm) @@ -3612,6 +3517,20 @@ static bool sandybridge_compute_srwm(struct drm_device *dev, int level, int small, large; int entries; int line_count, line_size; + int disp_cacheline_size, disp_guard_size; + int cur_cacheline_size, cur_guard_size; + + if (IS_GEN6(dev)) { + disp_cacheline_size = sandybridge_display_srwm_info.cacheline_size; + disp_guard_size = sandybridge_display_srwm_info.guard_size; + cur_cacheline_size = sandybridge_cursor_srwm_info.cacheline_size; + cur_guard_size = sandybridge_cursor_srwm_info.guard_size; + } else { + disp_cacheline_size = ironlake_display_srwm_info.cacheline_size; + disp_guard_size = ironlake_display_srwm_info.guard_size; + cur_cacheline_size = ironlake_cursor_srwm_info.cacheline_size; + cur_guard_size = ironlake_cursor_srwm_info.guard_size; + } if (!latency_ns) { *fbc_wm = *display_wm = *cursor_wm = 0; @@ -3626,9 +3545,8 @@ static bool sandybridge_compute_srwm(struct drm_device *dev, int level, small = ((clock * pixel_size / 1000) * latency_ns) / 1000; large = line_count * line_size; - entries = DIV_ROUND_UP(min(small, large), - sandybridge_display_srwm_info.cacheline_size); - *display_wm = entries + sandybridge_display_srwm_info.guard_size; + entries = DIV_ROUND_UP(min(small, large), disp_cacheline_size); + *display_wm = entries + disp_guard_size; /* * Spec said: @@ -3638,14 +3556,96 @@ static bool sandybridge_compute_srwm(struct drm_device *dev, int level, /* calculate the self-refresh watermark for display cursor */ entries = line_count * pixel_size * 64; - entries = DIV_ROUND_UP(entries, - sandybridge_cursor_srwm_info.cacheline_size); - *cursor_wm = entries + sandybridge_cursor_srwm_info.guard_size; + entries = DIV_ROUND_UP(entries, cur_cacheline_size); + *cursor_wm = entries + cur_guard_size; - return sandybridge_check_srwm(dev, level, + return ironlake_check_srwm(dev, level, *fbc_wm, *display_wm, *cursor_wm); } +static void ironlake_update_wm(struct drm_device *dev, + int planea_clock, int planeb_clock, + int hdisplay, int htotal, + int pixel_size) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int fbc_wm, plane_wm, cursor_wm, enabled; + int clock; + + enabled = 0; + if (ironlake_compute_wm0(dev, 0, + &ironlake_display_wm_info, + ILK_LP0_PLANE_LATENCY, + &ironlake_cursor_wm_info, + ILK_LP0_CURSOR_LATENCY, + &plane_wm, &cursor_wm)) { + I915_WRITE(WM0_PIPEA_ILK, + (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); + DRM_DEBUG_KMS("FIFO watermarks For pipe A -" + " plane %d, " "cursor: %d\n", + plane_wm, cursor_wm); + enabled++; + } + + if (ironlake_compute_wm0(dev, 1, + &ironlake_display_wm_info, + ILK_LP0_PLANE_LATENCY, + &ironlake_cursor_wm_info, + ILK_LP0_CURSOR_LATENCY, + &plane_wm, &cursor_wm)) { + I915_WRITE(WM0_PIPEB_ILK, + (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); + DRM_DEBUG_KMS("FIFO watermarks For pipe B -" + " plane %d, cursor: %d\n", + plane_wm, cursor_wm); + enabled++; + } + + /* + * Calculate and update the self-refresh watermark only when one + * display plane is used. + */ + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + + if (enabled != 1) + return; + + clock = planea_clock ? planea_clock : planeb_clock; + + /* WM1 */ + if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, + clock, ILK_READ_WM1_LATENCY() * 500, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM1_LP_ILK, + WM1_LP_SR_EN | + (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); + + /* WM2 */ + if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size, + clock, ILK_READ_WM2_LATENCY() * 500, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM2_LP_ILK, + WM2_LP_EN | + (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); + + /* + * WM3 is unsupported on ILK, probably because we don't have latency + * data for that power state + */ +} + static void sandybridge_update_wm(struct drm_device *dev, int planea_clock, int planeb_clock, int hdisplay, int htotal, @@ -3701,7 +3701,7 @@ static void sandybridge_update_wm(struct drm_device *dev, clock = planea_clock ? planea_clock : planeb_clock; /* WM1 */ - if (!sandybridge_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, + if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, clock, SNB_READ_WM1_LATENCY() * 500, &fbc_wm, &plane_wm, &cursor_wm)) return; @@ -3714,7 +3714,7 @@ static void sandybridge_update_wm(struct drm_device *dev, cursor_wm); /* WM2 */ - if (!sandybridge_compute_srwm(dev, 2, + if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size, clock, SNB_READ_WM2_LATENCY() * 500, &fbc_wm, &plane_wm, &cursor_wm)) @@ -3728,7 +3728,7 @@ static void sandybridge_update_wm(struct drm_device *dev, cursor_wm); /* WM3 */ - if (!sandybridge_compute_srwm(dev, 3, + if (!ironlake_compute_srwm(dev, 3, hdisplay, htotal, pixel_size, clock, SNB_READ_WM3_LATENCY() * 500, &fbc_wm, &plane_wm, &cursor_wm))