Tested-by: Marta Lofstedt <marta.lofst...@intel.com>

> -----Original Message-----
> From: Maarten Lankhorst [mailto:maarten.lankho...@linux.intel.com]
> Sent: Thursday, August 10, 2017 12:55 PM
> To: intel-gfx@lists.freedesktop.org
> Cc: Lofstedt, Marta <marta.lofst...@intel.com>; Maarten Lankhorst
> <maarten.lankho...@linux.intel.com>
> Subject: [PATCH] drm/i915: Keep IPS disabled during CRC collection
> 
> We need to look at crtc->state->active for the legacy crc to match the drm crc
> api. Even though the drm api explictily checks it, there's no harm in doing 
> the
> same there so keep it for both.
> 
> Introduce a intel_crtc->ips_disabled flag for CRC, which is protected by crtc-
> >mutex and set it to true while collecting. This way CRC will not interfere 
> >with
> ips, regardless of visibility.
> 
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101664
> Signed-off-by: Maarten Lankhorst <maarten.lankho...@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c  | 45 +++++++++++++--------------
>  drivers/gpu/drm/i915/intel_drv.h      |  3 ++
>  drivers/gpu/drm/i915/intel_pipe_crc.c | 58
> +++++++++++++++++++++++++++--------
>  3 files changed, 71 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c
> b/drivers/gpu/drm/i915/intel_display.c
> index a8775ed817d1..88dfb4bd8db0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -117,7 +117,8 @@ static void ironlake_pfit_disable(struct intel_crtc
> *crtc, bool force);  static void ironlake_pfit_enable(struct intel_crtc 
> *crtc);
> static void intel_modeset_setup_hw_state(struct drm_device *dev,
> 
> struct drm_modeset_acquire_ctx *ctx); -static void
> intel_pre_disable_primary_noatomic(struct drm_crtc *crtc);
> +static void intel_pre_disable_primary_noatomic(struct drm_crtc *crtc,
> +
> struct intel_crtc_state *pipe_config);
> 
>  struct intel_limit {
>       struct {
> @@ -2723,7 +2724,8 @@ intel_find_initial_plane_obj(struct intel_crtc
> *intel_crtc,
>       intel_set_plane_visible(to_intel_crtc_state(crtc_state),
> 
>       to_intel_plane_state(plane_state),
>                               false);
> -     intel_pre_disable_primary_noatomic(&intel_crtc->base);
> +     intel_pre_disable_primary_noatomic(&intel_crtc->base,
> +
> to_intel_crtc_state(crtc_state));
>       trace_intel_disable_plane(primary, intel_crtc);
>       intel_plane->disable_plane(intel_plane, intel_crtc);
> 
> @@ -4668,9 +4670,6 @@ void hsw_enable_ips(struct intel_crtc *crtc)
>       struct drm_device *dev = crtc->base.dev;
>       struct drm_i915_private *dev_priv = to_i915(dev);
> 
> -     if (!crtc->config->ips_enabled)
> -             return;
> -
>       /*
>        * We can only enable IPS after we enable a plane and wait for
> a vblank
>        * This function is called from post_plane_update, which is run
> after @@ -4706,9 +4705,6 @@ void hsw_disable_ips(struct intel_crtc *crtc)
>       struct drm_device *dev = crtc->base.dev;
>       struct drm_i915_private *dev_priv = to_i915(dev);
> 
> -     if (!crtc->config->ips_enabled)
> -             return;
> -
>       assert_plane_enabled(dev_priv, crtc->plane);
>       if (IS_BROADWELL(dev_priv)) {
>               mutex_lock(&dev_priv->rps.hw_lock);
> @@ -4754,7 +4750,7 @@ static void intel_crtc_dpms_overlay_disable(struct
> intel_crtc *intel_crtc)
>   * completely hide the primary plane.
>   */
>  static void
> -intel_post_enable_primary(struct drm_crtc *crtc)
> +intel_post_enable_primary(struct drm_crtc *crtc, struct
> +intel_crtc_state *pipe_config)
>  {
>       struct drm_device *dev = crtc->dev;
>       struct drm_i915_private *dev_priv = to_i915(dev); @@ -4767,7
> +4763,8 @@ intel_post_enable_primary(struct drm_crtc *crtc)
>        * when going from primary only to sprite only and vice
>        * versa.
>        */
> -     hsw_enable_ips(intel_crtc);
> +     if (pipe_config->ips_enabled && !intel_crtc->ips_disabled)
> +             hsw_enable_ips(intel_crtc);
> 
>       /*
>        * Gen2 reports pipe underruns whenever all planes are
> disabled.
> @@ -4786,7 +4783,7 @@ intel_post_enable_primary(struct drm_crtc *crtc)
> 
>  /* FIXME move all this to pre_plane_update() with proper state tracking */
> static void -intel_pre_disable_primary(struct drm_crtc *crtc)
> +intel_pre_disable_primary(struct drm_crtc *crtc, struct
> +intel_crtc_state *pipe_config)
>  {
>       struct drm_device *dev = crtc->dev;
>       struct drm_i915_private *dev_priv = to_i915(dev); @@ -
> 4808,19 +4805,20 @@ intel_pre_disable_primary(struct drm_crtc *crtc)
>        * when going from primary only to sprite only and vice
>        * versa.
>        */
> -     hsw_disable_ips(intel_crtc);
> +     if (pipe_config->ips_enabled)
> +             hsw_disable_ips(intel_crtc);
>  }
> 
>  /* FIXME get rid of this and use pre_plane_update */  static void -
> intel_pre_disable_primary_noatomic(struct drm_crtc *crtc)
> +intel_pre_disable_primary_noatomic(struct drm_crtc *crtc, struct
> +intel_crtc_state *pipe_config)
>  {
>       struct drm_device *dev = crtc->dev;
>       struct drm_i915_private *dev_priv = to_i915(dev);
>       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>       int pipe = intel_crtc->pipe;
> 
> -     intel_pre_disable_primary(crtc);
> +     intel_pre_disable_primary(crtc, pipe_config);
> 
>       /*
>        * Vblank time updates from the shadow to live plane control
> register @@ -4858,7 +4856,7 @@ static void intel_post_plane_update(struct
> intel_crtc_state *old_crtc_state)
>               if (new_primary_state->visible &&
>                   (needs_modeset(&pipe_config->base) ||
>                    !old_primary_state->visible))
> -                     intel_post_enable_primary(&crtc-
> >base);
> +                     intel_post_enable_primary(&crtc-
> >base, pipe_config);
>       }
>  }
> 
> @@ -4885,7 +4883,7 @@ static void intel_pre_plane_update(struct
> intel_crtc_state *old_crtc_state,
> 
>               if (old_primary_state->visible &&
>                   (modeset || !new_primary_state->visible))
> -                     intel_pre_disable_primary(&crtc-
> >base);
> +                     intel_pre_disable_primary(&crtc-
> >base, pipe_config);
>       }
> 
>       /*
> @@ -5700,13 +5698,6 @@ static void intel_crtc_disable_noatomic(struct
> drm_crtc *crtc,
>       if (!intel_crtc->active)
>               return;
> 
> -     if (crtc->primary->state->visible) {
> -             intel_pre_disable_primary_noatomic(crtc);
> -
> -             intel_crtc_disable_planes(crtc, 1 <<
> drm_plane_index(crtc->primary));
> -             crtc->primary->state->visible = false;
> -     }
> -
>       state = drm_atomic_state_alloc(crtc->dev);
>       if (!state) {
>               DRM_DEBUG_KMS("failed to disable
> [CRTC:%d:%s], out of memory", @@ -5722,6 +5713,14 @@ static void
> intel_crtc_disable_noatomic(struct drm_crtc *crtc,
> 
>       WARN_ON(IS_ERR(crtc_state) || ret);
> 
> +     if (crtc->primary->state->visible) {
> +             intel_pre_disable_primary_noatomic(crtc,
> crtc_state);
> +
> +             intel_crtc_disable_planes(crtc, 1 <<
> drm_plane_index(crtc->primary));
> +             crtc->primary->state->visible = false;
> +     }
> +
> +
>       dev_priv->display.crtc_disable(crtc_state, state);
> 
>       drm_atomic_state_put(state);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h
> b/drivers/gpu/drm/i915/intel_drv.h
> index a07d06fbc4b4..872b1fce1d0e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -828,6 +828,9 @@ struct intel_crtc {
>       bool cpu_fifo_underrun_disabled;
>       bool pch_fifo_underrun_disabled;
> 
> +     /* Whether ips is force-disabled for collecting CRC */
> +     bool ips_disabled;
> +
>       /* per-pipe watermark state */
>       struct {
>               /* watermarks currently being used  */ diff --git
> a/drivers/gpu/drm/i915/intel_pipe_crc.c
> b/drivers/gpu/drm/i915/intel_pipe_crc.c
> index 8fbd2bd0877f..fc3682c4c055 100644
> --- a/drivers/gpu/drm/i915/intel_pipe_crc.c
> +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c
> @@ -601,6 +601,33 @@ static int get_new_crc_ctl_reg(struct
> drm_i915_private *dev_priv,
>               return ivb_pipe_crc_ctl_reg(dev_priv, pipe,
> source, val);  }
> 
> +static int toggle_ips_and_test_active(struct intel_crtc *crtc,
> +
> bool has_source)
> +{
> +     bool has_ips = false;
> +     int ret;
> +
> +
> +     ret = drm_modeset_lock_interruptible(&crtc->base.mutex,
> NULL);
> +     if (ret)
> +             return ret;
> +
> +     if (to_intel_crtc_state(crtc->base.state)->ips_enabled &&
> +         crtc->base.state->plane_mask & BIT(drm_plane_index(crtc-
> >base.primary)))
> +             has_ips = crtc->base.primary->state->visible;
> +
> +     if (!crtc->base.state->active && has_source) {
> +             DRM_DEBUG_KMS("Trying to capture CRC while
> pipe is off\n");
> +             ret = -EIO;
> +     }
> +
> +     crtc->ips_disabled = has_source;
> +
> +     drm_modeset_unlock(&crtc->base.mutex);
> +
> +     return ret ?: has_ips;
> +}
> +
>  static int pipe_crc_set_source(struct drm_i915_private *dev_priv,
>                              enum pipe pipe,
>                              enum intel_pipe_crc_source
> source) @@ -610,6 +637,7 @@ static int pipe_crc_set_source(struct
> drm_i915_private *dev_priv,
>       enum intel_display_power_domain power_domain;
>       u32 val = 0; /* shut up gcc */
>       int ret;
> +     int has_ips;
> 
>       if (pipe_crc->source == source)
>               return 0;
> @@ -618,11 +646,12 @@ static int pipe_crc_set_source(struct
> drm_i915_private *dev_priv,
>       if (pipe_crc->source && source)
>               return -EINVAL;
> 
> +     has_ips = toggle_ips_and_test_active(crtc, source);
> +     if (has_ips < 0)
> +             return has_ips;
> +
>       power_domain = POWER_DOMAIN_PIPE(pipe);
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> power_domain)) {
> -             DRM_DEBUG_KMS("Trying to capture CRC while
> pipe is off\n");
> -             return -EIO;
> -     }
> +     intel_display_power_get(dev_priv, power_domain);
> 
>       ret = get_new_crc_ctl_reg(dev_priv, pipe, &source, &val);
>       if (ret != 0)
> @@ -649,7 +678,8 @@ static int pipe_crc_set_source(struct
> drm_i915_private *dev_priv,
>                * user space can't make reliable use of the
> CRCs, so let's just
>                * completely disable it.
>                */
> -             hsw_disable_ips(crtc);
> +             if (has_ips)
> +                     hsw_disable_ips(crtc);
> 
>               spin_lock_irq(&pipe_crc->lock);
>               kfree(pipe_crc->entries);
> @@ -694,7 +724,8 @@ static int pipe_crc_set_source(struct
> drm_i915_private *dev_priv,
>               else if (IS_HASWELL(dev_priv) && pipe ==
> PIPE_A)
> 
>       hsw_trans_edp_pipe_A_crc_wa(dev_priv, false);
> 
> -             hsw_enable_ips(crtc);
> +             if (has_ips)
> +                     hsw_enable_ips(crtc);
>       }
> 
>       ret = 0;
> @@ -919,23 +950,25 @@ int intel_crtc_set_crc_source(struct drm_crtc *crtc,
> const char *source_name,
>       enum intel_pipe_crc_source source;
>       u32 val = 0; /* shut up gcc */
>       int ret = 0;
> +     int has_ips;
> 
>       if (display_crc_ctl_parse_source(source_name, &source) < 0) {
>               DRM_DEBUG_DRIVER("unknown source %s\n",
> source_name);
>               return -EINVAL;
>       }
> 
> +     has_ips = toggle_ips_and_test_active(intel_crtc, source);
> +     if (has_ips < 0)
> +             return has_ips;
> +
>       power_domain = POWER_DOMAIN_PIPE(crtc->index);
> -     if (!intel_display_power_get_if_enabled(dev_priv,
> power_domain)) {
> -             DRM_DEBUG_KMS("Trying to capture CRC while
> pipe is off\n");
> -             return -EIO;
> -     }
> +     intel_display_power_get(dev_priv, power_domain);
> 
>       ret = get_new_crc_ctl_reg(dev_priv, crtc->index, &source,
> &val);
>       if (ret != 0)
>               goto out;
> 
> -     if (source) {
> +     if (source && has_ips) {
>               /*
>                * When IPS gets enabled, the pipe CRC
> changes. Since IPS gets
>                * enabled and disabled dynamically based on
> package C states, @@ -956,7 +989,8 @@ int intel_crtc_set_crc_source(struct
> drm_crtc *crtc, const char *source_name,
>               else if (IS_HASWELL(dev_priv) && crtc->index
> == PIPE_A)
> 
>       hsw_trans_edp_pipe_A_crc_wa(dev_priv, false);
> 
> -             hsw_enable_ips(intel_crtc);
> +             if (has_ips)
> +                     hsw_enable_ips(intel_crtc);
>       }
> 
>       pipe_crc->skipped = 0;
> --
> 2.11.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to