All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH] drm/i915/gen11: Link nv12 Y and UV planes in the atomic state, v5.
Date: Mon, 22 Oct 2018 18:48:22 +0300	[thread overview]
Message-ID: <20181022154822.GM9144@intel.com> (raw)
In-Reply-To: <20181022135152.15324-1-maarten.lankhorst@linux.intel.com>

On Mon, Oct 22, 2018 at 03:51:52PM +0200, Maarten Lankhorst wrote:
> To make NV12 working on icl, we need to update 2 planes simultaneously.
> I've chosen to do this in the CRTC step after plane validation is done,
> so we know what planes are (in)visible. The linked Y plane will get
> updated in intel_plane_update_planes_on_crtc(), by the call to
> update_slave, which gets the master's plane_state as argument.
> 
> The link requires both planes for atomic_update to work,
> so make sure skl_ddb_add_affected_planes() adds both states.
> 
> Changes since v1:
> - Introduce icl_is_nv12_y_plane(), instead of hardcoding sprite numbers.
> - Put all the state updating login in intel_plane_atomic_check_with_state().
> - Clean up changes in intel_plane_atomic_check().
> Changes since v2:
> - Fix intel_atomic_get_old_plane_state() to actually return old state.
> - Move visibility changes to preparation patch.
> - Only try to find a Y plane on gen11, earlier platforms only require
>   a single plane.
> Changes since v3:
> - Fix checkpatch warning about to_intel_crtc() usage.
> - Add affected planes from icl_add_linked_planes() before check_planes(),
>   it's a cleaner way to do this. (Ville)
> Changes since v4:
> - Clear plane links in icl_check_nv12_planes() for clarity.
> - Only pass crtc_state to icl_check_nv12_planes().
> - Use for_each_new_intel_plane_in_state() in icl_check_nv12_planes.
> - Rename aux to linked. (Ville)
> 
> Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_atomic_plane.c | 19 +++++
>  drivers/gpu/drm/i915/intel_display.c      | 95 +++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h          | 53 +++++++++++++
>  drivers/gpu/drm/i915/intel_pm.c           | 12 ++-
>  4 files changed, 178 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c
> index b957ad63cd87..7d3685075201 100644
> --- a/drivers/gpu/drm/i915/intel_atomic_plane.c
> +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c
> @@ -188,6 +188,25 @@ void intel_update_planes_on_crtc(struct intel_atomic_state *old_state,
>  			trace_intel_update_plane(&plane->base, crtc);
>  
>  			plane->update_plane(plane, new_crtc_state, new_plane_state);
> +		} else if (new_plane_state->slave) {
> +			struct intel_plane *master =
> +				new_plane_state->linked_plane;
> +
> +			/*
> +			 * We update the slave plane from this function because
> +			 * programming it from the master plane's update_plane
> +			 * callback runs into issues when the Y plane is
> +			 * reassigned, disabled or used by a different plane.
> +			 *
> +			 * The slave plane is updated with the master plane's
> +			 * plane_state.
> +			 */
> +			new_plane_state =
> +				intel_atomic_get_new_plane_state(old_state, master);
> +
> +			trace_intel_update_plane(&plane->base, crtc);
> +
> +			plane->update_slave(plane, new_crtc_state, new_plane_state);
>  		} else {
>  			trace_intel_disable_plane(&plane->base, crtc);
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 68c9aeeee05c..680895982e4f 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -10723,6 +10723,95 @@ static bool check_single_encoder_cloning(struct drm_atomic_state *state,
>  	return true;
>  }
>  
> +static int icl_add_linked_planes(struct intel_atomic_state *state)
> +{
> +	struct intel_plane *plane, *linked;
> +	struct intel_plane_state *plane_state, *linked_plane_state;
> +	int i;
> +
> +	for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
> +		linked = plane_state->linked_plane;
> +
> +		if (!linked)
> +			continue;
> +
> +		linked_plane_state = intel_atomic_get_plane_state(state, linked);
> +		if (IS_ERR(linked_plane_state))
> +			return PTR_ERR(linked_plane_state);

WARN_ON(linked_plane_state->linked != plane);
WARN_ON(linked_plane_state->slave == plane_state->slave);

perhaps?

> +	}
> +
> +	return 0;
> +}
> +
> +static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state)
> +{
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
> +	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
> +	struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->base.state);
> +	struct intel_plane *plane, *linked;
> +	struct intel_plane_state *plane_state;
> +	int i;
> +
> +	if (INTEL_GEN(dev_priv) < 11)
> +		return 0;
> +
> +	/*
> +	 * Destroy all old plane links and make the slave plane invisible
> +	 * in the crtc_state->active_planes mask.
> +	 */
> +	for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
> +		if (plane->pipe != crtc->pipe || !plane_state->linked_plane)
> +			continue;
> +
> +		plane_state->linked_plane = NULL;
> +		if (plane_state->slave && !plane_state->base.visible)

Hmm. Was confused for a moment here. Since we do this after the check_plane()
we could indeed have a visible slave plane here.

I wonder if it would be cleaner to do this in icl_add_linked_planes()
instead? Not sure.

Feel free to ignore my bikesheds you think this is better.
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

> +			crtc_state->active_planes &= ~BIT(plane->id);
> +
> +		plane_state->slave = false;
> +	}
> +
> +	if (!crtc_state->nv12_planes)
> +		return 0;
> +
> +	for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
> +		struct intel_plane_state *linked_state = NULL;
> +
> +		if (plane->pipe != crtc->pipe ||
> +		    !(crtc_state->nv12_planes & BIT(plane->id)))
> +			continue;
> +
> +		for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, linked) {
> +			if (!icl_is_nv12_y_plane(linked->id))
> +				continue;
> +
> +			if (crtc_state->active_planes & BIT(linked->id))
> +				continue;
> +
> +			linked_state = intel_atomic_get_plane_state(state, linked);
> +			if (IS_ERR(linked_state))
> +				return PTR_ERR(linked_state);
> +
> +			break;
> +		}
> +
> +		if (!linked_state) {
> +			DRM_DEBUG_KMS("Need %d free Y planes for NV12\n",
> +				      hweight8(crtc_state->nv12_planes));
> +
> +			return -EINVAL;
> +		}
> +
> +		plane_state->linked_plane = linked;
> +
> +		linked_state->slave = true;
> +		linked_state->linked_plane = plane;
> +		crtc_state->active_planes |= BIT(linked->id);
> +		DRM_DEBUG_KMS("Using %s as Y plane for %s\n", linked->base.name, plane->base.name);
> +	}
> +
> +	return 0;
> +}
> +
>  static int intel_crtc_atomic_check(struct drm_crtc *crtc,
>  				   struct drm_crtc_state *crtc_state)
>  {
> @@ -10794,6 +10883,8 @@ static int intel_crtc_atomic_check(struct drm_crtc *crtc,
>  		if (mode_changed)
>  			ret = skl_update_scaler_crtc(pipe_config);
>  
> +		if (!ret)
> +			ret = icl_check_nv12_planes(pipe_config);
>  		if (!ret)
>  			ret = skl_check_pipe_max_pixel_rate(intel_crtc,
>  							    pipe_config);
> @@ -12460,6 +12551,10 @@ static int intel_atomic_check(struct drm_device *dev,
>  		intel_state->cdclk.logical = dev_priv->cdclk.logical;
>  	}
>  
> +	ret = icl_add_linked_planes(intel_state);
> +	if (ret)
> +		return ret;
> +
>  	ret = drm_atomic_helper_check_planes(dev, state);
>  	if (ret)
>  		return ret;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 0e9a926fca04..59b35293a5f6 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -539,6 +539,26 @@ struct intel_plane_state {
>  	 */
>  	int scaler_id;
>  
> +	/*
> +	 * linked_plane:
> +	 *
> +	 * ICL planar formats require 2 planes that are updated as pairs.
> +	 * This member is used to make sure the other plane is also updated
> +	 * when required, and for update_slave() to find the correct
> +	 * plane_state to pass as argument.
> +	 */
> +	struct intel_plane *linked_plane;
> +
> +	/*
> +	 * slave:
> +	 * If set don't update use the linked plane's state for updating
> +	 * this plane during atomic commit with the update_slave() callback.
> +	 *
> +	 * It's also used by the watermark code to ignore wm calculations on
> +	 * this plane. They're calculated by the linked plane's wm code.
> +	 */
> +	bool slave;
> +
>  	struct drm_intel_sprite_colorkey ckey;
>  };
>  
> @@ -983,6 +1003,9 @@ struct intel_plane {
>  	void (*update_plane)(struct intel_plane *plane,
>  			     const struct intel_crtc_state *crtc_state,
>  			     const struct intel_plane_state *plane_state);
> +	void (*update_slave)(struct intel_plane *plane,
> +			     const struct intel_crtc_state *crtc_state,
> +			     const struct intel_plane_state *plane_state);
>  	void (*disable_plane)(struct intel_plane *plane,
>  			      struct intel_crtc *crtc);
>  	bool (*get_hw_state)(struct intel_plane *plane, enum pipe *pipe);
> @@ -1351,6 +1374,27 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)
>  	return container_of(intel_hdmi, struct intel_digital_port, hdmi);
>  }
>  
> +static inline struct intel_plane_state *
> +intel_atomic_get_plane_state(struct intel_atomic_state *state,
> +				 struct intel_plane *plane)
> +{
> +	struct drm_plane_state *ret =
> +		drm_atomic_get_plane_state(&state->base, &plane->base);
> +
> +	if (IS_ERR(ret))
> +		return ERR_CAST(ret);
> +
> +	return to_intel_plane_state(ret);
> +}
> +
> +static inline struct intel_plane_state *
> +intel_atomic_get_old_plane_state(struct intel_atomic_state *state,
> +				 struct intel_plane *plane)
> +{
> +	return to_intel_plane_state(drm_atomic_get_old_plane_state(&state->base,
> +								   &plane->base));
> +}
> +
>  static inline struct intel_plane_state *
>  intel_atomic_get_new_plane_state(struct intel_atomic_state *state,
>  				 struct intel_plane *plane)
> @@ -2158,6 +2202,15 @@ struct intel_plane *
>  skl_universal_plane_create(struct drm_i915_private *dev_priv,
>  			   enum pipe pipe, enum plane_id plane_id);
>  
> +static inline bool icl_is_nv12_y_plane(enum plane_id id)
> +{
> +	/* Don't need to do a gen check, these planes are only available on gen11 */
> +	if (id == PLANE_SPRITE4 || id == PLANE_SPRITE5)
> +		return true;
> +
> +	return false;
> +}
> +
>  /* intel_tv.c */
>  void intel_tv_init(struct drm_i915_private *dev_priv);
>  
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index f42b8c319046..9ba39a9c7d1c 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5153,11 +5153,12 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)
>  	struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
>  	struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb;
>  	struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb;
> -	struct drm_plane_state *plane_state;
>  	struct drm_plane *plane;
>  	enum pipe pipe = intel_crtc->pipe;
>  
>  	drm_for_each_plane_mask(plane, dev, cstate->base.plane_mask) {
> +		struct drm_plane_state *plane_state;
> +		struct intel_plane *linked;
>  		enum plane_id plane_id = to_intel_plane(plane)->id;
>  
>  		if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][plane_id],
> @@ -5169,6 +5170,15 @@ skl_ddb_add_affected_planes(struct intel_crtc_state *cstate)
>  		plane_state = drm_atomic_get_plane_state(state, plane);
>  		if (IS_ERR(plane_state))
>  			return PTR_ERR(plane_state);
> +
> +		/* Make sure linked plane is updated too */
> +		linked = to_intel_plane_state(plane_state)->linked_plane;
> +		if (!linked)
> +			continue;
> +
> +		plane_state = drm_atomic_get_plane_state(state, &linked->base);
> +		if (IS_ERR(plane_state))
> +			return PTR_ERR(plane_state);
>  	}
>  
>  	return 0;
> -- 
> 2.19.1

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

  reply	other threads:[~2018-10-22 15:48 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-18 11:51 [PATCH v2 0/8] drm/i915/gen11: Add support for the NV12 format Maarten Lankhorst
2018-10-18 11:51 ` [PATCH v2 1/8] drm/i915: Fix unsigned overflow when calculating total data rate Maarten Lankhorst
2018-10-18 14:53   ` Ville Syrjälä
2018-10-19 12:58     ` Maarten Lankhorst
2018-10-18 15:11   ` Ville Syrjälä
2018-10-19 13:03     ` Maarten Lankhorst
2018-10-19 13:06       ` Chris Wilson
2018-10-19 14:15         ` Maarten Lankhorst
2018-10-22 10:20         ` [PATCH] drm/i915: Fix unsigned overflow when calculating total data rate, v2 Maarten Lankhorst
2018-10-18 11:51 ` [PATCH v2 2/8] drm/i915/gen11: Enable 6 sprites on gen11 Maarten Lankhorst
2018-10-18 11:51 ` [PATCH v2 3/8] drm/i915/gen11: Link nv12 Y and UV planes in the atomic state, v4 Maarten Lankhorst
2018-10-18 16:00   ` Ville Syrjälä
2018-10-19 14:22     ` Maarten Lankhorst
2018-10-19 17:14       ` Ville Syrjälä
2018-10-22 10:09         ` Maarten Lankhorst
2018-10-22 13:51         ` [PATCH] drm/i915/gen11: Link nv12 Y and UV planes in the atomic state, v5 Maarten Lankhorst
2018-10-22 15:48           ` Ville Syrjälä [this message]
2018-10-23 14:25             ` Maarten Lankhorst
2018-10-23 14:36               ` Ville Syrjälä
2018-10-23 14:58                 ` Maarten Lankhorst
2018-10-18 11:51 ` [PATCH v2 4/8] drm/i915/gen11: Handle watermarks correctly for separate Y/UV planes, v2 Maarten Lankhorst
2018-10-18 16:17   ` Ville Syrjälä
2018-10-18 11:51 ` [PATCH v2 5/8] drm/i915/gen11: Program the scalers correctly for planar formats, v3 Maarten Lankhorst
2018-10-18 14:47   ` Ville Syrjälä
2018-10-18 11:51 ` [PATCH v2 6/8] drm/i915/gen11: Program the chroma upsampler for HDR planes Maarten Lankhorst
2018-10-18 14:50   ` Ville Syrjälä
2018-10-18 11:51 ` [PATCH v2 7/8] drm/i915/gen11: Program the Y and UV plane for planar mode correctly, v3 Maarten Lankhorst
2018-10-18 14:51   ` Ville Syrjälä
2018-10-18 11:51 ` [PATCH v2 8/8] drm/i915/gen11: Expose planar format support on gen11 Maarten Lankhorst
2018-10-18 16:20   ` Ville Syrjälä
2018-10-22 13:45     ` [PATCH] drm/i915/gen11: Expose planar format support on gen11, v2 Maarten Lankhorst
2018-10-22 15:55       ` Ville Syrjälä
2018-10-18 12:03 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915/gen11: Add support for the NV12 format Patchwork
2018-10-18 12:06 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-10-18 12:19 ` ✓ Fi.CI.BAT: success " Patchwork
2018-10-18 15:16 ` [PATCH v2 0/8] " Ville Syrjälä
2018-10-18 16:20   ` Maarten Lankhorst
2018-10-22 10:52 ` ✓ Fi.CI.IGT: success for " Patchwork
2018-10-22 15:28 ` ✗ Fi.CI.CHECKPATCH: warning for drm/i915/gen11: Add support for the NV12 format. (rev4) Patchwork
2018-10-22 15:32 ` ✗ Fi.CI.SPARSE: " Patchwork
2018-10-22 15:53 ` ✓ Fi.CI.BAT: success " Patchwork
2018-10-22 19:02 ` ✓ Fi.CI.IGT: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181022154822.GM9144@intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=maarten.lankhorst@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.