[Intel-gfx] [PATCH v3.6 20/22] drm/i915: Calculate haswell plane workaround, v4.

Matt Roper matthew.d.roper at intel.com
Thu May 28 17:58:12 PDT 2015


On Tue, May 26, 2015 at 10:36:14AM +0200, Maarten Lankhorst wrote:
> This needs to be a global check because at the time of crtc checking
> not all modesets have to be calculated yet. Use intel_crtc->atomic
> because there's no reason to keep it in state.

The note about intel_crtc->atomic is out of date as of v3.  Otherwise, I
think this looks okay.

Reviewed-by: Matt Roper <matthew.d.roper at intel.com>


Matt

> 
> Changes since v1:
>  - Use intel_crtc->atomic as a place to put hsw_workaround_pipe.
>  - Make sure quirk only applies to haswell.
>  - Use first loop to iterate over newly enabled crtc's only.
>    This increases readability.
> Changes since v2:
>  - Move hsw_workaround_pipe back to crtc_state.
> Changes since v3:
>  - Return errors from haswell_mode_set_planes_workaround.
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 109 +++++++++++++++++++++++++----------
>  drivers/gpu/drm/i915/intel_drv.h     |   3 +
>  2 files changed, 80 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index de13c1c14c93..f6733a777590 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4867,42 +4867,15 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc)
>  	return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A;
>  }
>  
> -/*
> - * This implements the workaround described in the "notes" section of the mode
> - * set sequence documentation. When going from no pipes or single pipe to
> - * multiple pipes, and planes are enabled after the pipe, we need to wait at
> - * least 2 vblanks on the first pipe before enabling planes on the second pipe.
> - */
> -static void haswell_mode_set_planes_workaround(struct intel_crtc *crtc)
> -{
> -	struct drm_device *dev = crtc->base.dev;
> -	struct intel_crtc *crtc_it, *other_active_crtc = NULL;
> -
> -	/* We want to get the other_active_crtc only if there's only 1 other
> -	 * active crtc. */
> -	for_each_intel_crtc(dev, crtc_it) {
> -		if (!crtc_it->active || crtc_it == crtc)
> -			continue;
> -
> -		if (other_active_crtc)
> -			return;
> -
> -		other_active_crtc = crtc_it;
> -	}
> -	if (!other_active_crtc)
> -		return;
> -
> -	intel_wait_for_vblank(dev, other_active_crtc->pipe);
> -	intel_wait_for_vblank(dev, other_active_crtc->pipe);
> -}
> -
>  static void haswell_crtc_enable(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>  	struct intel_encoder *encoder;
> -	int pipe = intel_crtc->pipe;
> +	int pipe = intel_crtc->pipe, hsw_workaround_pipe;
> +	struct intel_crtc_state *pipe_config =
> +		to_intel_crtc_state(crtc->state);
>  
>  	if (WARN_ON(intel_crtc->active))
>  		return;
> @@ -4979,7 +4952,11 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>  
>  	/* If we change the relative order between pipe/planes enabling, we need
>  	 * to change the workaround. */
> -	haswell_mode_set_planes_workaround(intel_crtc);
> +	hsw_workaround_pipe = pipe_config->hsw_workaround_pipe;
> +	if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) {
> +		intel_wait_for_vblank(dev, hsw_workaround_pipe);
> +		intel_wait_for_vblank(dev, hsw_workaround_pipe);
> +	}
>  }
>  
>  static void ironlake_pfit_disable(struct intel_crtc *crtc)
> @@ -12169,6 +12146,71 @@ static int __intel_set_mode_setup_plls(struct drm_atomic_state *state)
>  	return ret;
>  }
>  
> +/*
> + * This implements the workaround described in the "notes" section of the mode
> + * set sequence documentation. When going from no pipes or single pipe to
> + * multiple pipes, and planes are enabled after the pipe, we need to wait at
> + * least 2 vblanks on the first pipe before enabling planes on the second pipe.
> + */
> +static int haswell_mode_set_planes_workaround(struct drm_atomic_state *state)
> +{
> +	struct drm_crtc_state *crtc_state;
> +	struct intel_crtc *intel_crtc;
> +	struct drm_crtc *crtc;
> +	struct intel_crtc_state *first_crtc_state = NULL;
> +	struct intel_crtc_state *other_crtc_state = NULL;
> +	enum pipe first_pipe = INVALID_PIPE, enabled_pipe = INVALID_PIPE;
> +	int i;
> +
> +	/* look at all crtc's that are going to be enabled in during modeset */
> +	for_each_crtc_in_state(state, crtc, crtc_state, i) {
> +		intel_crtc = to_intel_crtc(crtc);
> +
> +		if (!crtc_state->active || !needs_modeset(crtc_state))
> +			continue;
> +
> +		if (first_crtc_state) {
> +			other_crtc_state = to_intel_crtc_state(crtc_state);
> +			break;
> +		} else {
> +			first_crtc_state = to_intel_crtc_state(crtc_state);
> +			first_pipe = intel_crtc->pipe;
> +		}
> +	}
> +
> +	/* No workaround needed? */
> +	if (!first_crtc_state)
> +		return 0;
> +
> +	/* w/a possibly needed, check how many crtc's are already enabled. */
> +	for_each_intel_crtc(state->dev, intel_crtc) {
> +		struct intel_crtc_state *pipe_config;
> +
> +		pipe_config = intel_atomic_get_crtc_state(state, intel_crtc);
> +		if (IS_ERR(pipe_config))
> +			return PTR_ERR(pipe_config);
> +
> +		pipe_config->hsw_workaround_pipe = INVALID_PIPE;
> +
> +		if (!pipe_config->base.active ||
> +		    needs_modeset(&pipe_config->base))
> +			continue;
> +
> +		/* 2 or more enabled crtcs means no need for w/a */
> +		if (enabled_pipe != INVALID_PIPE)
> +			return 0;
> +
> +		enabled_pipe = intel_crtc->pipe;
> +	}
> +
> +	if (enabled_pipe != INVALID_PIPE)
> +		first_crtc_state->hsw_workaround_pipe = enabled_pipe;
> +	else if (other_crtc_state)
> +		other_crtc_state->hsw_workaround_pipe = first_pipe;
> +
> +	return 0;
> +}
> +
>  /* Code that should eventually be part of atomic_check() */
>  static int __intel_set_mode_checks(struct drm_atomic_state *state)
>  {
> @@ -12192,7 +12234,10 @@ static int __intel_set_mode_checks(struct drm_atomic_state *state)
>  	if (ret)
>  		return ret;
>  
> -	return 0;
> +	if (IS_HASWELL(dev))
> +		ret = haswell_mode_set_planes_workaround(state);
> +
> +	return ret;
>  }
>  
>  static int
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 665e249ae8bf..d5f38e3d732b 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -443,6 +443,9 @@ struct intel_crtc_state {
>  	int pbn;
>  
>  	struct intel_crtc_scaler_state scaler_state;
> +
> +	/* w/a for waiting 2 vblanks during crtc enable */
> +	enum pipe hsw_workaround_pipe;
>  };
>  
>  struct intel_pipe_wm {
> -- 
> 2.1.0
> 
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795


More information about the Intel-gfx mailing list