All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Zhang <dingchen.zhang@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: stylon.wang@amd.com, Leo Li <sunpeng.li@amd.com>,
	Harry.Wentland@amd.com, qingqing.zhuo@amd.com,
	Rodrigo.Siqueira@amd.com, roman.li@amd.com, solomon.chiu@amd.com,
	jerry.zuo@amd.com, Aurabindo.Pillai@amd.com, wayne.lin@amd.com,
	Bhawanpreet.Lakha@amd.com, agustin.gutierrez@amd.com,
	pavle.kotarac@amd.com
Subject: [PATCH v2 17/19] drm/amd/display: Implement MPO PSR SU
Date: Tue, 10 May 2022 16:45:06 -0400	[thread overview]
Message-ID: <20220510204508.506089-18-dingchen.zhang@amd.com> (raw)
In-Reply-To: <20220510204508.506089-1-dingchen.zhang@amd.com>

From: Leo Li <sunpeng.li@amd.com>

[WHY]

For additional power savings, PSR SU (also referred to as PSR2) can be
enabled on eDP panels with PSR SU support.

PSR2 saves more power compared to PSR1 by allowing more opportunities
for the display hardware to be shut down. In comparison to PSR1, Shut
down can now occur in-between frames, as well as in display regions
where there is no visible update. In otherwords, it allows for some
display hw components to be enabled only for a **selectively updated**
region of the visible display. Hence PSR SU.

[HOW]

To define the SU region, support from the OS is required. OS needs to
inform driver of damaged regions that need to be flushed to the eDP
panel. Today, such support is lacking in most compositors.

Therefore, an in-between solution is to implement PSR SU for MPO and
cursor scenarios. The plane bounds can be used to define the damaged
region to be flushed to panel. This is achieved by:

* Leveraging dm_crtc_state->mpo_requested flag to identify when MPO is
  enabled.
* If MPO is enabled, only add updated plane bounds to dirty region.
  Determine plane update by either:
    * Existence of drm damaged clips attached to the plane (added by a
      damage-aware compositor)
    * Change in fb id (flip)
    * Change in plane bounds (position and dimensions)
* If cursor is enabled, the old_pos and new_pos of cursor plus cursor
  size is used as damaged regions(*).

(*) Cursor updates follow a different code path through DC. PSR SU for
cursor is already implemented in DC, and the only thing required to
enable is to set DC_PSR_VERSION_SU_1 on the eDP link. See
dcn10_dmub_update_cursor_data().

Signed-off-by: Leo Li <sunpeng.li@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 142 +++++++++++++++++-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c |   6 +-
 2 files changed, 144 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 2ea20dd7fccf..29dd59d06fa4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1255,10 +1255,20 @@ static void vblank_control_worker(struct work_struct *work)
 
 	DRM_DEBUG_KMS("Allow idle optimizations (MALL): %d\n", dm->active_vblank_irq_count == 0);
 
-	/* Control PSR based on vblank requirements from OS */
+	/*
+	 * Control PSR based on vblank requirements from OS
+	 *
+	 * If panel supports PSR SU, there's no need to disable PSR when OS is
+	 * submitting fast atomic commits (we infer this by whether the OS
+	 * requests vblank events). Fast atomic commits will simply trigger a
+	 * full-frame-update (FFU); a specific case of selective-update (SU)
+	 * where the SU region is the full hactive*vactive region. See
+	 * fill_dc_dirty_rects().
+	 */
 	if (vblank_work->stream && vblank_work->stream->link) {
 		if (vblank_work->enable) {
-			if (vblank_work->stream->link->psr_settings.psr_allow_active)
+			if (vblank_work->stream->link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 &&
+			    vblank_work->stream->link->psr_settings.psr_allow_active)
 				amdgpu_dm_psr_disable(vblank_work->stream);
 		} else if (vblank_work->stream->link->psr_settings.psr_feature_enabled &&
 			   !vblank_work->stream->link->psr_settings.psr_allow_active &&
@@ -5631,6 +5641,117 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
 	return 0;
 }
 
+/**
+ * fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
+ *
+ * @plane: DRM plane containing dirty regions that need to be flushed to the eDP
+ *         remote fb
+ * @old_plane_state: Old state of @plane
+ * @new_plane_state: New state of @plane
+ * @crtc_state: New state of CRTC connected to the @plane
+ * @flip_addrs: DC flip tracking struct, which also tracts dirty rects
+ *
+ * For PSR SU, DC informs the DMUB uController of dirty rectangle regions
+ * (referred to as "damage clips" in DRM nomenclature) that require updating on
+ * the eDP remote buffer. The responsibility of specifying the dirty regions is
+ * amdgpu_dm's.
+ *
+ * A damage-aware DRM client should fill the FB_DAMAGE_CLIPS property on the
+ * plane with regions that require flushing to the eDP remote buffer. In
+ * addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
+ * implicitly provide damage clips without any client support via the plane
+ * bounds.
+ *
+ * Today, amdgpu_dm only supports the MPO and cursor usecase.
+ *
+ * TODO: Also enable for FB_DAMAGE_CLIPS
+ */
+static void fill_dc_dirty_rects(struct drm_plane *plane,
+				struct drm_plane_state *old_plane_state,
+				struct drm_plane_state *new_plane_state,
+				struct drm_crtc_state *crtc_state,
+				struct dc_flip_addrs *flip_addrs)
+{
+	struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
+	struct rect *dirty_rects = flip_addrs->dirty_rects;
+	uint32_t num_clips;
+	bool bb_changed;
+	bool fb_changed;
+	uint32_t i = 0;
+
+	flip_addrs->dirty_rect_count = 0;
+
+	/*
+	 * Cursor plane has it's own dirty rect update interface. See
+	 * dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
+	 */
+	if (plane->type == DRM_PLANE_TYPE_CURSOR)
+		return;
+
+	/*
+	 * Today, we only consider MPO use-case for PSR SU. If MPO not
+	 * requested, and there is a plane update, do FFU.
+	 */
+	if (!dm_crtc_state->mpo_requested) {
+		dirty_rects[0].x = 0;
+		dirty_rects[0].y = 0;
+		dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay;
+		dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay;
+		flip_addrs->dirty_rect_count = 1;
+		DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
+				 new_plane_state->plane->base.id,
+				 dm_crtc_state->base.mode.crtc_hdisplay,
+				 dm_crtc_state->base.mode.crtc_vdisplay);
+		return;
+	}
+
+	/*
+	 * MPO is requested. Add entire plane bounding box to dirty rects if
+	 * flipped to or damaged.
+	 *
+	 * If plane is moved or resized, also add old bounding box to dirty
+	 * rects.
+	 */
+	num_clips = drm_plane_get_damage_clips_count(new_plane_state);
+	fb_changed = old_plane_state->fb->base.id !=
+		     new_plane_state->fb->base.id;
+	bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
+		      old_plane_state->crtc_y != new_plane_state->crtc_y ||
+		      old_plane_state->crtc_w != new_plane_state->crtc_w ||
+		      old_plane_state->crtc_h != new_plane_state->crtc_h);
+
+	DRM_DEBUG_DRIVER("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
+			 new_plane_state->plane->base.id,
+			 bb_changed, fb_changed, num_clips);
+
+	if (num_clips || fb_changed || bb_changed) {
+		dirty_rects[i].x = new_plane_state->crtc_x;
+		dirty_rects[i].y = new_plane_state->crtc_y;
+		dirty_rects[i].width = new_plane_state->crtc_w;
+		dirty_rects[i].height = new_plane_state->crtc_h;
+		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
+				 new_plane_state->plane->base.id,
+				 dirty_rects[i].x, dirty_rects[i].y,
+				 dirty_rects[i].width, dirty_rects[i].height);
+		i += 1;
+	}
+
+	/* Add old plane bounding-box if plane is moved or resized */
+	if (bb_changed) {
+		dirty_rects[i].x = old_plane_state->crtc_x;
+		dirty_rects[i].y = old_plane_state->crtc_y;
+		dirty_rects[i].width = old_plane_state->crtc_w;
+		dirty_rects[i].height = old_plane_state->crtc_h;
+		DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
+				old_plane_state->plane->base.id,
+				dirty_rects[i].x, dirty_rects[i].y,
+				dirty_rects[i].width, dirty_rects[i].height);
+		i += 1;
+	}
+
+	flip_addrs->dirty_rect_count = i;
+}
+
 static void update_stream_scaling_settings(const struct drm_display_mode *mode,
 					   const struct dm_connector_state *dm_state,
 					   struct dc_stream_state *stream)
@@ -6579,6 +6700,7 @@ dm_crtc_duplicate_state(struct drm_crtc *crtc)
 	state->cm_has_degamma = cur->cm_has_degamma;
 	state->cm_is_degamma_srgb = cur->cm_is_degamma_srgb;
 	state->force_dpms_off = cur->force_dpms_off;
+	state->mpo_requested = cur->mpo_requested;
 	/* TODO Duplicate dc_stream after objects are stream object is flattened */
 
 	return &state->base;
@@ -9219,6 +9341,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 		bundle->surface_updates[planes_count].plane_info =
 			&bundle->plane_infos[planes_count];
 
+		fill_dc_dirty_rects(plane, old_plane_state, new_plane_state,
+				    new_crtc_state,
+				    &bundle->flip_addrs[planes_count]);
+
 		/*
 		 * Only allow immediate flips for fast updates that don't
 		 * change FB pitch, DCC state, rotation or mirroing.
@@ -9414,6 +9540,18 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 
 			/* Allow PSR when skip count is 0. */
 			acrtc_attach->dm_irq_params.allow_psr_entry = !aconn->psr_skip_count;
+
+			/*
+			 * If sink supports PSR SU, there is no need to rely on
+			 * a vblank event disable request to enable PSR. PSR SU
+			 * can be enabled immediately once OS demonstrates an
+			 * adequate number of fast atomic commits to notify KMD
+			 * of update events. See `vblank_control_worker()`.
+			 */
+			if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
+			    acrtc_attach->dm_irq_params.allow_psr_entry &&
+			    !acrtc_state->stream->link->psr_settings.psr_allow_active)
+				amdgpu_dm_psr_enable(acrtc_state->stream);
 		} else {
 			acrtc_attach->dm_irq_params.allow_psr_entry = false;
 		}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
index 52508bdda8e9..c8da18e45b0e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
@@ -79,10 +79,12 @@ void amdgpu_dm_set_psr_caps(struct dc_link *link)
 		link->psr_settings.psr_feature_enabled = true;
 	}
 
-	DRM_INFO("PSR support %d, DC PSR ver %d, sink PSR ver %d\n",
+	DRM_INFO("PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n",
 		link->psr_settings.psr_feature_enabled,
 		link->psr_settings.psr_version,
-		link->dpcd_caps.psr_info.psr_version);
+		link->dpcd_caps.psr_info.psr_version,
+		link->dpcd_caps.psr_info.psr_dpcd_caps.raw,
+		link->dpcd_caps.psr_info.psr2_su_y_granularity_cap);
 
 }
 
-- 
2.25.1


  parent reply	other threads:[~2022-05-10 20:46 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-10 20:44 [PATCH v2 00/19] DC/DM changes needed for amdgpu PSR-SU David Zhang
2022-05-10 20:44 ` [PATCH v2 01/19] drm/amd/display: align dmub cmd header to latest dmub FW to support PSR-SU David Zhang
2022-05-10 20:44 ` [PATCH v2 02/19] drm/amd/display: feed PSR-SU as psr version to dmub FW David Zhang
2022-05-10 20:44 ` [PATCH v2 03/19] drm/amd/display: combine dirty rectangles in DMUB FW David Zhang
2022-05-10 20:44 ` [PATCH v2 04/19] drm/amd/display: update GSP1 generic info packet for PSRSU David Zhang
2022-05-10 20:44 ` [PATCH v2 05/19] drm/amd/display: revise Start/End SDP data David Zhang
2022-05-10 20:44 ` [PATCH v2 06/19] drm/amd/display: program PSR2 DPCD Configuration David Zhang
2022-05-10 20:44 ` [PATCH v2 07/19] drm/amd/display: Passing Y-granularity to dmub fw David Zhang
2022-05-10 20:44 ` [PATCH v2 08/19] drm/amd/display: Set default value of line_capture_indication David Zhang
2022-05-10 20:44 ` [PATCH v2 09/19] drm/amd/display: add vline time in micro sec to PSR context David Zhang
2022-05-10 20:44 ` [PATCH v2 10/19] drm/amd/display: fix system hang when PSR exits David Zhang
2022-05-10 20:45 ` [PATCH v2 11/19] drm/amd/display: Set PSR level to enable ALPM by default David Zhang
2022-05-10 20:45 ` [PATCH v2 12/19] drm/amd/display: use HW lock mgr for PSR-SU David Zhang
2022-05-10 20:45 ` [PATCH v2 13/19] drm/amd/display: PSRSU+DSC WA for specific TCON David Zhang
2022-05-10 20:45 ` [PATCH v2 14/19] drm/amd/display: add shared helpers to update psr config fields to power module David Zhang
2022-05-10 20:45 ` [PATCH v2 15/19] drm/amd/display: calculate psr config settings in runtime in DM David Zhang
2022-05-10 20:45 ` [PATCH v2 16/19] drm/amd/display: update cursor position to DMUB FW David Zhang
2022-05-10 20:45 ` David Zhang [this message]
2022-05-10 20:45 ` [PATCH v2 18/19] drm/amd/display: expose AMD source specific DPCD for FreeSync PSR support David Zhang
2022-05-10 20:45 ` [PATCH v2 19/19] drm/amd/display: PSR-SU rate control support in DC David Zhang
2022-05-19 15:37   ` Harry Wentland
2022-05-11 15:35 ` [PATCH v2 00/19] DC/DM changes needed for amdgpu PSR-SU Alex Deucher
2022-05-12 11:22   ` Daniel Vetter
2022-05-12 17:22     ` Zhang, Dingchen (David)
2022-05-12 17:39       ` Daniel Vetter
2022-05-16 16:23         ` Leo Li
2022-05-16 17:21           ` Daniel Vetter
2022-05-19 15:38 ` Harry Wentland

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=20220510204508.506089-18-dingchen.zhang@amd.com \
    --to=dingchen.zhang@amd.com \
    --cc=Aurabindo.Pillai@amd.com \
    --cc=Bhawanpreet.Lakha@amd.com \
    --cc=Harry.Wentland@amd.com \
    --cc=Rodrigo.Siqueira@amd.com \
    --cc=agustin.gutierrez@amd.com \
    --cc=amd-gfx@lists.freedesktop.org \
    --cc=jerry.zuo@amd.com \
    --cc=pavle.kotarac@amd.com \
    --cc=qingqing.zhuo@amd.com \
    --cc=roman.li@amd.com \
    --cc=solomon.chiu@amd.com \
    --cc=stylon.wang@amd.com \
    --cc=sunpeng.li@amd.com \
    --cc=wayne.lin@amd.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.