[Intel-gfx] [RFC] drm/i915/dp: Preliminary support for 2 pipe 1 port mode for 5K at 120

Matt Roper matthew.d.roper at intel.com
Wed Jan 23 17:31:17 UTC 2019


On Tue, Jan 22, 2019 at 01:12:07PM -0800, Manasi Navare wrote:
> On Gen 11 platform, to enable resolutions like 5K at 120 where
> the pixel clock is greater than pipe pixel rate, we need to split it across
> 2 pipes and enable it using DSC and big joiner. In order to support this
> dual pipe single port mode, we need to link two crtcs involved in this
> ganged mode.
> 
> This patch is a RFC patch that links two crtcs using linked_crtc pointer
> in intel_crtc_state and slave to indicate if the crtc is a master or slave.
> Here the HW necessitates the first CRTC to be the master CRTC through which
> the final output will be driven and the next consecutive CRTC should be
> slave crtc.
> 
> This is currently not tested, but I wanted to get some inputs on this approach.
> The idea is to follow the same approach used in Ganged plane mode for NV12
> planes.
> 
> Suggested-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>,
> Matt Roper <matthew.d.roper at intel.com>
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Cc: Matt Roper <matthew.d.roper at intel.com>
> Cc: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
> Signed-off-by: Manasi Navare <manasi.d.navare at intel.com>

Looks like the right general approach of using slave/master.  I agree
with Ville and Maarten's feedback as well.

The other thing we're going to need to worry about is dealing with all
the planes on the two crtc's.  Suppose we have a userspace-visible state
of:

   Pipe A:  off
   Pipe B:  5000x2000 at 120 (using round numbers to make example simpler)
      Plane 0:  RGB32: pos (0,0), width=5000, height=2000
      Plane 1:  RGB32: pos (100,100), width=100, height=100
      Plane 2:  RGB32: pos (4800,1800), width=100, height=100
      Plane 3:  RGB32: pos (0,0), width=3000, height=2000
      Plane 4:  NV12:  pos (2000,0), width=1000, height=2000
      Plane 5:  off
      Plane 6:  off
   Pipe C:  off

this means that we need to grab extra planes on the other CRTC and
adjust their size, position, and/or surface offsets accordingly.  So the
internal driver state that we actually program into the hardware needs
to be something like:

   Pipe A:  off
   Pipe B:  2500x1000 (master)
      Plane 0:  pos (0,0), width=2500, height=2000
      Plane 1:  pos (100,100), width=100, height=100
      Plane 2:  off
      Plane 3:  pos (0, 0), width=2500, height=2000
      Plane 4{UV}: pos (2000, 0), width=500, height=2000
      Plane 5{Y}:  pos (2000, 0), width=500, height=2000
      Plane 6:  off
   Pipe C:  2500x1000 (slave)
      Plane 0:  pos (0,0), offset=(2500,0), width=2500, height=2000
      Plane 1:  off
      Plane 2:  pos (2300,1800), width=100, height=100
      Plane 3:  pos (0, 0), offset=(2500, 0), width=500, height=2000
      Plane 4{UV}: pos (0, 0), offset=(500,0), width=500, height=2000
      Plane 5{Y}:  pos (0, 0), offset=(500,0), width=500, height=2000
      Plane 6:  off

So I think Ville is right; we're going to need to really copy a lot of
the userspace-facing state data into our own internal state structures
so that we can do the various adjustments on it.  As you can see above
there are cases (2pi1po + nv12) where a single userspace plane request
translates into us programming four different sets of plane register
values.


Matt


> ---
>  drivers/gpu/drm/i915/intel_display.c | 63 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |  6 +++
>  2 files changed, 69 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 2fa9f4aec08e..9910dad7371b 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -10900,6 +10900,63 @@ static bool check_single_encoder_cloning(struct drm_atomic_state *state,
>  	return true;
>  }
>  
> +static bool icl_dual_pipe_mode(struct drm_i915_private *dev_priv,
> +			       struct drm_crtc_state *crtc_state)
> +{
> +	if (crtc_state->mode.clock <= 2 * dev_priv->max_cdclk_freq)
> +		return false;
> +
> +	return true;
> +}
> +
> +static int icl_set_linked_crtcs(struct drm_atomic_state *state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(state->dev);
> +	struct drm_crtc *crtc;
> +	struct drm_crtc_state *crtc_state;
> +	struct intel_crtc_state *linked_state = NULL;
> +	struct intel_crtc *slave_crtc = NULL;
> +	int i;
> +
> +	for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
> +		struct intel_crtc_state *pipe_config =
> +			to_intel_crtc_state(crtc_state);
> +		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +
> +		if (crtc_state->active)
> +			continue;
> +
> +		if (!icl_dual_pipe_mode(dev_priv, crtc_state))
> +			continue;
> +
> +		if (!pipe_config->linked_crtc) {
> +			slave_crtc = intel_get_crtc_for_pipe(dev_priv,
> +							     intel_crtc->pipe + 1);
> +			if (!slave_crtc)
> +				return PTR_ERR(slave_crtc);
> +
> +			linked_state = intel_atomic_get_crtc_state(state, slave_crtc);
> +			if (IS_ERR(linked_state))
> +				return PTR_ERR(linked_state);
> +
> +			pipe_config->linked_crtc = slave_crtc;
> +			pipe_config->slave = false;
> +			linked_state->linked_crtc = intel_crtc;
> +			linked_state->slave = true;
> +			// Update the intel_state->active_crtcs if needed
> +
> +			DRM_DEBUG_KMS("Using [CRTC:%d:%s] as master and [CRTC:%d:%s] as slave\n",
> +				      intel_crtc->base.base.id, intel_crtc->base.name,
> +				      slave_crtc->base.base.id, slave_crtc->base.name);
> +
> +			break;
> +		}
> +	}
> +
> +	return 0;
> +
> +}
> +
>  static int icl_add_linked_planes(struct intel_atomic_state *state)
>  {
>  	struct intel_plane *plane, *linked;
> @@ -12702,6 +12759,12 @@ static int intel_atomic_check(struct drm_device *dev,
>  	if (ret)
>  		return ret;
>  
> +	if (INTEL_GEN(dev_priv) >= 11) {
> +		ret = icl_set_linked_crtcs(state);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, crtc_state, i) {
>  		struct intel_crtc_state *pipe_config =
>  			to_intel_crtc_state(crtc_state);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 33b733d37706..f8bbed525ec3 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -959,6 +959,12 @@ struct intel_crtc_state {
>  
>  	/* Forward Error correction State */
>  	bool fec_enable;
> +
> +	/* Pointer to linked crtc in dual pipe mode */
> +	struct intel_crtc *linked_crtc;
> +
> +	/* Flag to indicate whether this crtc is master or slave */
> +	bool slave;
>  };
>  
>  struct intel_crtc {
> -- 
> 2.19.1
> 

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


More information about the Intel-gfx mailing list