diff mbox

[1/2] drm/i915: Fixup cursor latency used for IVB lp3 watermarks

Message ID 1355227303-17157-1-git-send-email-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Chris Wilson Dec. 11, 2012, 12:01 p.m. UTC
It operates at twice the declared latency, so adjust the computation to
avoid potential flicker at low power.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50248
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
CC: Jesse Barnes <jbarnes@virtuousgeek.org>
---
 drivers/gpu/drm/i915/intel_pm.c |  117 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 112 insertions(+), 5 deletions(-)

Comments

Jesse Barnes Dec. 11, 2012, 4:27 p.m. UTC | #1
On Tue, 11 Dec 2012 12:01:42 +0000
Chris Wilson <chris@chris-wilson.co.uk> wrote:

> It operates at twice the declared latency, so adjust the computation to
> avoid potential flicker at low power.
> 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=50248
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> CC: Jesse Barnes <jbarnes@virtuousgeek.org>
> ---
>  drivers/gpu/drm/i915/intel_pm.c |  117 +++++++++++++++++++++++++++++++++++++--
>  1 file changed, 112 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 6e9393c..1e61f5e 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -1813,8 +1813,110 @@ static void sandybridge_update_wm(struct drm_device *dev)
>  		enabled |= 2;
>  	}
>  
> -	if ((dev_priv->num_pipe == 3) &&
> -	    g4x_compute_wm0(dev, 2,
> +	/*
> +	 * Calculate and update the self-refresh watermark only when one
> +	 * display plane is used.
> +	 *
> +	 * SNB support 3 levels of watermark.
> +	 *
> +	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
> +	 * and disabled in the descending order
> +	 *
> +	 */
> +	I915_WRITE(WM3_LP_ILK, 0);
> +	I915_WRITE(WM2_LP_ILK, 0);
> +	I915_WRITE(WM1_LP_ILK, 0);
> +
> +	if (!single_plane_enabled(enabled) ||
> +	    dev_priv->sprite_scaling_enabled)
> +		return;
> +	enabled = ffs(enabled) - 1;
> +
> +	/* WM1 */
> +	if (!ironlake_compute_srwm(dev, 1, enabled,
> +				   SNB_READ_WM1_LATENCY() * 500,
> +				   &sandybridge_display_srwm_info,
> +				   &sandybridge_cursor_srwm_info,
> +				   &fbc_wm, &plane_wm, &cursor_wm))
> +		return;
> +
> +	I915_WRITE(WM1_LP_ILK,
> +		   WM1_LP_SR_EN |
> +		   (SNB_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, enabled,
> +				   SNB_READ_WM2_LATENCY() * 500,
> +				   &sandybridge_display_srwm_info,
> +				   &sandybridge_cursor_srwm_info,
> +				   &fbc_wm, &plane_wm, &cursor_wm))
> +		return;
> +
> +	I915_WRITE(WM2_LP_ILK,
> +		   WM2_LP_EN |
> +		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> +		   (fbc_wm << WM1_LP_FBC_SHIFT) |
> +		   (plane_wm << WM1_LP_SR_SHIFT) |
> +		   cursor_wm);
> +
> +	/* WM3 */
> +	if (!ironlake_compute_srwm(dev, 3, enabled,
> +				   SNB_READ_WM3_LATENCY() * 500,
> +				   &sandybridge_display_srwm_info,
> +				   &sandybridge_cursor_srwm_info,
> +				   &fbc_wm, &plane_wm, &cursor_wm))
> +		return;
> +
> +	I915_WRITE(WM3_LP_ILK,
> +		   WM3_LP_EN |
> +		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
> +		   (fbc_wm << WM1_LP_FBC_SHIFT) |
> +		   (plane_wm << WM1_LP_SR_SHIFT) |
> +		   cursor_wm);
> +}
> +
> +static void ivybridge_update_wm(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
> +	u32 val;
> +	int fbc_wm, plane_wm, cursor_wm;
> +	int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
> +	unsigned int enabled;
> +
> +	enabled = 0;
> +	if (g4x_compute_wm0(dev, 0,
> +			    &sandybridge_display_wm_info, latency,
> +			    &sandybridge_cursor_wm_info, latency,
> +			    &plane_wm, &cursor_wm)) {
> +		val = I915_READ(WM0_PIPEA_ILK);
> +		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> +		I915_WRITE(WM0_PIPEA_ILK, val |
> +			   ((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 |= 1;
> +	}
> +
> +	if (g4x_compute_wm0(dev, 1,
> +			    &sandybridge_display_wm_info, latency,
> +			    &sandybridge_cursor_wm_info, latency,
> +			    &plane_wm, &cursor_wm)) {
> +		val = I915_READ(WM0_PIPEB_ILK);
> +		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
> +		I915_WRITE(WM0_PIPEB_ILK, val |
> +			   ((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 |= 2;
> +	}
> +
> +	if (g4x_compute_wm0(dev, 2,
>  			    &sandybridge_display_wm_info, latency,
>  			    &sandybridge_cursor_wm_info, latency,
>  			    &plane_wm, &cursor_wm)) {
> @@ -1877,12 +1979,17 @@ static void sandybridge_update_wm(struct drm_device *dev)
>  		   (plane_wm << WM1_LP_SR_SHIFT) |
>  		   cursor_wm);
>  
> -	/* WM3 */
> +	/* WM3, note we have to correct the cursor latency */
>  	if (!ironlake_compute_srwm(dev, 3, enabled,
>  				   SNB_READ_WM3_LATENCY() * 500,
>  				   &sandybridge_display_srwm_info,
>  				   &sandybridge_cursor_srwm_info,
> -				   &fbc_wm, &plane_wm, &cursor_wm))
> +				   &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
> +	    !ironlake_compute_srwm(dev, 3, enabled,
> +				   2 * SNB_READ_WM3_LATENCY() * 500,
> +				   &sandybridge_display_srwm_info,
> +				   &sandybridge_cursor_srwm_info,
> +				   &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
>  		return;
>  
>  	I915_WRITE(WM3_LP_ILK,
> @@ -3999,7 +4106,7 @@ void intel_init_pm(struct drm_device *dev)
>  		} else if (IS_IVYBRIDGE(dev)) {
>  			/* FIXME: detect B0+ stepping and use auto training */
>  			if (SNB_READ_WM0_LATENCY()) {
> -				dev_priv->display.update_wm = sandybridge_update_wm;
> +				dev_priv->display.update_wm = ivybridge_update_wm;
>  				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
>  			} else {
>  				DRM_DEBUG_KMS("Failed to read display plane latency. "

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Let's see how this works out... will cost a few more mW, but at least
we shouldn't flicker as much.
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6e9393c..1e61f5e 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -1813,8 +1813,110 @@  static void sandybridge_update_wm(struct drm_device *dev)
 		enabled |= 2;
 	}
 
-	if ((dev_priv->num_pipe == 3) &&
-	    g4x_compute_wm0(dev, 2,
+	/*
+	 * Calculate and update the self-refresh watermark only when one
+	 * display plane is used.
+	 *
+	 * SNB support 3 levels of watermark.
+	 *
+	 * WM1/WM2/WM2 watermarks have to be enabled in the ascending order,
+	 * and disabled in the descending order
+	 *
+	 */
+	I915_WRITE(WM3_LP_ILK, 0);
+	I915_WRITE(WM2_LP_ILK, 0);
+	I915_WRITE(WM1_LP_ILK, 0);
+
+	if (!single_plane_enabled(enabled) ||
+	    dev_priv->sprite_scaling_enabled)
+		return;
+	enabled = ffs(enabled) - 1;
+
+	/* WM1 */
+	if (!ironlake_compute_srwm(dev, 1, enabled,
+				   SNB_READ_WM1_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
+
+	I915_WRITE(WM1_LP_ILK,
+		   WM1_LP_SR_EN |
+		   (SNB_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, enabled,
+				   SNB_READ_WM2_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
+
+	I915_WRITE(WM2_LP_ILK,
+		   WM2_LP_EN |
+		   (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
+
+	/* WM3 */
+	if (!ironlake_compute_srwm(dev, 3, enabled,
+				   SNB_READ_WM3_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &fbc_wm, &plane_wm, &cursor_wm))
+		return;
+
+	I915_WRITE(WM3_LP_ILK,
+		   WM3_LP_EN |
+		   (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) |
+		   (fbc_wm << WM1_LP_FBC_SHIFT) |
+		   (plane_wm << WM1_LP_SR_SHIFT) |
+		   cursor_wm);
+}
+
+static void ivybridge_update_wm(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
+	u32 val;
+	int fbc_wm, plane_wm, cursor_wm;
+	int ignore_fbc_wm, ignore_plane_wm, ignore_cursor_wm;
+	unsigned int enabled;
+
+	enabled = 0;
+	if (g4x_compute_wm0(dev, 0,
+			    &sandybridge_display_wm_info, latency,
+			    &sandybridge_cursor_wm_info, latency,
+			    &plane_wm, &cursor_wm)) {
+		val = I915_READ(WM0_PIPEA_ILK);
+		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+		I915_WRITE(WM0_PIPEA_ILK, val |
+			   ((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 |= 1;
+	}
+
+	if (g4x_compute_wm0(dev, 1,
+			    &sandybridge_display_wm_info, latency,
+			    &sandybridge_cursor_wm_info, latency,
+			    &plane_wm, &cursor_wm)) {
+		val = I915_READ(WM0_PIPEB_ILK);
+		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK);
+		I915_WRITE(WM0_PIPEB_ILK, val |
+			   ((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 |= 2;
+	}
+
+	if (g4x_compute_wm0(dev, 2,
 			    &sandybridge_display_wm_info, latency,
 			    &sandybridge_cursor_wm_info, latency,
 			    &plane_wm, &cursor_wm)) {
@@ -1877,12 +1979,17 @@  static void sandybridge_update_wm(struct drm_device *dev)
 		   (plane_wm << WM1_LP_SR_SHIFT) |
 		   cursor_wm);
 
-	/* WM3 */
+	/* WM3, note we have to correct the cursor latency */
 	if (!ironlake_compute_srwm(dev, 3, enabled,
 				   SNB_READ_WM3_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
-				   &fbc_wm, &plane_wm, &cursor_wm))
+				   &fbc_wm, &plane_wm, &ignore_cursor_wm) ||
+	    !ironlake_compute_srwm(dev, 3, enabled,
+				   2 * SNB_READ_WM3_LATENCY() * 500,
+				   &sandybridge_display_srwm_info,
+				   &sandybridge_cursor_srwm_info,
+				   &ignore_fbc_wm, &ignore_plane_wm, &cursor_wm))
 		return;
 
 	I915_WRITE(WM3_LP_ILK,
@@ -3999,7 +4106,7 @@  void intel_init_pm(struct drm_device *dev)
 		} else if (IS_IVYBRIDGE(dev)) {
 			/* FIXME: detect B0+ stepping and use auto training */
 			if (SNB_READ_WM0_LATENCY()) {
-				dev_priv->display.update_wm = sandybridge_update_wm;
+				dev_priv->display.update_wm = ivybridge_update_wm;
 				dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;
 			} else {
 				DRM_DEBUG_KMS("Failed to read display plane latency. "