On Tue, 11 Dec 2012 12:01:42 +0000
Chris Wilson <[email protected]> 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 <[email protected]>
> CC: Jesse Barnes <[email protected]>
> ---
>  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 <[email protected]>

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

-- 
Jesse Barnes, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to