linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes
@ 2023-03-21  1:18 Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 01/13] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state Dmitry Baryshkov
                   ` (12 more replies)
  0 siblings, 13 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

As promised in the basic wide planes support ([1]) here comes a series
supporting 2*max_linewidth for all the planes.

Note: this iteration features handling of rotation and reflection of the
wide plane. However rot90 is still not tested: it is enabled on sc7280
and it only supports UBWC (tiled) framebuffers, it was quite low on my
priority list.

Note#2: to simplify the dpu_plane_virtual_assign_resources(), which
already becomes big enough, I stripped support for sharing the SSPP
across two planes (doubling amount of planes available to some of
compositors/applications). I plan to get back to this topic once this
series lands.

Dependencies: msm-next + msm-fixes, [1], [2]

[1] https://patchwork.freedesktop.org/series/99909/

[2] https://patchwork.freedesktop.org/series/113423/

Changes since v1:
- Fixed build error due to me missing one of fixups, it was left
  uncommitted.
- Implementated proper handling of wide plane rotation & reflection.

Dmitry Baryshkov (13):
  drm/atomic-helper: split not-scaling part of
    drm_atomic_helper_check_plane_state
  drm/msm/dpu: take plane rotation into account for wide planes
  drm/msm/dpu: encoder: simplify debugfs handling
  drm/msm/dpu: remove unused fields from dpu_encoder_virt
  drm/msm/dpu: get rid of struct dpu_rm_requirements
  drm/msm/dpu: switch RM to use crtc_id rather than enc_id for
    allocation
  drm/msm/dpu: move resource allocation to CRTC
  drm/msm/dpu: fill CRTC resources in dpu_crtc.c
  drm/msm/dpu: move pstate->pipe initialization to
    dpu_plane_atomic_check
  drm/msm/dpu: add list of supported formats to the DPU caps
  drm/msm/dpu: add a field describing inline rotation to dpu_caps
  drm/msm/dpu: add support for virtual planes
  drm/msm/dpu: allow using two SSPP blocks for a single plane

 drivers/gpu/drm/drm_atomic_helper.c           |  85 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c      | 162 ++++++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 150 +-----
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   8 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 -
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    |  27 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |   6 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       | 120 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |  14 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c     | 428 ++++++++++++++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h     |  33 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        | 243 +++++-----
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        |  41 +-
 include/drm/drm_atomic_helper.h               |   4 +
 14 files changed, 959 insertions(+), 365 deletions(-)

-- 
2.30.2


^ permalink raw reply	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 01/13] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes Dmitry Baryshkov
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

The helper drm_atomic_helper_check_plane_state() runs several checks on
plane src and dst rectangles, including the check whether required
scaling fits into the required margins. The msm driver would benefit
from having a function that does all these checks except the scaling
one. Split them into a new helper called
drm_atomic_helper_check_plane_noscale().

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/drm_atomic_helper.c | 85 ++++++++++++++++++++++-------
 include/drm/drm_atomic_helper.h     |  4 ++
 2 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index d579fd8f7cb8..86c5e19c7bdb 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -825,11 +825,9 @@ drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder,
 EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
 
 /**
- * drm_atomic_helper_check_plane_state() - Check plane state for validity
+ * drm_atomic_helper_check_plane_noscale() - Check plane state for validity
  * @plane_state: plane state to check
  * @crtc_state: CRTC state to check
- * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
- * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
  * @can_position: is it legal to position the plane such that it
  *                doesn't cover the entire CRTC?  This will generally
  *                only be false for primary planes.
@@ -845,19 +843,16 @@ EXPORT_SYMBOL(drm_atomic_helper_check_wb_encoder_state);
  * RETURNS:
  * Zero if update appears valid, error code on failure
  */
-int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
-					const struct drm_crtc_state *crtc_state,
-					int min_scale,
-					int max_scale,
-					bool can_position,
-					bool can_update_disabled)
+int drm_atomic_helper_check_plane_noscale(struct drm_plane_state *plane_state,
+					  const struct drm_crtc_state *crtc_state,
+					  bool can_position,
+					  bool can_update_disabled)
 {
 	struct drm_framebuffer *fb = plane_state->fb;
 	struct drm_rect *src = &plane_state->src;
 	struct drm_rect *dst = &plane_state->dst;
 	unsigned int rotation = plane_state->rotation;
 	struct drm_rect clip = {};
-	int hscale, vscale;
 
 	WARN_ON(plane_state->crtc && plane_state->crtc != crtc_state->crtc);
 
@@ -883,17 +878,6 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
 
 	drm_rect_rotate(src, fb->width << 16, fb->height << 16, rotation);
 
-	/* Check scaling */
-	hscale = drm_rect_calc_hscale(src, dst, min_scale, max_scale);
-	vscale = drm_rect_calc_vscale(src, dst, min_scale, max_scale);
-	if (hscale < 0 || vscale < 0) {
-		drm_dbg_kms(plane_state->plane->dev,
-			    "Invalid scaling of plane\n");
-		drm_rect_debug_print("src: ", &plane_state->src, true);
-		drm_rect_debug_print("dst: ", &plane_state->dst, false);
-		return -ERANGE;
-	}
-
 	if (crtc_state->enable)
 		drm_mode_get_hv_timing(&crtc_state->mode, &clip.x2, &clip.y2);
 
@@ -921,6 +905,65 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
 
 	return 0;
 }
+EXPORT_SYMBOL(drm_atomic_helper_check_plane_noscale);
+
+/**
+ * drm_atomic_helper_check_plane_state() - Check plane state for validity
+ * @plane_state: plane state to check
+ * @crtc_state: CRTC state to check
+ * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
+ * @max_scale: maximum @src:@dest scaling factor in 16.16 fixed point
+ * @can_position: is it legal to position the plane such that it
+ *                doesn't cover the entire CRTC?  This will generally
+ *                only be false for primary planes.
+ * @can_update_disabled: can the plane be updated while the CRTC
+ *                       is disabled?
+ *
+ * Checks that a desired plane update is valid, and updates various
+ * bits of derived state (clipped coordinates etc.). Drivers that provide
+ * their own plane handling rather than helper-provided implementations may
+ * still wish to call this function to avoid duplication of error checking
+ * code.
+ *
+ * RETURNS:
+ * Zero if update appears valid, error code on failure
+ */
+int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
+					const struct drm_crtc_state *crtc_state,
+					int min_scale,
+					int max_scale,
+					bool can_position,
+					bool can_update_disabled)
+{
+	struct drm_framebuffer *fb = plane_state->fb;
+	struct drm_rect src;
+	struct drm_rect dst;
+	int hscale, vscale, ret;
+
+	ret = drm_atomic_helper_check_plane_noscale(plane_state, crtc_state, can_position, can_update_disabled);
+	if (ret < 0)
+		return ret;
+
+	if (!plane_state->visible)
+		return 0;
+
+	src = drm_plane_state_src(plane_state);
+	dst = drm_plane_state_dest(plane_state);
+
+	drm_rect_rotate(&src, fb->width << 16, fb->height << 16, plane_state->rotation);
+
+	hscale = drm_rect_calc_hscale(&src, &dst, min_scale, max_scale);
+	vscale = drm_rect_calc_vscale(&src, &dst, min_scale, max_scale);
+	if (hscale < 0 || vscale < 0) {
+		drm_dbg_kms(plane_state->plane->dev,
+			    "Invalid scaling of plane\n");
+		drm_rect_debug_print("src: ", &plane_state->src, true);
+		drm_rect_debug_print("dst: ", &plane_state->dst, false);
+		return -ERANGE;
+	}
+
+	return 0;
+}
 EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
 
 /**
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 33f982cd1a27..ebf95437431d 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -52,6 +52,10 @@ int drm_atomic_helper_check_modeset(struct drm_device *dev,
 int
 drm_atomic_helper_check_wb_encoder_state(struct drm_encoder *encoder,
 					 struct drm_connector_state *conn_state);
+int drm_atomic_helper_check_plane_noscale(struct drm_plane_state *plane_state,
+					  const struct drm_crtc_state *crtc_state,
+					  bool can_position,
+					  bool can_update_disabled);
 int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
 					const struct drm_crtc_state *crtc_state,
 					int min_scale,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 01/13] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-12 22:12   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling Dmitry Baryshkov
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

Take into account the plane rotation and flipping when calculating src
positions for the wide plane parts.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++++++++++++++---------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 2e63eb0a2f3f..d43e04fc4578 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -887,16 +887,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 		return -EINVAL;
 	}
 
-	pipe_cfg->src_rect = new_plane_state->src;
-
-	/* state->src is 16.16, src_rect is not */
-	pipe_cfg->src_rect.x1 >>= 16;
-	pipe_cfg->src_rect.x2 >>= 16;
-	pipe_cfg->src_rect.y1 >>= 16;
-	pipe_cfg->src_rect.y2 >>= 16;
-
-	pipe_cfg->dst_rect = new_plane_state->dst;
-
 	fb_rect.x2 = new_plane_state->fb->width;
 	fb_rect.y2 = new_plane_state->fb->height;
 
@@ -912,6 +902,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 
 	max_linewidth = pdpu->catalog->caps->max_linewidth;
 
+	/* state->src is 16.16, src_rect is not */
+	drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
+
+	pipe_cfg->dst_rect = new_plane_state->dst;
+
+	drm_rect_rotate(&pipe_cfg->src_rect,
+			new_plane_state->fb->width, new_plane_state->fb->height,
+			new_plane_state->rotation);
+
 	if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
 		/*
 		 * In parallel multirect case only the half of the usual width
@@ -959,6 +958,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 		r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
 	}
 
+	drm_rect_rotate_inv(&pipe_cfg->src_rect,
+			    new_plane_state->fb->width, new_plane_state->fb->height,
+			    new_plane_state->rotation);
+	if (r_pipe->sspp)
+		drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
+				    new_plane_state->fb->width, new_plane_state->fb->height,
+				    new_plane_state->rotation);
+
 	ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
 	if (ret)
 		return ret;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 01/13] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-12 22:18   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt Dmitry Baryshkov
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

As the debugfs is fully cleared on drm device removal, drop the
encoder-specific cleanup function, remove debugfs_root from dpu_encoder
struct and also remove phys_encoder late_register() ops which has been
unused since the driver being added.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 22 +++----------------
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  3 ---
 2 files changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 97d8d777f178..28729c77364f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -142,7 +142,6 @@ enum dpu_enc_rc_states {
  * @crtc_kickoff_cb:		Callback into CRTC that will flush & start
  *				all CTL paths
  * @crtc_kickoff_cb_data:	Opaque user data given to crtc_kickoff_cb
- * @debugfs_root:		Debug file system root file node
  * @enc_lock:			Lock around physical encoder
  *				create/destroy/enable/disable
  * @frame_busy_mask:		Bitmask tracking which phys_enc we are still
@@ -186,7 +185,6 @@ struct dpu_encoder_virt {
 	struct drm_crtc *crtc;
 	struct drm_connector *connector;
 
-	struct dentry *debugfs_root;
 	struct mutex enc_lock;
 	DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL);
 	void (*crtc_frame_event_cb)(void *, u32 event);
@@ -2134,7 +2132,7 @@ DEFINE_SHOW_ATTRIBUTE(_dpu_encoder_status);
 static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
 {
 	struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
-	int i;
+	struct dentry *debugfs_root;
 
 	char name[DPU_NAME_SIZE];
 
@@ -2146,18 +2144,12 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
 	snprintf(name, DPU_NAME_SIZE, "encoder%u", drm_enc->base.id);
 
 	/* create overall sub-directory for the encoder */
-	dpu_enc->debugfs_root = debugfs_create_dir(name,
+	debugfs_root = debugfs_create_dir(name,
 			drm_enc->dev->primary->debugfs_root);
 
 	/* don't error check these */
 	debugfs_create_file("status", 0600,
-		dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
-
-	for (i = 0; i < dpu_enc->num_phys_encs; i++)
-		if (dpu_enc->phys_encs[i]->ops.late_register)
-			dpu_enc->phys_encs[i]->ops.late_register(
-					dpu_enc->phys_encs[i],
-					dpu_enc->debugfs_root);
+		debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
 
 	return 0;
 }
@@ -2173,13 +2165,6 @@ static int dpu_encoder_late_register(struct drm_encoder *encoder)
 	return _dpu_encoder_init_debugfs(encoder);
 }
 
-static void dpu_encoder_early_unregister(struct drm_encoder *encoder)
-{
-	struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder);
-
-	debugfs_remove_recursive(dpu_enc->debugfs_root);
-}
-
 static int dpu_encoder_virt_add_phys_encs(
 		struct msm_display_info *disp_info,
 		struct dpu_encoder_virt *dpu_enc,
@@ -2406,7 +2391,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
 static const struct drm_encoder_funcs dpu_encoder_funcs = {
 		.destroy = dpu_encoder_destroy,
 		.late_register = dpu_encoder_late_register,
-		.early_unregister = dpu_encoder_early_unregister,
 };
 
 int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 1d434b22180d..9e29079a6fc4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -63,7 +63,6 @@ struct dpu_encoder_phys;
 /**
  * struct dpu_encoder_phys_ops - Interface the physical encoders provide to
  *	the containing virtual encoder.
- * @late_register:		DRM Call. Add Userspace interfaces, debugfs.
  * @prepare_commit:		MSM Atomic Call, start of atomic commit sequence
  * @is_master:			Whether this phys_enc is the current master
  *				encoder. Can be switched at enable time. Based
@@ -93,8 +92,6 @@ struct dpu_encoder_phys;
  */
 
 struct dpu_encoder_phys_ops {
-	int (*late_register)(struct dpu_encoder_phys *encoder,
-			struct dentry *debugfs_root);
 	void (*prepare_commit)(struct dpu_encoder_phys *encoder);
 	bool (*is_master)(struct dpu_encoder_phys *encoder);
 	void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (2 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-06-06 20:25   ` [Freedreno] " Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements Dmitry Baryshkov
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

Remove historical fields intfs_swapped and topology fields from struct
dpu_encoder_virt and also remove even more historical docs.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 28729c77364f..4ee708264f3b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -130,18 +130,12 @@ enum dpu_enc_rc_states {
  *			pingpong blocks can be different than num_phys_encs.
  * @hw_dsc:		Handle to the DSC blocks used for the display.
  * @dsc_mask:		Bitmask of used DSC blocks.
- * @intfs_swapped:	Whether or not the phys_enc interfaces have been swapped
- *			for partial update right-only cases, such as pingpong
- *			split where virtual pingpong does not generate IRQs
  * @crtc:		Pointer to the currently assigned crtc. Normally you
  *			would use crtc->state->encoder_mask to determine the
  *			link between encoder/crtc. However in this case we need
  *			to track crtc in the disable() hook which is called
  *			_after_ encoder_mask is cleared.
  * @connector:		If a mode is set, cached pointer to the active connector
- * @crtc_kickoff_cb:		Callback into CRTC that will flush & start
- *				all CTL paths
- * @crtc_kickoff_cb_data:	Opaque user data given to crtc_kickoff_cb
  * @enc_lock:			Lock around physical encoder
  *				create/destroy/enable/disable
  * @frame_busy_mask:		Bitmask tracking which phys_enc we are still
@@ -160,7 +154,6 @@ enum dpu_enc_rc_states {
  * @delayed_off_work:		delayed worker to schedule disabling of
  *				clks and resources after IDLE_TIMEOUT time.
  * @vsync_event_work:		worker to handle vsync event for autorefresh
- * @topology:                   topology of the display
  * @idle_timeout:		idle timeout duration in milliseconds
  * @wide_bus_en:		wide bus is enabled on this interface
  * @dsc:			drm_dsc_config pointer, for DSC-enabled encoders
@@ -180,8 +173,6 @@ struct dpu_encoder_virt {
 
 	unsigned int dsc_mask;
 
-	bool intfs_swapped;
-
 	struct drm_crtc *crtc;
 	struct drm_connector *connector;
 
@@ -201,7 +192,6 @@ struct dpu_encoder_virt {
 	enum dpu_enc_rc_states rc_state;
 	struct delayed_work delayed_off_work;
 	struct kthread_work vsync_event_work;
-	struct msm_display_topology topology;
 
 	u32 idle_timeout;
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (3 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-12 22:39   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Dmitry Baryshkov
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

The struct dpu_rm_requirements was used to wrap display topology and
hw resources, which meant INTF indices. As of commit ef58e0ad3436
("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
resources struct was removed, leaving struct dpu_rm_requirements
containing a single field (topology). Remove the useless wrapper.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 69 +++++++--------------
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  2 +-
 3 files changed, 23 insertions(+), 50 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 4ee708264f3b..a2cb23dea0b8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -638,7 +638,7 @@ static int dpu_encoder_virt_atomic_check(
 
 		if (!crtc_state->active_changed || crtc_state->enable)
 			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					drm_enc, crtc_state, topology);
+					drm_enc, crtc_state, &topology);
 	}
 
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f4dda88a73f7..952e139c0234 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -24,15 +24,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
 	return res_map[idx] && res_map[idx] != enc_id;
 }
 
-/**
- * struct dpu_rm_requirements - Reservation requirements parameter bundle
- * @topology:  selected topology for the display
- * @hw_res:	   Hardware resources required as reported by the encoders
- */
-struct dpu_rm_requirements {
-	struct msm_display_topology topology;
-};
-
 int dpu_rm_destroy(struct dpu_rm *rm)
 {
 	int i;
@@ -329,14 +320,13 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
  *      mixer in rm->pingpong_blks[].
  * @dspp_idx: output parameter, index of dspp block attached to the layer
  *      mixer in rm->dspp_blks[].
- * @reqs: input parameter, rm requirements for HW blocks needed in the
- *      datapath.
+ * @topology:  selected topology for the display
  * Return: true if lm matches all requirements, false otherwise
  */
 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
 		uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
-		struct dpu_rm_requirements *reqs)
+		struct msm_display_topology *topology)
 {
 	const struct dpu_lm_cfg *lm_cfg;
 	int idx;
@@ -361,7 +351,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 	}
 	*pp_idx = idx;
 
-	if (!reqs->topology.num_dspp)
+	if (!topology->num_dspp)
 		return true;
 
 	idx = lm_cfg->dspp - DSPP_0;
@@ -383,7 +373,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 			       struct dpu_global_state *global_state,
 			       uint32_t enc_id,
-			       struct dpu_rm_requirements *reqs)
+			       struct msm_display_topology *topology)
 
 {
 	int lm_idx[MAX_BLOCKS];
@@ -391,14 +381,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 	int dspp_idx[MAX_BLOCKS] = {0};
 	int i, j, lm_count = 0;
 
-	if (!reqs->topology.num_lm) {
-		DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
+	if (!topology->num_lm) {
+		DPU_ERROR("invalid number of lm: %d\n", topology->num_lm);
 		return -EINVAL;
 	}
 
 	/* Find a primary mixer */
 	for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
-			lm_count < reqs->topology.num_lm; i++) {
+			lm_count < topology->num_lm; i++) {
 		if (!rm->mixer_blks[i])
 			continue;
 
@@ -407,7 +397,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 
 		if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
 				enc_id, i, &pp_idx[lm_count],
-				&dspp_idx[lm_count], reqs)) {
+				&dspp_idx[lm_count], topology)) {
 			continue;
 		}
 
@@ -415,7 +405,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 
 		/* Valid primary mixer found, find matching peers */
 		for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
-				lm_count < reqs->topology.num_lm; j++) {
+				lm_count < topology->num_lm; j++) {
 			if (!rm->mixer_blks[j])
 				continue;
 
@@ -428,7 +418,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 			if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
 					global_state, enc_id, j,
 					&pp_idx[lm_count], &dspp_idx[lm_count],
-					reqs)) {
+					topology)) {
 				continue;
 			}
 
@@ -437,7 +427,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 		}
 	}
 
-	if (lm_count != reqs->topology.num_lm) {
+	if (lm_count != topology->num_lm) {
 		DPU_DEBUG("unable to find appropriate mixers\n");
 		return -ENAVAIL;
 	}
@@ -446,7 +436,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 		global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
 		global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
 		global_state->dspp_to_enc_id[dspp_idx[i]] =
-			reqs->topology.num_dspp ? enc_id : 0;
+			topology->num_dspp ? enc_id : 0;
 
 		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
 					 pp_idx[i] + PINGPONG_0);
@@ -539,44 +529,30 @@ static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
 		struct drm_encoder *enc,
-		struct dpu_rm_requirements *reqs)
+		struct msm_display_topology *topology)
 {
 	int ret;
 
-	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
+	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
 	if (ret) {
 		DPU_ERROR("unable to find appropriate mixers\n");
 		return ret;
 	}
 
 	ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
-				&reqs->topology);
+				   topology);
 	if (ret) {
 		DPU_ERROR("unable to find appropriate CTL\n");
 		return ret;
 	}
 
-	ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
+	ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
 	if (ret)
 		return ret;
 
 	return ret;
 }
 
-static int _dpu_rm_populate_requirements(
-		struct drm_encoder *enc,
-		struct dpu_rm_requirements *reqs,
-		struct msm_display_topology req_topology)
-{
-	reqs->topology = req_topology;
-
-	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
-		      reqs->topology.num_lm, reqs->topology.num_dsc,
-		      reqs->topology.num_intf);
-
-	return 0;
-}
-
 static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
 				  uint32_t enc_id)
 {
@@ -608,9 +584,8 @@ int dpu_rm_reserve(
 		struct dpu_global_state *global_state,
 		struct drm_encoder *enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology)
+		struct msm_display_topology *topology)
 {
-	struct dpu_rm_requirements reqs;
 	int ret;
 
 	/* Check if this is just a page-flip */
@@ -625,13 +600,11 @@ int dpu_rm_reserve(
 	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
 		      enc->base.id, crtc_state->crtc->base.id);
 
-	ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
-	if (ret) {
-		DPU_ERROR("failed to populate hw requirements\n");
-		return ret;
-	}
+	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
+		      topology->num_lm, topology->num_dsc,
+		      topology->num_intf);
 
-	ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
+	ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
 	if (ret)
 		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index d62c2edb2460..f05697462856 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -71,7 +71,7 @@ int dpu_rm_reserve(struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology);
+		struct msm_display_topology *topology);
 
 /**
  * dpu_rm_reserve - Given the encoder for the display chain, release any
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (4 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-18 23:46   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 07/13] drm/msm/dpu: move resource allocation to CRTC Dmitry Baryshkov
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

Up to now the driver has been using encoder to allocate hardware
resources. Switch it to use CRTC id in preparation for the next step.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  16 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  10 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 119 ++++++++++----------
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  15 ++-
 4 files changed, 77 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index a2cb23dea0b8..270c85ea898a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -634,11 +634,11 @@ static int dpu_encoder_virt_atomic_check(
 	 * Dont allocate when active is false.
 	 */
 	if (drm_atomic_crtc_needs_modeset(crtc_state)) {
-		dpu_rm_release(global_state, drm_enc);
+		dpu_rm_release(global_state, crtc_state->crtc);
 
 		if (!crtc_state->active_changed || crtc_state->enable)
 			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					drm_enc, crtc_state, &topology);
+					crtc_state->crtc, &topology);
 	}
 
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
@@ -1034,14 +1034,14 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 
 	/* Query resource that have been reserved in atomic check step. */
 	num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
+		drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
 		ARRAY_SIZE(hw_pp));
 	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
+		drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
 	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
+		drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
 	dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
+		drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
 		ARRAY_SIZE(hw_dspp));
 
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
@@ -1050,7 +1050,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 
 	if (dpu_enc->dsc) {
 		num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-							drm_enc->base.id, DPU_HW_BLK_DSC,
+							drm_enc->crtc, DPU_HW_BLK_DSC,
 							hw_dsc, ARRAY_SIZE(hw_dsc));
 		for (i = 0; i < num_dsc; i++) {
 			dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
@@ -1994,7 +1994,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
 	global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
 
 	num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
-		phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
+		phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
 
 	for (i = 0; i < num_lm; i++) {
 		hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index ed80ed6784ee..934874eb2248 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -129,11 +129,11 @@ struct vsync_info {
 struct dpu_global_state {
 	struct drm_private_state base;
 
-	uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
-	uint32_t mixer_to_enc_id[LM_MAX - LM_0];
-	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
-	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
-	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
+	uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
+	uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
+	uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
+	uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
+	uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 952e139c0234..f0a94008d17a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -19,9 +19,9 @@
 
 
 static inline bool reserved_by_other(uint32_t *res_map, int idx,
-				     uint32_t enc_id)
+				     uint32_t crtc_id)
 {
-	return res_map[idx] && res_map[idx] != enc_id;
+	return res_map[idx] && res_map[idx] != crtc_id;
 }
 
 int dpu_rm_destroy(struct dpu_rm *rm)
@@ -312,7 +312,7 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
  *	pingpong
  * @rm: dpu resource manager handle
  * @global_state: resources shared across multiple kms objects
- * @enc_id: encoder id requesting for allocation
+ * @crtc_id: encoder id requesting for allocation
  * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
  *      if lm, and all other hardwired blocks connected to the lm (pp) is
  *      available and appropriate
@@ -325,14 +325,14 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
  */
 static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
-		uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
+		uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
 		struct msm_display_topology *topology)
 {
 	const struct dpu_lm_cfg *lm_cfg;
 	int idx;
 
 	/* Already reserved? */
-	if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
+	if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
 		DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
 		return false;
 	}
@@ -344,7 +344,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 		return false;
 	}
 
-	if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
+	if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
 		DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
 				lm_cfg->pingpong);
 		return false;
@@ -360,7 +360,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 		return false;
 	}
 
-	if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
+	if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
 		DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
 				lm_cfg->dspp);
 		return false;
@@ -372,7 +372,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
 
 static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 			       struct dpu_global_state *global_state,
-			       uint32_t enc_id,
+			       uint32_t crtc_id,
 			       struct msm_display_topology *topology)
 
 {
@@ -396,7 +396,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 		lm_idx[lm_count] = i;
 
 		if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
-				enc_id, i, &pp_idx[lm_count],
+				crtc_id, i, &pp_idx[lm_count],
 				&dspp_idx[lm_count], topology)) {
 			continue;
 		}
@@ -416,7 +416,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 			}
 
 			if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
-					global_state, enc_id, j,
+					global_state, crtc_id, j,
 					&pp_idx[lm_count], &dspp_idx[lm_count],
 					topology)) {
 				continue;
@@ -433,12 +433,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 	}
 
 	for (i = 0; i < lm_count; i++) {
-		global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
-		global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
-		global_state->dspp_to_enc_id[dspp_idx[i]] =
-			topology->num_dspp ? enc_id : 0;
+		global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
+		global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
+		global_state->dspp_to_crtc_id[dspp_idx[i]] =
+			topology->num_dspp ? crtc_id : 0;
 
-		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
+		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
 					 pp_idx[i] + PINGPONG_0);
 	}
 
@@ -448,7 +448,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
 static int _dpu_rm_reserve_ctls(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
-		uint32_t enc_id,
+		uint32_t crtc_id,
 		const struct msm_display_topology *top)
 {
 	int ctl_idx[MAX_BLOCKS];
@@ -467,7 +467,7 @@ static int _dpu_rm_reserve_ctls(
 
 		if (!rm->ctl_blks[j])
 			continue;
-		if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
+		if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
 			continue;
 
 		ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
@@ -491,8 +491,8 @@ static int _dpu_rm_reserve_ctls(
 		return -ENAVAIL;
 
 	for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
-		global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
-		trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
+		global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
+		trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
 	}
 
 	return 0;
@@ -500,7 +500,7 @@ static int _dpu_rm_reserve_ctls(
 
 static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
 			       struct dpu_global_state *global_state,
-			       struct drm_encoder *enc,
+			       uint32_t crtc_id,
 			       const struct msm_display_topology *top)
 {
 	int num_dsc = top->num_dsc;
@@ -513,14 +513,14 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
 			return -EIO;
 		}
 
-		if (global_state->dsc_to_enc_id[i]) {
+		if (global_state->dsc_to_crtc_id[i]) {
 			DPU_ERROR("DSC %d is already allocated\n", i);
 			return -EIO;
 		}
 	}
 
 	for (i = 0; i < num_dsc; i++)
-		global_state->dsc_to_enc_id[i] = enc->base.id;
+		global_state->dsc_to_crtc_id[i] = crtc_id;
 
 	return 0;
 }
@@ -528,25 +528,25 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
 static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
-		struct drm_encoder *enc,
+		uint32_t crtc_id,
 		struct msm_display_topology *topology)
 {
 	int ret;
 
-	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
+	ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
 	if (ret) {
 		DPU_ERROR("unable to find appropriate mixers\n");
 		return ret;
 	}
 
-	ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
+	ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
 				   topology);
 	if (ret) {
 		DPU_ERROR("unable to find appropriate CTL\n");
 		return ret;
 	}
 
-	ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
+	ret  = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
 	if (ret)
 		return ret;
 
@@ -554,97 +554,92 @@ static int _dpu_rm_make_reservation(
 }
 
 static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
-				  uint32_t enc_id)
+				  uint32_t crtc_id)
 {
 	int i;
 
 	for (i = 0; i < cnt; i++) {
-		if (res_mapping[i] == enc_id)
+		if (res_mapping[i] == crtc_id)
 			res_mapping[i] = 0;
 	}
 }
 
 void dpu_rm_release(struct dpu_global_state *global_state,
-		    struct drm_encoder *enc)
+		    struct drm_crtc *crtc)
 {
-	_dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
-		ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
-	_dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
-		ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
-	_dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
-		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
-	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
-		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
-	_dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
-		ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
+	uint32_t crtc_id = crtc->base.id;
+
+	_dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
+		ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
+	_dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
+		ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
+	_dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
+		ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
+	_dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
+		ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
+	_dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
+		ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
 }
 
 int dpu_rm_reserve(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
-		struct drm_encoder *enc,
-		struct drm_crtc_state *crtc_state,
+		struct drm_crtc *crtc,
 		struct msm_display_topology *topology)
 {
 	int ret;
 
-	/* Check if this is just a page-flip */
-	if (!drm_atomic_crtc_needs_modeset(crtc_state))
-		return 0;
-
 	if (IS_ERR(global_state)) {
 		DPU_ERROR("failed to global state\n");
 		return PTR_ERR(global_state);
 	}
 
-	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
-		      enc->base.id, crtc_state->crtc->base.id);
+	DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
 
 	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
 		      topology->num_lm, topology->num_dsc,
 		      topology->num_intf);
 
-	ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
+	ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
 	if (ret)
 		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
 
-
-
 	return ret;
 }
 
 int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
-	struct dpu_global_state *global_state, uint32_t enc_id,
+	struct dpu_global_state *global_state, struct drm_crtc *crtc,
 	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
 {
+	uint32_t crtc_id = crtc->base.id;
 	struct dpu_hw_blk **hw_blks;
-	uint32_t *hw_to_enc_id;
+	uint32_t *hw_to_crtc_id;
 	int i, num_blks, max_blks;
 
 	switch (type) {
 	case DPU_HW_BLK_PINGPONG:
 		hw_blks = rm->pingpong_blks;
-		hw_to_enc_id = global_state->pingpong_to_enc_id;
+		hw_to_crtc_id = global_state->pingpong_to_crtc_id;
 		max_blks = ARRAY_SIZE(rm->pingpong_blks);
 		break;
 	case DPU_HW_BLK_LM:
 		hw_blks = rm->mixer_blks;
-		hw_to_enc_id = global_state->mixer_to_enc_id;
+		hw_to_crtc_id = global_state->mixer_to_crtc_id;
 		max_blks = ARRAY_SIZE(rm->mixer_blks);
 		break;
 	case DPU_HW_BLK_CTL:
 		hw_blks = rm->ctl_blks;
-		hw_to_enc_id = global_state->ctl_to_enc_id;
+		hw_to_crtc_id = global_state->ctl_to_crtc_id;
 		max_blks = ARRAY_SIZE(rm->ctl_blks);
 		break;
 	case DPU_HW_BLK_DSPP:
 		hw_blks = rm->dspp_blks;
-		hw_to_enc_id = global_state->dspp_to_enc_id;
+		hw_to_crtc_id = global_state->dspp_to_crtc_id;
 		max_blks = ARRAY_SIZE(rm->dspp_blks);
 		break;
 	case DPU_HW_BLK_DSC:
 		hw_blks = rm->dsc_blks;
-		hw_to_enc_id = global_state->dsc_to_enc_id;
+		hw_to_crtc_id = global_state->dsc_to_crtc_id;
 		max_blks = ARRAY_SIZE(rm->dsc_blks);
 		break;
 	default:
@@ -654,17 +649,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 
 	num_blks = 0;
 	for (i = 0; i < max_blks; i++) {
-		if (hw_to_enc_id[i] != enc_id)
+		if (hw_to_crtc_id[i] != crtc_id)
 			continue;
 
 		if (num_blks == blks_size) {
-			DPU_ERROR("More than %d resources assigned to enc %d\n",
-				  blks_size, enc_id);
+			DPU_ERROR("More than %d resources assigned to crtc %d\n",
+				  blks_size, crtc_id);
 			break;
 		}
 		if (!hw_blks[i]) {
-			DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
-				  type, enc_id);
+			DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
+				  type, crtc_id);
 			break;
 		}
 		blks[num_blks++] = hw_blks[i];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index f05697462856..f402bec8322b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -62,32 +62,31 @@ int dpu_rm_destroy(struct dpu_rm *rm);
  *	HW blocks can then be accessed through dpu_rm_get_* functions.
  *	HW Reservations should be released via dpu_rm_release_hw.
  * @rm: DPU Resource Manager handle
- * @drm_enc: DRM Encoder handle
- * @crtc_state: Proposed Atomic DRM CRTC State handle
+ * @crtc: DRM CRTC handle
  * @topology: Pointer to topology info for the display
  * @Return: 0 on Success otherwise -ERROR
  */
-int dpu_rm_reserve(struct dpu_rm *rm,
+int dpu_rm_reserve(
+		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
-		struct drm_encoder *drm_enc,
-		struct drm_crtc_state *crtc_state,
+		struct drm_crtc *crtc,
 		struct msm_display_topology *topology);
 
 /**
  * dpu_rm_reserve - Given the encoder for the display chain, release any
  *	HW blocks previously reserved for that use case.
  * @rm: DPU Resource Manager handle
- * @enc: DRM Encoder handle
+ * @crtc: DRM CRTC handle
  * @Return: 0 on Success otherwise -ERROR
  */
 void dpu_rm_release(struct dpu_global_state *global_state,
-		struct drm_encoder *enc);
+		struct drm_crtc *crtc);
 
 /**
  * Get hw resources of the given type that are assigned to this encoder.
  */
 int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
-	struct dpu_global_state *global_state, uint32_t enc_id,
+	struct dpu_global_state *global_state, struct drm_crtc *crtc,
 	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
 
 /**
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 07/13] drm/msm/dpu: move resource allocation to CRTC
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (5 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 08/13] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Dmitry Baryshkov
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

All resource allocation is centered around the LMs. Then other blocks
(except DSCs) are allocated basing on the LMs that was selected, and LM
powers up the CRTC rather than the encoder.

Moreover if at some point the driver supports encoder cloning,
allocating resources from the encoder will be incorrect, as all clones
will have different encoder IDs, while LMs are to be shared by these
encoders.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    | 76 ++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 88 +++------------------
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  8 ++
 3 files changed, 94 insertions(+), 78 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 508e5b950e52..77226de54363 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1176,6 +1176,76 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
 	return false;
 }
 
+#define MAX_HDISPLAY_SPLIT 1080
+
+static struct msm_display_topology dpu_crtc_get_topology(
+			struct drm_crtc *crtc,
+			struct dpu_kms *dpu_kms,
+			struct drm_crtc_state *crtc_state)
+{
+	struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+	struct msm_display_topology topology = {0};
+	struct drm_encoder *drm_enc;
+
+	drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
+		dpu_encoder_update_topology(drm_enc, &topology);
+
+	/*
+	 * Datapath topology selection
+	 *
+	 * Dual display
+	 * 2 LM, 2 INTF ( Split display using 2 interfaces)
+	 *
+	 * Single display
+	 * 1 LM, 1 INTF
+	 * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
+	 *
+	 * Add dspps to the reservation requirements if ctm is requested
+	 */
+	if (topology.num_intf == 2)
+		topology.num_lm = 2;
+	else if (topology.num_dsc == 2)
+		topology.num_lm = 2;
+	else if (dpu_kms->catalog->caps->has_3d_merge)
+		topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
+	else
+		topology.num_lm = 1;
+
+	if (crtc_state->ctm)
+		topology.num_dspp = topology.num_lm;
+
+	return topology;
+}
+
+static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
+{
+	struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
+	struct dpu_global_state *global_state;
+	struct msm_display_topology topology;
+	int ret;
+
+	/*
+	 * Release and Allocate resources on every modeset
+	 * Dont allocate when enable is false.
+	 */
+	global_state = dpu_kms_get_global_state(crtc_state->state);
+	if (IS_ERR(global_state))
+		return PTR_ERR(global_state);
+
+	dpu_rm_release(global_state, crtc);
+
+	if (!crtc_state->enable)
+		return 0;
+
+	topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
+	ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
+			     crtc, &topology);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 		struct drm_atomic_state *state)
 {
@@ -1191,6 +1261,12 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 
 	bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
 
+	if (drm_atomic_crtc_needs_modeset(crtc_state)) {
+		rc = dpu_crtc_assign_resources(crtc, crtc_state);
+		if (rc < 0)
+			return rc;
+	}
+
 	if (!crtc_state->enable || !crtc_state->active) {
 		DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
 				crtc->base.id, crtc_state->enable,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 270c85ea898a..204360485b81 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -53,8 +53,6 @@
 
 #define IDLE_SHORT_TIMEOUT	1
 
-#define MAX_HDISPLAY_SPLIT 1080
-
 /* timeout in frames waiting for frame done */
 #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5
 
@@ -514,71 +512,28 @@ void dpu_encoder_helper_split_config(
 	}
 }
 
-bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
+				 struct msm_display_topology *topology)
 {
 	struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
-	int i, intf_count = 0, num_dsc = 0;
+	int i;
 
 	for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
 		if (dpu_enc->phys_encs[i])
-			intf_count++;
+			topology->num_intf++;
 
-	/* See dpu_encoder_get_topology, we only support 2:2:1 topology */
+	/* We only support 2 DSC mode (with 2 LM and 1 INTF) */
 	if (dpu_enc->dsc)
-		num_dsc = 2;
-
-	return (num_dsc > 0) && (num_dsc > intf_count);
+		topology->num_dsc += 2;
 }
 
-static struct msm_display_topology dpu_encoder_get_topology(
-			struct dpu_encoder_virt *dpu_enc,
-			struct dpu_kms *dpu_kms,
-			struct drm_display_mode *mode,
-			struct drm_crtc_state *crtc_state)
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
 {
-	struct msm_display_topology topology = {0};
-	int i, intf_count = 0;
-
-	for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
-		if (dpu_enc->phys_encs[i])
-			intf_count++;
-
-	/* Datapath topology selection
-	 *
-	 * Dual display
-	 * 2 LM, 2 INTF ( Split display using 2 interfaces)
-	 *
-	 * Single display
-	 * 1 LM, 1 INTF
-	 * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
-	 *
-	 * Add dspps to the reservation requirements if ctm is requested
-	 */
-	if (intf_count == 2)
-		topology.num_lm = 2;
-	else if (!dpu_kms->catalog->caps->has_3d_merge)
-		topology.num_lm = 1;
-	else
-		topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
-
-	if (crtc_state->ctm)
-		topology.num_dspp = topology.num_lm;
+	struct msm_display_topology topology = { 0 };
 
-	topology.num_intf = intf_count;
+	dpu_encoder_update_topology(drm_enc, &topology);
 
-	if (dpu_enc->dsc) {
-		/*
-		 * In case of Display Stream Compression (DSC), we would use
-		 * 2 DSC encoders, 2 layer mixers and 1 interface
-		 * this is power optimal and can drive up to (including) 4k
-		 * screens
-		 */
-		topology.num_dsc = 2;
-		topology.num_lm = 2;
-		topology.num_intf = 1;
-	}
-
-	return topology;
+	return (topology.num_dsc > 0) && (topology.num_dsc > topology.num_intf);
 }
 
 static int dpu_encoder_virt_atomic_check(
@@ -587,11 +542,7 @@ static int dpu_encoder_virt_atomic_check(
 		struct drm_connector_state *conn_state)
 {
 	struct dpu_encoder_virt *dpu_enc;
-	struct msm_drm_private *priv;
-	struct dpu_kms *dpu_kms;
 	struct drm_display_mode *adj_mode;
-	struct msm_display_topology topology;
-	struct dpu_global_state *global_state;
 	int i = 0;
 	int ret = 0;
 
@@ -604,12 +555,7 @@ static int dpu_encoder_virt_atomic_check(
 	dpu_enc = to_dpu_encoder_virt(drm_enc);
 	DPU_DEBUG_ENC(dpu_enc, "\n");
 
-	priv = drm_enc->dev->dev_private;
-	dpu_kms = to_dpu_kms(priv->kms);
 	adj_mode = &crtc_state->adjusted_mode;
-	global_state = dpu_kms_get_global_state(crtc_state->state);
-	if (IS_ERR(global_state))
-		return PTR_ERR(global_state);
 
 	trace_dpu_enc_atomic_check(DRMID(drm_enc));
 
@@ -627,20 +573,6 @@ static int dpu_encoder_virt_atomic_check(
 		}
 	}
 
-	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state);
-
-	/*
-	 * Release and Allocate resources on every modeset
-	 * Dont allocate when active is false.
-	 */
-	if (drm_atomic_crtc_needs_modeset(crtc_state)) {
-		dpu_rm_release(global_state, crtc_state->crtc);
-
-		if (!crtc_state->active_changed || crtc_state->enable)
-			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					crtc_state->crtc, &topology);
-	}
-
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
 
 	return ret;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 9e7236ef34e6..88248b9faf1c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -202,6 +202,14 @@ int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
  */
 bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_update_topology - update topology with the requirements for the encoder
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ * @topology:	Topology to be updated
+ */
+void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
+				 struct msm_display_topology *topology);
+
 /**
  * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
  * @drm_enc:    Pointer to previously created drm encoder structure
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 08/13] drm/msm/dpu: fill CRTC resources in dpu_crtc.c
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (6 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 07/13] drm/msm/dpu: move resource allocation to CRTC Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check Dmitry Baryshkov
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

Stop poking into CRTC state from dpu_encoder.c, fill CRTC HW resources
from dpu_crtc_assign_resources().

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c    | 27 +++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 24 ++----------------
 2 files changed, 29 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 77226de54363..8ef191fd002d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1177,6 +1177,7 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
 }
 
 #define MAX_HDISPLAY_SPLIT 1080
+#define MAX_CHANNELS_PER_CRTC 2
 
 static struct msm_display_topology dpu_crtc_get_topology(
 			struct drm_crtc *crtc,
@@ -1219,9 +1220,14 @@ static struct msm_display_topology dpu_crtc_get_topology(
 
 static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
 {
+	struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_CRTC];
+	struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_CRTC];
+	struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_CRTC];
+	int i, num_lm, num_ctl, num_dspp;
 	struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
 	struct dpu_global_state *global_state;
 	struct msm_display_topology topology;
+	struct dpu_crtc_state *cstate;
 	int ret;
 
 	/*
@@ -1243,6 +1249,27 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
 	if (ret)
 		return ret;
 
+	cstate = to_dpu_crtc_state(crtc_state);
+
+	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
+	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
+	num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		crtc, DPU_HW_BLK_DSPP, hw_dspp,
+		ARRAY_SIZE(hw_dspp));
+
+	for (i = 0; i < num_lm; i++) {
+		int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
+
+		cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
+		cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
+		if (i < num_dspp)
+			cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
+	}
+
+	cstate->num_mixers = num_lm;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 204360485b81..068d4e47eaa9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -934,14 +934,11 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 	struct dpu_encoder_virt *dpu_enc;
 	struct msm_drm_private *priv;
 	struct dpu_kms *dpu_kms;
-	struct dpu_crtc_state *cstate;
 	struct dpu_global_state *global_state;
 	struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
-	struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
-	struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
 	struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
-	int num_lm, num_ctl, num_pp, num_dsc;
+	int num_pp, num_dsc;
 	unsigned int dsc_mask = 0;
 	int i;
 
@@ -968,13 +965,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 	num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
 		drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
 		ARRAY_SIZE(hw_pp));
-	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
-	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
 	dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-		drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
-		ARRAY_SIZE(hw_dspp));
+		drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
 
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
 		dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
@@ -992,18 +984,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 
 	dpu_enc->dsc_mask = dsc_mask;
 
-	cstate = to_dpu_crtc_state(crtc_state);
-
-	for (i = 0; i < num_lm; i++) {
-		int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
-
-		cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
-		cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
-		cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
-	}
-
-	cstate->num_mixers = num_lm;
-
 	dpu_enc->connector = conn_state->connector;
 
 	for (i = 0; i < dpu_enc->num_phys_encs; i++) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (7 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 08/13] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-24 22:46   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps Dmitry Baryshkov
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

In preparation to virtualized planes support, move pstate->pipe
initialization from dpu_plane_reset() to dpu_plane_atomic_check(). In
case of virtual planes the plane's pipe will not be known up to the
point of atomic_check() callback.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 23 +++++++++--------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index d43e04fc4578..cf17075676d5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -845,6 +845,7 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 	int ret = 0, min_scale;
 	struct dpu_plane *pdpu = to_dpu_plane(plane);
 	struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
+	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
 	struct dpu_sw_pipe *pipe = &pstate->pipe;
 	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
 	const struct drm_crtc_state *crtc_state = NULL;
@@ -855,13 +856,19 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 	uint32_t max_linewidth;
 	unsigned int rotation;
 	uint32_t supported_rotations;
-	const struct dpu_sspp_cfg *pipe_hw_caps = pstate->pipe.sspp->cap;
-	const struct dpu_sspp_sub_blks *sblk = pstate->pipe.sspp->cap->sblk;
+	const struct dpu_sspp_cfg *pipe_hw_caps;
+	const struct dpu_sspp_sub_blks *sblk;
 
 	if (new_plane_state->crtc)
 		crtc_state = drm_atomic_get_new_crtc_state(state,
 							   new_plane_state->crtc);
 
+	pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
+	r_pipe->sspp = NULL;
+
+	pipe_hw_caps = pstate->pipe.sspp->cap;
+	sblk = pstate->pipe.sspp->cap->sblk;
+
 	min_scale = FRAC_16_16(1, sblk->maxupscale);
 	ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
 						  min_scale,
@@ -878,7 +885,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 	pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
 	r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
 	r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
-	r_pipe->sspp = NULL;
 
 	pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos;
 	if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) {
@@ -1374,7 +1380,6 @@ static void dpu_plane_reset(struct drm_plane *plane)
 {
 	struct dpu_plane *pdpu;
 	struct dpu_plane_state *pstate;
-	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
 
 	if (!plane) {
 		DPU_ERROR("invalid plane\n");
@@ -1396,16 +1401,6 @@ static void dpu_plane_reset(struct drm_plane *plane)
 		return;
 	}
 
-	/*
-	 * Set the SSPP here until we have proper virtualized DPU planes.
-	 * This is the place where the state is allocated, so fill it fully.
-	 */
-	pstate->pipe.sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
-	pstate->pipe.multirect_index = DPU_SSPP_RECT_SOLO;
-	pstate->pipe.multirect_mode = DPU_SSPP_MULTIRECT_NONE;
-
-	pstate->r_pipe.sspp = NULL;
-
 	__drm_atomic_helper_plane_reset(plane, &pstate->base);
 }
 
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (8 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-24 23:16   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps Dmitry Baryshkov
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

As we are going to add virtual planes, add the list of supported formats
to the hw catalog entry. It will be used to setup universal planes, with
later selecting a pipe depending on whether the YUV format is used for
the framebuffer.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 +++++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
 2 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 212d546b6c5d..2d6944a9679a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
 	.max_hdeci_exp = MAX_HORZ_DECIMATION,
 	.max_vdeci_exp = MAX_VERT_DECIMATION,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps qcm2290_dpu_caps = {
@@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
 	.has_idle_pc = true,
 	.max_linewidth = 2160,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sdm845_dpu_caps = {
@@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
 	.max_hdeci_exp = MAX_HORZ_DECIMATION,
 	.max_vdeci_exp = MAX_VERT_DECIMATION,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sc7180_dpu_caps = {
@@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
 	.has_idle_pc = true,
 	.max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sm6115_dpu_caps = {
@@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
 	.has_idle_pc = true,
 	.max_linewidth = 2160,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sm8150_dpu_caps = {
@@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
 	.max_hdeci_exp = MAX_HORZ_DECIMATION,
 	.max_vdeci_exp = MAX_VERT_DECIMATION,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sc8180x_dpu_caps = {
@@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
 	.max_hdeci_exp = MAX_HORZ_DECIMATION,
 	.max_vdeci_exp = MAX_VERT_DECIMATION,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sc8280xp_dpu_caps = {
@@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
 	.has_3d_merge = true,
 	.max_linewidth = 5120,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sm8250_dpu_caps = {
@@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
 	.has_3d_merge = true,
 	.max_linewidth = 900,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sm8350_dpu_caps = {
@@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
 	.has_3d_merge = true,
 	.max_linewidth = 4096,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sm8450_dpu_caps = {
@@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
 	.has_3d_merge = true,
 	.max_linewidth = 5120,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sm8550_dpu_caps = {
@@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
 	.has_3d_merge = true,
 	.max_linewidth = 5120,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_caps sc7280_dpu_caps = {
@@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
 	.has_idle_pc = true,
 	.max_linewidth = 2400,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+	.format_list = plane_formats_yuv,
+	.num_formats = ARRAY_SIZE(plane_formats_yuv),
 };
 
 static const struct dpu_mdp_cfg msm8998_mdp[] = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 89b372cdca92..4847aae78db2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
  * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
  * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
  * @max_vdeci_exp      max vertical decimation supported (max is 2^value)
+ * @format_list: Pointer to list of supported formats
+ * @num_formats: Number of supported formats
  */
 struct dpu_caps {
 	u32 max_mixer_width;
@@ -419,6 +421,8 @@ struct dpu_caps {
 	u32 pixel_ram_size;
 	u32 max_hdeci_exp;
 	u32 max_vdeci_exp;
+	const u32 *format_list;
+	u32 num_formats;
 };
 
 /**
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (9 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-05-24 23:20   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes Dmitry Baryshkov
  2023-03-21  1:18 ` [RFC PATCH v2 13/13] drm/msm/dpu: allow using two SSPP blocks for a single plane Dmitry Baryshkov
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

We need to know if the platform supports inline rotation on any of the
SSPP blocks or not. Add this information to struct dpu_caps in a form of
the boolean field has_inline_rot.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 ++
 2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 2d6944a9679a..33527ec7c938 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -489,6 +489,7 @@ static const struct dpu_caps sc7280_dpu_caps = {
 	.ubwc_version = DPU_HW_UBWC_VER_30,
 	.has_dim_layer = true,
 	.has_idle_pc = true,
+	.has_inline_rot = true,
 	.max_linewidth = 2400,
 	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
 	.format_list = plane_formats_yuv,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 4847aae78db2..cc64fb2e815f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -400,6 +400,7 @@ struct dpu_rotation_cfg {
  * @has_dim_layer      dim layer feature status
  * @has_idle_pc        indicate if idle power collapse feature is supported
  * @has_3d_merge       indicate if 3D merge is supported
+ * @has_inline_rot     indicate if inline rotation is supported
  * @max_linewidth      max linewidth for sspp
  * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
  * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
@@ -416,6 +417,7 @@ struct dpu_caps {
 	bool has_dim_layer;
 	bool has_idle_pc;
 	bool has_3d_merge;
+	bool has_inline_rot;
 	/* SSPP limits */
 	u32 max_linewidth;
 	u32 pixel_ram_size;
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (10 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  2023-06-07 21:05   ` Abhinav Kumar
  2023-03-21  1:18 ` [RFC PATCH v2 13/13] drm/msm/dpu: allow using two SSPP blocks for a single plane Dmitry Baryshkov
  12 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

Only several SSPP blocks support such features as YUV output or scaling,
thus different DRM planes have different features.  Properly utilizing
all planes requires the attention of the compositor, who should
prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
to end up in a situation when all featureful planes are already
allocated for simple windows, leaving no spare plane for YUV playback.

To solve this problem make all planes virtual. Each plane is registered
as if it supports all possible features, but then at the runtime during
the atomic_check phase the driver selects backing SSPP block for each
plane.

Note, this does not provide support for using two different SSPP blocks
for a single plane or using two rectangles of an SSPP to drive two
planes. Each plane still gets its own SSPP and can utilize either a solo
rectangle or both multirect rectangles depending on the resolution.

Note #2: By default support for virtual planes is turned off and the
driver still uses old code path with preallocated SSPP block for each
plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
kernel parameter.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  59 +++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 120 ++++++++++----
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 187 ++++++++++++++++++----
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  24 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c    |  65 ++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h    |  24 +++
 7 files changed, 413 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 8ef191fd002d..cdece21b81c9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1273,6 +1273,29 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
 	return 0;
 }
 
+static int dpu_crtc_assign_plane_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
+{
+	struct dpu_global_state *global_state;
+	struct drm_plane *plane;
+	int rc;
+
+	global_state = dpu_kms_get_global_state(crtc_state->state);
+	if (IS_ERR(global_state))
+		return PTR_ERR(global_state);
+
+	dpu_rm_release_all_sspp(global_state, crtc);
+
+	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
+		rc = dpu_plane_virtual_assign_resources(plane, crtc,
+							global_state,
+							crtc_state->state);
+		if (rc)
+			return rc;
+	}
+
+	return 0;
+}
+
 static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 		struct drm_atomic_state *state)
 {
@@ -1281,7 +1304,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 	struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
 	struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
 
-	const struct drm_plane_state *pstate;
 	struct drm_plane *plane;
 
 	int rc = 0;
@@ -1294,6 +1316,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 			return rc;
 	}
 
+	if (dpu_use_virtual_planes &&
+	    crtc_state->planes_changed) {
+		rc = dpu_crtc_assign_plane_resources(crtc, crtc_state);
+		if (rc < 0)
+			return rc;
+	}
+
 	if (!crtc_state->enable || !crtc_state->active) {
 		DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
 				crtc->base.id, crtc_state->enable,
@@ -1311,20 +1340,30 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 	if (cstate->num_mixers)
 		_dpu_crtc_setup_lm_bounds(crtc, crtc_state);
 
-	/* FIXME: move this to dpu_plane_atomic_check? */
-	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
-		struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate);
-
-		if (IS_ERR_OR_NULL(pstate)) {
-			rc = PTR_ERR(pstate);
-			DPU_ERROR("%s: failed to get plane%d state, %d\n",
-					dpu_crtc->name, plane->base.id, rc);
-			return rc;
+	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
+		const struct drm_plane_state *pstate;
+		struct dpu_plane_state *dpu_pstate;
+
+		pstate = drm_atomic_get_plane_state(crtc_state->state, plane);
+		if (IS_ERR(pstate))
+			return PTR_ERR(pstate);
+
+		if (dpu_use_virtual_planes) {
+			/*
+			 * In case of virtual planes, the plane's atomic_check
+			 * is a shortcut. Perform actual check here, after
+			 * allocating SSPPs.
+			 */
+			rc = dpu_plane_atomic_check(plane, crtc_state->state);
+			if (rc)
+				return rc;
 		}
 
 		if (!pstate->visible)
 			continue;
 
+		/* FIXME: move this to dpu_plane_atomic_check? */
+		dpu_pstate = to_dpu_plane_state(pstate);
 		dpu_pstate->needs_dirtyfb = needs_dirtyfb;
 	}
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 35194262e628..487bb19ee9d6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -50,6 +50,9 @@
 #define DPU_DEBUGFS_DIR "msm_dpu"
 #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
 
+bool dpu_use_virtual_planes = false;
+module_param(dpu_use_virtual_planes, bool, 0);
+
 static int dpu_kms_hw_init(struct msm_kms *kms);
 static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
 
@@ -735,38 +738,54 @@ static int _dpu_kms_setup_displays(struct drm_device *dev,
 	return rc;
 }
 
-#define MAX_PLANES 20
-static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
+static int dpu_kms_create_virtual_planes(struct dpu_kms *dpu_kms,
+					 int max_crtc_count,
+					 struct drm_plane **primary_planes,
+					 struct drm_plane **cursor_planes)
 {
-	struct drm_device *dev;
-	struct drm_plane *primary_planes[MAX_PLANES], *plane;
-	struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
-	struct drm_crtc *crtc;
-	struct drm_encoder *encoder;
-	unsigned int num_encoders;
+	const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
+	struct drm_device *dev = dpu_kms->dev;
+	int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
+	struct drm_plane *plane;
 
-	struct msm_drm_private *priv;
-	const struct dpu_mdss_cfg *catalog;
+	/* Create the planes, keeping track of one primary/cursor per crtc */
+	for (i = 0; i < catalog->sspp_count; i++) {
+		enum drm_plane_type type;
 
-	int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
-	int max_crtc_count;
-	dev = dpu_kms->dev;
-	priv = dev->dev_private;
-	catalog = dpu_kms->catalog;
+		if (primary_planes_idx < max_crtc_count)
+			type = DRM_PLANE_TYPE_PRIMARY;
+		else if (cursor_planes_idx < max_crtc_count)
+			type = DRM_PLANE_TYPE_CURSOR;
+		else
+			type = DRM_PLANE_TYPE_OVERLAY;
 
-	/*
-	 * Create encoder and query display drivers to create
-	 * bridges and connectors
-	 */
-	ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
-	if (ret)
-		return ret;
+		DPU_DEBUG("Create plane type %d\n", type);
 
-	num_encoders = 0;
-	drm_for_each_encoder(encoder, dev)
-		num_encoders++;
+		plane = dpu_plane_init_virtual(dev, type, (1UL << max_crtc_count) - 1);
+		if (IS_ERR(plane)) {
+			DPU_ERROR("dpu_plane_init failed\n");
+			ret = PTR_ERR(plane);
+			return ret;
+		}
 
-	max_crtc_count = min(catalog->mixer_count, num_encoders);
+		if (type == DRM_PLANE_TYPE_CURSOR)
+			cursor_planes[cursor_planes_idx++] = plane;
+		else if (type == DRM_PLANE_TYPE_PRIMARY)
+			primary_planes[primary_planes_idx++] = plane;
+	}
+
+	return primary_planes_idx;
+}
+
+static int dpu_kms_create_planes(struct dpu_kms *dpu_kms,
+				 int max_crtc_count,
+				 struct drm_plane **primary_planes,
+				 struct drm_plane **cursor_planes)
+{
+	const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
+	struct drm_device *dev = dpu_kms->dev;
+	int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
+	struct drm_plane *plane;
 
 	/* Create the planes, keeping track of one primary/cursor per crtc */
 	for (i = 0; i < catalog->sspp_count; i++) {
@@ -784,8 +803,8 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
 			  type, catalog->sspp[i].features,
 			  catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR));
 
-		plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
-				       (1UL << max_crtc_count) - 1);
+		plane = dpu_plane_init_sspp(dev, catalog->sspp[i].id, type,
+					    (1UL << max_crtc_count) - 1);
 		if (IS_ERR(plane)) {
 			DPU_ERROR("dpu_plane_init failed\n");
 			ret = PTR_ERR(plane);
@@ -798,7 +817,50 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
 			primary_planes[primary_planes_idx++] = plane;
 	}
 
-	max_crtc_count = min(max_crtc_count, primary_planes_idx);
+	return primary_planes_idx;
+}
+
+#define MAX_PLANES 20
+static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
+{
+	struct drm_device *dev;
+	struct drm_plane *primary_planes[MAX_PLANES];
+	struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
+	struct drm_crtc *crtc;
+	struct drm_encoder *encoder;
+	unsigned int num_encoders;
+
+	struct msm_drm_private *priv;
+	const struct dpu_mdss_cfg *catalog;
+	int i, ret;
+	int max_crtc_count;
+
+	dev = dpu_kms->dev;
+	priv = dev->dev_private;
+	catalog = dpu_kms->catalog;
+
+	/*
+	 * Create encoder and query display drivers to create
+	 * bridges and connectors
+	 */
+	ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
+	if (ret)
+		return ret;
+
+	num_encoders = 0;
+	drm_for_each_encoder(encoder, dev)
+		num_encoders++;
+
+	max_crtc_count = min(catalog->mixer_count, num_encoders);
+
+	if (dpu_use_virtual_planes)
+		ret = dpu_kms_create_virtual_planes(dpu_kms, max_crtc_count, primary_planes, cursor_planes);
+	else
+		ret = dpu_kms_create_planes(dpu_kms, max_crtc_count, primary_planes, cursor_planes);
+	if (ret < 0)
+		return ret;
+
+	max_crtc_count = min(max_crtc_count, ret);
 
 	/* Create one CRTC per encoder */
 	for (i = 0; i < max_crtc_count; i++) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 934874eb2248..9f6478f0ced6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -65,6 +65,8 @@
 
 #define DPU_NAME_SIZE  12
 
+extern bool dpu_use_virtual_planes;
+
 struct dpu_kms {
 	struct msm_kms base;
 	struct drm_device *dev;
@@ -134,6 +136,8 @@ struct dpu_global_state {
 	uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
 	uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
 	uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
+
+	uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE];
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index cf17075676d5..ee906c276aa5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -837,8 +837,77 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
 	return 0;
 }
 
-static int dpu_plane_atomic_check(struct drm_plane *plane,
-				  struct drm_atomic_state *state)
+static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
+					  struct drm_atomic_state *state)
+{
+	struct drm_plane_state *plane_state =
+		drm_atomic_get_plane_state(state, plane);
+	struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
+	const struct dpu_format *format;
+	struct drm_crtc_state *crtc_state;
+
+	/*
+	 * Main part of checks, including drm_atomic_helper_check_plane_state()
+	 * is called from dpu_crtc_atomic_check(). Do minimal processing here.
+	 */
+
+	if (!plane_state->fb) {
+		plane_state->visible = false;
+
+		/* resources are freed by dpu_crtc_atomic_check(), but clean them here */
+		pstate->pipe.sspp = NULL;
+		pstate->r_pipe.sspp = NULL;
+
+		return 0;
+	}
+
+	format = to_dpu_format(msm_framebuffer_format(plane_state->fb));
+	crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
+
+	/* force resource reallocation if the format of FB has changed */
+	if (pstate->saved_fmt != format) {
+		crtc_state->planes_changed = true;
+		pstate->saved_fmt = format;
+	}
+
+	return 0;
+}
+
+int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
+				       struct drm_crtc *crtc,
+				       struct dpu_global_state *global_state,
+				       struct drm_atomic_state *state)
+{
+	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+	struct dpu_plane_state *pstate;
+	struct drm_plane_state *plane_state;
+	struct dpu_hw_sspp *hw_sspp;
+	bool yuv, scale, rot90;
+
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state))
+		return PTR_ERR(plane_state);
+
+	yuv = plane_state->fb ?
+		DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(plane_state->fb))) :
+		false;
+	scale = (plane_state->src_w >> 16 != plane_state->crtc_w) ||
+		(plane_state->src_h >> 16 != plane_state->crtc_h);
+
+	rot90 = drm_rotation_90_or_270(plane_state->rotation);
+
+	hw_sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, yuv, scale, rot90);
+	if (!hw_sspp)
+		return -ENODEV;
+
+	pstate = to_dpu_plane_state(plane_state);
+	pstate->pipe.sspp = hw_sspp;
+
+	return 0;
+}
+
+int dpu_plane_atomic_check(struct drm_plane *plane,
+			   struct drm_atomic_state *state)
 {
 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
 										 plane);
@@ -863,8 +932,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
 		crtc_state = drm_atomic_get_new_crtc_state(state,
 							   new_plane_state->crtc);
 
-	pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
-	r_pipe->sspp = NULL;
+	if (pdpu->pipe != SSPP_NONE) {
+		pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
+		r_pipe->sspp = NULL;
+	}
 
 	pipe_hw_caps = pstate->pipe.sspp->cap;
 	sblk = pstate->pipe.sspp->cap->sblk;
@@ -1358,12 +1429,14 @@ static void dpu_plane_atomic_print_state(struct drm_printer *p,
 
 	drm_printf(p, "\tstage=%d\n", pstate->stage);
 
-	drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
-	drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode));
-	drm_printf(p, "\tmultirect_index[0]=%s\n",
-		   dpu_get_multirect_index(pipe->multirect_index));
-	drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect));
-	drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect));
+	if (pipe->sspp) {
+		drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
+		drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode));
+		drm_printf(p, "\tmultirect_index[0]=%s\n",
+			   dpu_get_multirect_index(pipe->multirect_index));
+		drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect));
+		drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect));
+	}
 
 	if (r_pipe->sspp) {
 		drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
@@ -1453,18 +1526,30 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = {
 		.atomic_update = dpu_plane_atomic_update,
 };
 
+/*
+ * For virtual planes atomic_check is called from dpu_crtc_atomic_check(),
+ * after CRTC code assigning SSPP.
+ */
+static const struct drm_plane_helper_funcs dpu_plane_virtual_helper_funcs = {
+	.prepare_fb = dpu_plane_prepare_fb,
+	.cleanup_fb = dpu_plane_cleanup_fb,
+	.atomic_check = dpu_plane_virtual_atomic_check,
+	.atomic_update = dpu_plane_atomic_update,
+};
+
 /* initialize plane */
-struct drm_plane *dpu_plane_init(struct drm_device *dev,
-		uint32_t pipe, enum drm_plane_type type,
-		unsigned long possible_crtcs)
+static struct drm_plane *dpu_plane_init(struct drm_device *dev,
+					enum drm_plane_type type,
+					unsigned long possible_crtcs,
+					bool inline_rotation,
+					const uint32_t *format_list,
+					uint32_t num_formats,
+					enum dpu_sspp pipe)
 {
 	struct drm_plane *plane = NULL;
-	const uint32_t *format_list;
 	struct dpu_plane *pdpu;
 	struct msm_drm_private *priv = dev->dev_private;
 	struct dpu_kms *kms = to_dpu_kms(priv->kms);
-	struct dpu_hw_sspp *pipe_hw;
-	uint32_t num_formats;
 	uint32_t supported_rotations;
 	int ret = -EINVAL;
 
@@ -1480,16 +1565,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 	plane = &pdpu->base;
 	pdpu->pipe = pipe;
 
-	/* initialize underlying h/w driver */
-	pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
-	if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
-		DPU_ERROR("[%u]SSPP is invalid\n", pipe);
-		goto clean_plane;
-	}
-
-	format_list = pipe_hw->cap->sblk->format_list;
-	num_formats = pipe_hw->cap->sblk->num_formats;
-
 	ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
 				format_list, num_formats,
 				supported_format_modifiers, type, NULL);
@@ -1510,7 +1585,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 
 	supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
 
-	if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION))
+	if (inline_rotation)
 		supported_rotations |= DRM_MODE_ROTATE_MASK;
 
 	drm_plane_create_rotation_property(plane,
@@ -1519,8 +1594,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 	drm_plane_enable_fb_damage_clips(plane);
 
 	/* success! finalize initialization */
-	drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
-
 	mutex_init(&pdpu->lock);
 
 	DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
@@ -1531,3 +1604,59 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
 	kfree(pdpu);
 	return ERR_PTR(ret);
 }
+
+struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
+				      uint32_t pipe, enum drm_plane_type type,
+				      unsigned long possible_crtcs)
+{
+	struct drm_plane *plane = NULL;
+	struct msm_drm_private *priv = dev->dev_private;
+	struct dpu_kms *kms = to_dpu_kms(priv->kms);
+	struct dpu_hw_sspp *pipe_hw;
+
+	/* initialize underlying h/w driver */
+	pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
+	if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
+		DPU_ERROR("[%u]SSPP is invalid\n", pipe);
+		return ERR_PTR(-EINVAL);
+	}
+
+
+	plane = dpu_plane_init(dev, type, possible_crtcs,
+			       pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION),
+			       pipe_hw->cap->sblk->format_list,
+			       pipe_hw->cap->sblk->num_formats,
+			       pipe);
+	if (IS_ERR(plane))
+		return plane;
+
+	drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
+
+	DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
+					pipe, plane->base.id);
+
+	return plane;
+}
+
+struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
+					 enum drm_plane_type type,
+					 unsigned long possible_crtcs)
+{
+	struct drm_plane *plane = NULL;
+	struct msm_drm_private *priv = dev->dev_private;
+	struct dpu_kms *kms = to_dpu_kms(priv->kms);
+
+	plane = dpu_plane_init(dev, type, possible_crtcs,
+			       kms->catalog->caps->has_inline_rot,
+			       kms->catalog->caps->format_list,
+			       kms->catalog->caps->num_formats,
+			       SSPP_NONE);
+	if (IS_ERR(plane))
+		return plane;
+
+	drm_plane_helper_add(plane, &dpu_plane_virtual_helper_funcs);
+
+	DPU_DEBUG("%s created virtual id:%u\n", plane->name, plane->base.id);
+
+	return plane;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index abd6b21a049b..cb1e31ef0d3f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -31,6 +31,7 @@
  * @plane_clk: calculated clk per plane
  * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
  * @rotation: simplified drm rotation hint
+ * @saved_fmt: format used by the plane's FB, saved for for virtual plane support
  */
 struct dpu_plane_state {
 	struct drm_plane_state base;
@@ -48,6 +49,8 @@ struct dpu_plane_state {
 
 	bool needs_dirtyfb;
 	unsigned int rotation;
+
+	const struct dpu_format *saved_fmt;
 };
 
 #define to_dpu_plane_state(x) \
@@ -66,17 +69,27 @@ void dpu_plane_flush(struct drm_plane *plane);
 void dpu_plane_set_error(struct drm_plane *plane, bool error);
 
 /**
- * dpu_plane_init - create new dpu plane for the given pipe
+ * dpu_plane_init_sspp - create new dpu plane for the given pipe
  * @dev:   Pointer to DRM device
  * @pipe:  dpu hardware pipe identifier
  * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
  * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
  *
  */
-struct drm_plane *dpu_plane_init(struct drm_device *dev,
+struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
 		uint32_t pipe, enum drm_plane_type type,
 		unsigned long possible_crtcs);
 
+/**
+ * dpu_plane_init_virtual - create new dpu virtualized plane
+ * @dev:   Pointer to DRM device
+ * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
+ * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
+ */
+struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
+					 enum drm_plane_type type,
+					 unsigned long possible_crtcs);
+
 /**
  * dpu_plane_color_fill - enables color fill on plane
  * @plane:  Pointer to DRM plane object
@@ -93,4 +106,11 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable);
 static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {}
 #endif
 
+int dpu_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state);
+
+int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
+				       struct drm_crtc *crtc,
+				       struct dpu_global_state *global_state,
+				       struct drm_atomic_state *state);
+
 #endif /* _DPU_PLANE_H_ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f0a94008d17a..6130ac87d7e3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -607,6 +607,71 @@ int dpu_rm_reserve(
 	return ret;
 }
 
+struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
+					struct dpu_global_state *global_state,
+					struct drm_crtc *crtc,
+					bool yuv, bool scale, bool rot90)
+{
+	uint32_t crtc_id = crtc->base.id;
+	struct dpu_hw_sspp *hw_sspp;
+	bool retry = false;
+	int i;
+
+retry_loop:
+	for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) {
+		if (!rm->hw_sspp[i])
+			continue;
+
+		if (global_state->sspp_to_crtc_id[i])
+			continue;
+
+		hw_sspp = rm->hw_sspp[i];
+
+		/* skip incompatible planes */
+		if (scale && !(hw_sspp->cap->features & DPU_SSPP_SCALER))
+			continue;
+
+		if (yuv && !(hw_sspp->cap->features & DPU_SSPP_CSC_ANY))
+			continue;
+
+		if (rot90 && !(hw_sspp->cap->features & DPU_SSPP_INLINE_ROTATION))
+			continue;
+
+		/*
+		 * For non-yuv, non-scaled planes try to find simple (DMA)
+		 * plane, fallback to VIG on a second try.
+		 *
+		 * This way we'd leave VIG sspps to be later used for YUV formats.
+		 */
+
+		if (!scale && !yuv && !rot90 && !retry &&
+		    (hw_sspp->cap->features &
+		     (DPU_SSPP_SCALER | DPU_SSPP_CSC_ANY | DPU_SSPP_INLINE_ROTATION)))
+			continue;
+
+		global_state->sspp_to_crtc_id[hw_sspp->idx - SSPP_NONE] = crtc_id;
+
+		return hw_sspp;
+	}
+
+	/* If we were looking for DMA plane, retry looking for VIG plane */
+	if (!scale && !yuv && !retry) {
+		retry = true;
+		goto retry_loop;
+	}
+
+	return NULL;
+}
+
+void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
+			     struct drm_crtc *crtc)
+{
+	uint32_t crtc_id = crtc->base.id;
+
+	_dpu_rm_clear_mapping(global_state->sspp_to_crtc_id,
+		ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id);
+}
+
 int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 	struct dpu_global_state *global_state, struct drm_crtc *crtc,
 	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index f402bec8322b..5bf6740ecb45 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -82,6 +82,30 @@ int dpu_rm_reserve(
 void dpu_rm_release(struct dpu_global_state *global_state,
 		struct drm_crtc *crtc);
 
+/**
+ * dpu_rm_reserve_sspp - Reserve the required SSPP for the provided CRTC
+ * @rm: DPU Resource Manager handle
+ * @global_state: private global state
+ * @crtc: DRM CRTC handle
+ * @yuv: required SSPP supporting YUV formats
+ * @scale: required SSPP supporting scaling
+ * @rot90: required SSPP supporting inline 90 degree rotation
+ */
+struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
+					struct dpu_global_state *global_state,
+					struct drm_crtc *crtc,
+					bool yuv, bool scale, bool rot90);
+
+/**
+ * dpu_rm_release_all_sspp - Given the CRTC, release all SSPP
+ *	blocks previously reserved for that use case.
+ * @rm: DPU Resource Manager handle
+ * @crtc: DRM CRTC handle
+ * @Return: 0 on Success otherwise -ERROR
+ */
+void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
+			     struct drm_crtc *crtc);
+
 /**
  * Get hw resources of the given type that are assigned to this encoder.
  */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [RFC PATCH v2 13/13] drm/msm/dpu: allow using two SSPP blocks for a single plane
  2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
                   ` (11 preceding siblings ...)
  2023-03-21  1:18 ` [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes Dmitry Baryshkov
@ 2023-03-21  1:18 ` Dmitry Baryshkov
  12 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-03-21  1:18 UTC (permalink / raw)
  To: Rob Clark, Sean Paul, Abhinav Kumar
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

Virtual wide planes give high amount of flexibility, but it is not
always enough:

In parallel multirect case only the half of the usual width is supported
for tiled formats. Thus the whole width of two tiled multirect
rectangles can not be greater than max_linewidth, which is not enough
for some platforms/compositors.

Another example is as simple as wide YUV plane. YUV planes can not use
multirect, so currently they are limited to max_linewidth too.

Now that the planes are fully virtualized, add support for allocating
two SSPP blocks to drive a single DRM plane. This fixes both mentioned
cases and allows all planes to go up to 2*max_linewidth (at the cost of
making some of the planes unavailable to the user).

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 247 +++++++++++++++++++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  13 +-
 3 files changed, 235 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index cdece21b81c9..7422bee8d21f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1354,7 +1354,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
 			 * is a shortcut. Perform actual check here, after
 			 * allocating SSPPs.
 			 */
-			rc = dpu_plane_atomic_check(plane, crtc_state->state);
+			rc = dpu_plane_virtual_atomic_check_late(plane, crtc_state->state);
 			if (rc)
 				return rc;
 		}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index ee906c276aa5..56cb03f1d393 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -840,20 +840,32 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
 static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
 					  struct drm_atomic_state *state)
 {
+	struct dpu_plane *pdpu = to_dpu_plane(plane);
 	struct drm_plane_state *plane_state =
 		drm_atomic_get_plane_state(state, plane);
 	struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
 	const struct dpu_format *format;
-	struct drm_crtc_state *crtc_state;
+	struct drm_crtc_state *crtc_state = NULL;
+	int ret;
+
+	if (plane_state->crtc)
+		crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
 
 	/*
-	 * Main part of checks, including drm_atomic_helper_check_plane_state()
-	 * is called from dpu_crtc_atomic_check(). Do minimal processing here.
+	 * Main part of checks is performed in
+	 * dpu_plane_virtual_atomic_check_late(), called from
+	 * dpu_crtc_atomic_check(). Do minimal processing here.
 	 */
+	ret = drm_atomic_helper_check_plane_noscale(plane_state, crtc_state,
+						    true, true);
+	if (ret) {
+		DPU_DEBUG_PLANE(to_dpu_plane(plane),
+				"Check plane state failed (%d)\n", ret);
+		return ret;
+	}
 
-	if (!plane_state->fb) {
-		plane_state->visible = false;
 
+	if (!plane_state->visible) {
 		/* resources are freed by dpu_crtc_atomic_check(), but clean them here */
 		pstate->pipe.sspp = NULL;
 		pstate->r_pipe.sspp = NULL;
@@ -861,18 +873,46 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
 		return 0;
 	}
 
+	pstate->stage = DPU_STAGE_0 + pstate->base.normalized_zpos;
+	if (pstate->stage >= pdpu->catalog->caps->max_mixer_blendstages) {
+		DPU_ERROR("> %d plane stages assigned\n",
+			  pdpu->catalog->caps->max_mixer_blendstages - DPU_STAGE_0);
+		return -EINVAL;
+	}
+
+	/* Ensure fb size is supported */
+	if (plane_state->fb->width > MAX_IMG_WIDTH ||
+	    plane_state->fb->height > MAX_IMG_HEIGHT) {
+		DPU_DEBUG_PLANE(pdpu, "invalid framebuffer %dx%d\n",
+				plane_state->fb->width,
+				plane_state->fb->height);
+		return -E2BIG;
+	}
+
 	format = to_dpu_format(msm_framebuffer_format(plane_state->fb));
-	crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
 
-	/* force resource reallocation if the format of FB has changed */
-	if (pstate->saved_fmt != format) {
+	/* force resource reallocation if the format of FB or src/dst have changed */
+	if (pstate->saved_fmt != format ||
+	    pstate->saved_src_w != plane_state->src_w ||
+	    pstate->saved_src_h != plane_state->src_h ||
+	    pstate->saved_src_w != plane_state->src_w ||
+	    pstate->saved_crtc_h != plane_state->crtc_h) {
 		crtc_state->planes_changed = true;
 		pstate->saved_fmt = format;
+		pstate->saved_src_w = plane_state->src_w;
+		pstate->saved_src_h = plane_state->src_h;
+		pstate->saved_crtc_w = plane_state->crtc_w;
+		pstate->saved_crtc_h = plane_state->crtc_h;
 	}
 
 	return 0;
 }
 
+/*
+ * Allocate backing SSPP blocks for the plane. This does not perform any
+ * additional checks on the plane, this is done in
+ * dpu_plane_virtual_atomic_check_late().
+ */
 int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
 				       struct drm_crtc *crtc,
 				       struct dpu_global_state *global_state,
@@ -881,18 +921,44 @@ int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
 	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
 	struct dpu_plane_state *pstate;
 	struct drm_plane_state *plane_state;
+	struct dpu_sw_pipe *pipe;
+	struct dpu_sw_pipe *r_pipe;
+	struct dpu_sw_pipe_cfg *pipe_cfg;
+	struct dpu_sw_pipe_cfg *r_pipe_cfg;
 	struct dpu_hw_sspp *hw_sspp;
-	bool yuv, scale, rot90;
+	const struct dpu_format *fmt;
+	bool yuv, scale, rot90, tiled;
+	uint32_t max_linewidth;
 
 	plane_state = drm_atomic_get_plane_state(state, plane);
 	if (IS_ERR(plane_state))
 		return PTR_ERR(plane_state);
 
-	yuv = plane_state->fb ?
-		DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(plane_state->fb))) :
-		false;
-	scale = (plane_state->src_w >> 16 != plane_state->crtc_w) ||
-		(plane_state->src_h >> 16 != plane_state->crtc_h);
+	pstate = to_dpu_plane_state(plane_state);
+
+	pipe = &pstate->pipe;
+	r_pipe = &pstate->r_pipe;
+	pipe_cfg = &pstate->pipe_cfg;
+	r_pipe_cfg = &pstate->r_pipe_cfg;
+
+	fmt = to_dpu_format(msm_framebuffer_format(plane_state->fb));
+	yuv = DPU_FORMAT_IS_YUV(fmt);
+	tiled = DPU_FORMAT_IS_UBWC(fmt);
+
+	/* state->src is 16.16, src_rect is not */
+	drm_rect_fp_to_int(&pipe_cfg->src_rect, &plane_state->src);
+	pipe_cfg->dst_rect = plane_state->dst;
+
+	scale = (drm_rect_width(&pipe_cfg->src_rect) != drm_rect_width(&pipe_cfg->dst_rect)) ||
+		(drm_rect_height(&pipe_cfg->src_rect) != drm_rect_height(&pipe_cfg->dst_rect));
+
+	max_linewidth = dpu_kms->catalog->caps->max_linewidth;
+
+	pipe->multirect_index = DPU_SSPP_RECT_SOLO;
+	pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
+	r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
+	r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
+	r_pipe->sspp = NULL;
 
 	rot90 = drm_rotation_90_or_270(plane_state->rotation);
 
@@ -900,21 +966,159 @@ int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
 	if (!hw_sspp)
 		return -ENODEV;
 
-	pstate = to_dpu_plane_state(plane_state);
-	pstate->pipe.sspp = hw_sspp;
+	pipe->sspp = hw_sspp;
+
+	if (drm_rect_width(&pipe_cfg->src_rect) <= max_linewidth)
+		return 0;
+
+	drm_rect_rotate(&pipe_cfg->src_rect,
+			plane_state->fb->width, plane_state->fb->height,
+			plane_state->rotation);
+
+	*r_pipe_cfg = *pipe_cfg;
+
+	pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1;
+	pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1;
+
+	if (yuv && pipe_cfg->src_rect.x2 & 0x1) {
+		pipe_cfg->src_rect.x2 -= 1;
+		pipe_cfg->dst_rect.x2 -= 1;
+	}
+
+	r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2;
+	r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
+
+	if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth ||
+	    drm_rect_width(&r_pipe_cfg->src_rect) > max_linewidth) {
+		DPU_DEBUG_PLANE(to_dpu_plane(plane),
+				"invalid src " DRM_RECT_FMT " / " DRM_RECT_FMT " line:%u\n",
+				DRM_RECT_ARG(&pipe_cfg->src_rect),
+				DRM_RECT_ARG(&r_pipe_cfg->src_rect),
+				max_linewidth);
+		return -E2BIG;
+	}
+
+	drm_rect_rotate_inv(&pipe_cfg->src_rect,
+			    plane_state->fb->width, plane_state->fb->height,
+			    plane_state->rotation);
+	drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
+			    plane_state->fb->width, plane_state->fb->height,
+			    plane_state->rotation);
+
+	/*
+	 * Check if we can use parallel multirect for the wide plane.
+	 *
+	 * For tiled formats there is no point in trying multirect.
+	 * In parallel multirect case only the half of the usual width
+	 * is supported for tiled formats. If we are here, we know that
+	 * full width is more than max_linewidth, thus each rect is
+	 * wider than allowed.
+	 */
+	if (!yuv && !scale && !tiled &&
+	    test_bit(DPU_SSPP_SMART_DMA_V2, &pipe->sspp->cap->features)) {
+		pipe->multirect_index = DPU_SSPP_RECT_0;
+		pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
+
+		r_pipe->sspp = pipe->sspp;
+		r_pipe->multirect_index = DPU_SSPP_RECT_1;
+		r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_PARALLEL;
+	} else {
+		/* multirect is not possible, use two SSPP blocks */
+		hw_sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, yuv, scale, rot90);
+		if (!hw_sspp)
+			return -ENODEV;
+
+		r_pipe->sspp = hw_sspp;
+	}
 
 	return 0;
 }
 
-int dpu_plane_atomic_check(struct drm_plane *plane,
-			   struct drm_atomic_state *state)
+int dpu_plane_virtual_atomic_check_late(struct drm_plane *plane,
+					struct drm_atomic_state *state)
+{
+	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+	int ret = 0, min_scale, max_scale, hscale, vscale;
+	struct dpu_plane *pdpu = to_dpu_plane(plane);
+	struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
+	struct dpu_sw_pipe *pipe = &pstate->pipe;
+	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
+	const struct drm_crtc_state *crtc_state = NULL;
+	const struct dpu_format *fmt;
+	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
+	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
+	unsigned int rotation;
+	uint32_t supported_rotations;
+	struct drm_rect src;
+	const struct dpu_sspp_cfg *pipe_hw_caps;
+	const struct dpu_sspp_sub_blks *sblk;
+
+	if (plane_state->crtc)
+		crtc_state = drm_atomic_get_new_crtc_state(state,
+							   plane_state->crtc);
+
+	if (!plane_state->visible)
+		return 0;
+
+	pipe_hw_caps = pstate->pipe.sspp->cap;
+	sblk = pstate->pipe.sspp->cap->sblk;
+
+	src = drm_plane_state_src(plane_state);
+	drm_rect_rotate(&src, plane_state->fb->width << 16, plane_state->fb->height << 16,
+			plane_state->rotation);
+
+	min_scale = FRAC_16_16(1, sblk->maxupscale);
+	max_scale = sblk->maxdwnscale << 16;
+	hscale = drm_rect_calc_hscale(&plane_state->src, &plane_state->dst, min_scale, max_scale);
+	vscale = drm_rect_calc_vscale(&plane_state->src, &plane_state->dst, min_scale, max_scale);
+	if (hscale < 0 || vscale < 0) {
+		drm_dbg_kms(plane->dev, "Invalid scaling of plane\n");
+		drm_rect_debug_print("src: ", &plane_state->src, true);
+		drm_rect_debug_print("dst: ", &plane_state->dst, false);
+		return -ERANGE;
+	}
+
+	fmt = to_dpu_format(msm_framebuffer_format(plane_state->fb));
+
+	ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
+	if (ret)
+		return ret;
+
+	if (r_pipe->sspp) {
+		ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt);
+		if (ret)
+			return ret;
+	}
+
+	supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0;
+
+	if (pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION))
+		supported_rotations |= DRM_MODE_ROTATE_90;
+
+	rotation = drm_rotation_simplify(plane_state->rotation,
+					supported_rotations);
+
+	if ((pipe_hw_caps->features & BIT(DPU_SSPP_INLINE_ROTATION)) &&
+		(rotation & DRM_MODE_ROTATE_90)) {
+		ret = dpu_plane_check_inline_rotation(pdpu, sblk, pipe_cfg->src_rect, fmt);
+		if (ret)
+			return ret;
+	}
+
+	pstate->rotation = rotation;
+	pstate->needs_qos_remap = drm_atomic_crtc_needs_modeset(crtc_state);
+
+	return 0;
+}
+
+static int dpu_plane_atomic_check(struct drm_plane *plane,
+				  struct drm_atomic_state *state)
 {
 	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
 										 plane);
 	int ret = 0, min_scale;
 	struct dpu_plane *pdpu = to_dpu_plane(plane);
 	struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
-	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
 	struct dpu_sw_pipe *pipe = &pstate->pipe;
 	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
 	const struct drm_crtc_state *crtc_state = NULL;
@@ -932,11 +1136,6 @@ int dpu_plane_atomic_check(struct drm_plane *plane,
 		crtc_state = drm_atomic_get_new_crtc_state(state,
 							   new_plane_state->crtc);
 
-	if (pdpu->pipe != SSPP_NONE) {
-		pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
-		r_pipe->sspp = NULL;
-	}
-
 	pipe_hw_caps = pstate->pipe.sspp->cap;
 	sblk = pstate->pipe.sspp->cap->sblk;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index cb1e31ef0d3f..07e0796cc100 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -32,6 +32,10 @@
  * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
  * @rotation: simplified drm rotation hint
  * @saved_fmt: format used by the plane's FB, saved for for virtual plane support
+ * @saved_src_w: cached value of plane's src_w, saved for for virtual plane support
+ * @saved_src_h: cached value of plane's src_h, saved for for virtual plane support
+ * @saved_crtc_w: cached value of plane's crtc_w, saved for for virtual plane support
+ * @saved_crtc_h: cached value of plane's crtc_h, saved for for virtual plane support
  */
 struct dpu_plane_state {
 	struct drm_plane_state base;
@@ -51,6 +55,10 @@ struct dpu_plane_state {
 	unsigned int rotation;
 
 	const struct dpu_format *saved_fmt;
+	uint32_t saved_src_w;
+	uint32_t saved_src_h;
+	uint32_t saved_crtc_w;
+	uint32_t saved_crtc_h;
 };
 
 #define to_dpu_plane_state(x) \
@@ -106,11 +114,12 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable);
 static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {}
 #endif
 
-int dpu_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state);
-
 int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
 				       struct drm_crtc *crtc,
 				       struct dpu_global_state *global_state,
 				       struct drm_atomic_state *state);
 
+int dpu_plane_virtual_atomic_check_late(struct drm_plane *plane,
+					struct drm_atomic_state *state);
+
 #endif /* _DPU_PLANE_H_ */
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes
  2023-03-21  1:18 ` [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes Dmitry Baryshkov
@ 2023-05-12 22:12   ` Abhinav Kumar
  2023-05-14 17:01     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-12 22:12 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> Take into account the plane rotation and flipping when calculating src
> positions for the wide plane parts.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

Do we need to have a fixes tag for this? This means we dont consider 
rotation while calculating src position today which is a bug?

> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++++++++++++++---------
>   1 file changed, 17 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> index 2e63eb0a2f3f..d43e04fc4578 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> @@ -887,16 +887,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>   		return -EINVAL;
>   	}
>   
> -	pipe_cfg->src_rect = new_plane_state->src;
> -
> -	/* state->src is 16.16, src_rect is not */
> -	pipe_cfg->src_rect.x1 >>= 16;
> -	pipe_cfg->src_rect.x2 >>= 16;
> -	pipe_cfg->src_rect.y1 >>= 16;
> -	pipe_cfg->src_rect.y2 >>= 16;
> -
> -	pipe_cfg->dst_rect = new_plane_state->dst;
> -
>   	fb_rect.x2 = new_plane_state->fb->width;
>   	fb_rect.y2 = new_plane_state->fb->height;
>   
> @@ -912,6 +902,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>   
>   	max_linewidth = pdpu->catalog->caps->max_linewidth;
>   
> +	/* state->src is 16.16, src_rect is not */
> +	drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
> +
> +	pipe_cfg->dst_rect = new_plane_state->dst;
> +
> +	drm_rect_rotate(&pipe_cfg->src_rect,
> +			new_plane_state->fb->width, new_plane_state->fb->height,
> +			new_plane_state->rotation);
> +
>   	if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
>   		/*
>   		 * In parallel multirect case only the half of the usual width
> @@ -959,6 +958,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>   		r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
>   	}
>   
> +	drm_rect_rotate_inv(&pipe_cfg->src_rect,
> +			    new_plane_state->fb->width, new_plane_state->fb->height,
> +			    new_plane_state->rotation);
> +	if (r_pipe->sspp)

Dont you need to check for if (r_pipe_cfg) here and not if 
(r_pipe->sspp) because parameter you are passing is the r_pipe_cfg to 
drm_rect_rotate_inv().

So we rotated the pipe_cfg once, then rotated_inv it to restore the 
rectangle to its original state, but r_pipe_cfg's rectangle was never 
rotated as it was not allocated before this function so it will remain 
in inverse rotated state now right?


> +		drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
> +				    new_plane_state->fb->width, new_plane_state->fb->height,
> +				    new_plane_state->rotation);
> +
>   	ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
>   	if (ret)
>   		return ret;

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling
  2023-03-21  1:18 ` [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling Dmitry Baryshkov
@ 2023-05-12 22:18   ` Abhinav Kumar
  2023-05-14 17:02     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-12 22:18 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> As the debugfs is fully cleared on drm device removal, drop the
> encoder-specific cleanup function, remove debugfs_root from dpu_encoder
> struct and also remove phys_encoder late_register() ops which has been
> unused since the driver being added.
> 

Agreed, late_register of encoder_phys is unused, so we can drop that.

For the other two things which this patch does:

1) remove debugfs_root from dpu_encoder
2) remove early_unregister of dpu_encoder

I think this has been posted separately here 
https://patchwork.freedesktop.org/patch/534802/?series=117150&rev=1 for 
which I had given my feedback about why it cant be removed

So these 2 parts have to be kept till we sort out that feedback

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 22 +++----------------
>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  3 ---
>   2 files changed, 3 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 97d8d777f178..28729c77364f 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -142,7 +142,6 @@ enum dpu_enc_rc_states {
>    * @crtc_kickoff_cb:		Callback into CRTC that will flush & start
>    *				all CTL paths
>    * @crtc_kickoff_cb_data:	Opaque user data given to crtc_kickoff_cb
> - * @debugfs_root:		Debug file system root file node
>    * @enc_lock:			Lock around physical encoder
>    *				create/destroy/enable/disable
>    * @frame_busy_mask:		Bitmask tracking which phys_enc we are still
> @@ -186,7 +185,6 @@ struct dpu_encoder_virt {
>   	struct drm_crtc *crtc;
>   	struct drm_connector *connector;
>   
> -	struct dentry *debugfs_root;
>   	struct mutex enc_lock;
>   	DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL);
>   	void (*crtc_frame_event_cb)(void *, u32 event);
> @@ -2134,7 +2132,7 @@ DEFINE_SHOW_ATTRIBUTE(_dpu_encoder_status);
>   static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
>   {
>   	struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> -	int i;
> +	struct dentry *debugfs_root;
>   
>   	char name[DPU_NAME_SIZE];
>   
> @@ -2146,18 +2144,12 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
>   	snprintf(name, DPU_NAME_SIZE, "encoder%u", drm_enc->base.id);
>   
>   	/* create overall sub-directory for the encoder */
> -	dpu_enc->debugfs_root = debugfs_create_dir(name,
> +	debugfs_root = debugfs_create_dir(name,
>   			drm_enc->dev->primary->debugfs_root);
>   
>   	/* don't error check these */
>   	debugfs_create_file("status", 0600,
> -		dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
> -
> -	for (i = 0; i < dpu_enc->num_phys_encs; i++)
> -		if (dpu_enc->phys_encs[i]->ops.late_register)
> -			dpu_enc->phys_encs[i]->ops.late_register(
> -					dpu_enc->phys_encs[i],
> -					dpu_enc->debugfs_root);
> +		debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
>   
>   	return 0;
>   }
> @@ -2173,13 +2165,6 @@ static int dpu_encoder_late_register(struct drm_encoder *encoder)
>   	return _dpu_encoder_init_debugfs(encoder);
>   }
>   
> -static void dpu_encoder_early_unregister(struct drm_encoder *encoder)
> -{
> -	struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder);
> -
> -	debugfs_remove_recursive(dpu_enc->debugfs_root);
> -}
> -
>   static int dpu_encoder_virt_add_phys_encs(
>   		struct msm_display_info *disp_info,
>   		struct dpu_encoder_virt *dpu_enc,
> @@ -2406,7 +2391,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
>   static const struct drm_encoder_funcs dpu_encoder_funcs = {
>   		.destroy = dpu_encoder_destroy,
>   		.late_register = dpu_encoder_late_register,
> -		.early_unregister = dpu_encoder_early_unregister,
>   };
>   
>   int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index 1d434b22180d..9e29079a6fc4 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -63,7 +63,6 @@ struct dpu_encoder_phys;
>   /**
>    * struct dpu_encoder_phys_ops - Interface the physical encoders provide to
>    *	the containing virtual encoder.
> - * @late_register:		DRM Call. Add Userspace interfaces, debugfs.
>    * @prepare_commit:		MSM Atomic Call, start of atomic commit sequence
>    * @is_master:			Whether this phys_enc is the current master
>    *				encoder. Can be switched at enable time. Based
> @@ -93,8 +92,6 @@ struct dpu_encoder_phys;
>    */
>   
>   struct dpu_encoder_phys_ops {
> -	int (*late_register)(struct dpu_encoder_phys *encoder,
> -			struct dentry *debugfs_root);
>   	void (*prepare_commit)(struct dpu_encoder_phys *encoder);
>   	bool (*is_master)(struct dpu_encoder_phys *encoder);
>   	void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements
  2023-03-21  1:18 ` [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements Dmitry Baryshkov
@ 2023-05-12 22:39   ` Abhinav Kumar
  2023-05-14 17:06     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-12 22:39 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> The struct dpu_rm_requirements was used to wrap display topology and
> hw resources, which meant INTF indices. As of commit ef58e0ad3436
> ("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
> resources struct was removed, leaving struct dpu_rm_requirements
> containing a single field (topology). Remove the useless wrapper.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---

Irrespective of where we plan to have the topology, this change doesn't 
seem incorrect as such.

The only thing I can think of is when we need more information to be 
passed to the RM to allocate the blocks in addition to the topology this 
struct could have been expanded.

So one example I can think of is lets say I want to add CDM block 
support. Then that information is outside of topology today because I 
will use CDM if my output format is yuv. It has nothing to do with 
topology but that block still needs to come from RM.

I know that usually I have lost on these type of discussions saying that 
if the code is not there yet, it should be dropped but I do have a plan 
to add that support soon probably by the next cycle. That time we will 
need some sort of wrapper to hold the topology and "extra" information 
to allocate the blocks.

One alternative ofcourse is to expand dpu_rm_reserve() to accept 
something like "needs_cdm" but this is not scalable.

Thoughts?

>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 69 +++++++--------------
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  2 +-
>   3 files changed, 23 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 4ee708264f3b..a2cb23dea0b8 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -638,7 +638,7 @@ static int dpu_encoder_virt_atomic_check(
>   
>   		if (!crtc_state->active_changed || crtc_state->enable)
>   			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> -					drm_enc, crtc_state, topology);
> +					drm_enc, crtc_state, &topology);
>   	}
>   
>   	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index f4dda88a73f7..952e139c0234 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -24,15 +24,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
>   	return res_map[idx] && res_map[idx] != enc_id;
>   }
>   
> -/**
> - * struct dpu_rm_requirements - Reservation requirements parameter bundle
> - * @topology:  selected topology for the display
> - * @hw_res:	   Hardware resources required as reported by the encoders
> - */
> -struct dpu_rm_requirements {
> -	struct msm_display_topology topology;
> -};
> -
>   int dpu_rm_destroy(struct dpu_rm *rm)
>   {
>   	int i;
> @@ -329,14 +320,13 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
>    *      mixer in rm->pingpong_blks[].
>    * @dspp_idx: output parameter, index of dspp block attached to the layer
>    *      mixer in rm->dspp_blks[].
> - * @reqs: input parameter, rm requirements for HW blocks needed in the
> - *      datapath.
> + * @topology:  selected topology for the display
>    * Return: true if lm matches all requirements, false otherwise
>    */
>   static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
>   		uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> -		struct dpu_rm_requirements *reqs)
> +		struct msm_display_topology *topology)
>   {
>   	const struct dpu_lm_cfg *lm_cfg;
>   	int idx;
> @@ -361,7 +351,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   	}
>   	*pp_idx = idx;
>   
> -	if (!reqs->topology.num_dspp)
> +	if (!topology->num_dspp)
>   		return true;
>   
>   	idx = lm_cfg->dspp - DSPP_0;
> @@ -383,7 +373,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   			       struct dpu_global_state *global_state,
>   			       uint32_t enc_id,
> -			       struct dpu_rm_requirements *reqs)
> +			       struct msm_display_topology *topology)
>   
>   {
>   	int lm_idx[MAX_BLOCKS];
> @@ -391,14 +381,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   	int dspp_idx[MAX_BLOCKS] = {0};
>   	int i, j, lm_count = 0;
>   
> -	if (!reqs->topology.num_lm) {
> -		DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
> +	if (!topology->num_lm) {
> +		DPU_ERROR("invalid number of lm: %d\n", topology->num_lm);
>   		return -EINVAL;
>   	}
>   
>   	/* Find a primary mixer */
>   	for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> -			lm_count < reqs->topology.num_lm; i++) {
> +			lm_count < topology->num_lm; i++) {
>   		if (!rm->mixer_blks[i])
>   			continue;
>   
> @@ -407,7 +397,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   
>   		if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
>   				enc_id, i, &pp_idx[lm_count],
> -				&dspp_idx[lm_count], reqs)) {
> +				&dspp_idx[lm_count], topology)) {
>   			continue;
>   		}
>   
> @@ -415,7 +405,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   
>   		/* Valid primary mixer found, find matching peers */
>   		for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
> -				lm_count < reqs->topology.num_lm; j++) {
> +				lm_count < topology->num_lm; j++) {
>   			if (!rm->mixer_blks[j])
>   				continue;
>   
> @@ -428,7 +418,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   			if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
>   					global_state, enc_id, j,
>   					&pp_idx[lm_count], &dspp_idx[lm_count],
> -					reqs)) {
> +					topology)) {
>   				continue;
>   			}
>   
> @@ -437,7 +427,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   		}
>   	}
>   
> -	if (lm_count != reqs->topology.num_lm) {
> +	if (lm_count != topology->num_lm) {
>   		DPU_DEBUG("unable to find appropriate mixers\n");
>   		return -ENAVAIL;
>   	}
> @@ -446,7 +436,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   		global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
>   		global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
>   		global_state->dspp_to_enc_id[dspp_idx[i]] =
> -			reqs->topology.num_dspp ? enc_id : 0;
> +			topology->num_dspp ? enc_id : 0;
>   
>   		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
>   					 pp_idx[i] + PINGPONG_0);
> @@ -539,44 +529,30 @@ static int _dpu_rm_make_reservation(
>   		struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
>   		struct drm_encoder *enc,
> -		struct dpu_rm_requirements *reqs)
> +		struct msm_display_topology *topology)
>   {
>   	int ret;
>   
> -	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
> +	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
>   	if (ret) {
>   		DPU_ERROR("unable to find appropriate mixers\n");
>   		return ret;
>   	}
>   
>   	ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> -				&reqs->topology);
> +				   topology);
>   	if (ret) {
>   		DPU_ERROR("unable to find appropriate CTL\n");
>   		return ret;
>   	}
>   
> -	ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
> +	ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
>   	if (ret)
>   		return ret;
>   
>   	return ret;
>   }
>   
> -static int _dpu_rm_populate_requirements(
> -		struct drm_encoder *enc,
> -		struct dpu_rm_requirements *reqs,
> -		struct msm_display_topology req_topology)
> -{
> -	reqs->topology = req_topology;
> -
> -	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> -		      reqs->topology.num_lm, reqs->topology.num_dsc,
> -		      reqs->topology.num_intf);
> -
> -	return 0;
> -}
> -
>   static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>   				  uint32_t enc_id)
>   {
> @@ -608,9 +584,8 @@ int dpu_rm_reserve(
>   		struct dpu_global_state *global_state,
>   		struct drm_encoder *enc,
>   		struct drm_crtc_state *crtc_state,
> -		struct msm_display_topology topology)
> +		struct msm_display_topology *topology)
>   {
> -	struct dpu_rm_requirements reqs;
>   	int ret;
>   
>   	/* Check if this is just a page-flip */
> @@ -625,13 +600,11 @@ int dpu_rm_reserve(
>   	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>   		      enc->base.id, crtc_state->crtc->base.id);
>   
> -	ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
> -	if (ret) {
> -		DPU_ERROR("failed to populate hw requirements\n");
> -		return ret;
> -	}
> +	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> +		      topology->num_lm, topology->num_dsc,
> +		      topology->num_intf);
>   
> -	ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
> +	ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
>   	if (ret)
>   		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index d62c2edb2460..f05697462856 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -71,7 +71,7 @@ int dpu_rm_reserve(struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
>   		struct drm_encoder *drm_enc,
>   		struct drm_crtc_state *crtc_state,
> -		struct msm_display_topology topology);
> +		struct msm_display_topology *topology);
>   
>   /**
>    * dpu_rm_reserve - Given the encoder for the display chain, release any

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes
  2023-05-12 22:12   ` Abhinav Kumar
@ 2023-05-14 17:01     ` Dmitry Baryshkov
  2023-05-15 18:45       ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-14 17:01 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On Sat, 13 May 2023 at 01:12, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> > Take into account the plane rotation and flipping when calculating src
> > positions for the wide plane parts.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> Do we need to have a fixes tag for this? This means we dont consider
> rotation while calculating src position today which is a bug?

Hmm, I thought that I had a check forbidding rotation with the current
approach, but I don't see it. Most probably I thought about it and
then forgot to add it.
The proper fix should be to disallow it for static SSPP case. I'll
include the patch into v3.

>
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++++++++++++++---------
> >   1 file changed, 17 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > index 2e63eb0a2f3f..d43e04fc4578 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> > @@ -887,16 +887,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
> >               return -EINVAL;
> >       }
> >
> > -     pipe_cfg->src_rect = new_plane_state->src;
> > -
> > -     /* state->src is 16.16, src_rect is not */
> > -     pipe_cfg->src_rect.x1 >>= 16;
> > -     pipe_cfg->src_rect.x2 >>= 16;
> > -     pipe_cfg->src_rect.y1 >>= 16;
> > -     pipe_cfg->src_rect.y2 >>= 16;
> > -
> > -     pipe_cfg->dst_rect = new_plane_state->dst;
> > -
> >       fb_rect.x2 = new_plane_state->fb->width;
> >       fb_rect.y2 = new_plane_state->fb->height;
> >
> > @@ -912,6 +902,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
> >
> >       max_linewidth = pdpu->catalog->caps->max_linewidth;
> >
> > +     /* state->src is 16.16, src_rect is not */
> > +     drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
> > +
> > +     pipe_cfg->dst_rect = new_plane_state->dst;
> > +
> > +     drm_rect_rotate(&pipe_cfg->src_rect,
> > +                     new_plane_state->fb->width, new_plane_state->fb->height,
> > +                     new_plane_state->rotation);
> > +
> >       if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
> >               /*
> >                * In parallel multirect case only the half of the usual width
> > @@ -959,6 +958,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
> >               r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
> >       }
> >
> > +     drm_rect_rotate_inv(&pipe_cfg->src_rect,
> > +                         new_plane_state->fb->width, new_plane_state->fb->height,
> > +                         new_plane_state->rotation);
> > +     if (r_pipe->sspp)
>
> Dont you need to check for if (r_pipe_cfg) here and not if
> (r_pipe->sspp) because parameter you are passing is the r_pipe_cfg to
> drm_rect_rotate_inv().

Of course not. r_pipe_cfg is a pointer to the field in pstate. We know
that it can not be NULL.

>
> So we rotated the pipe_cfg once, then rotated_inv it to restore the
> rectangle to its original state, but r_pipe_cfg's rectangle was never
> rotated as it was not allocated before this function so it will remain
> in inverse rotated state now right?

No. r_pipe_cfg is set beforehand to the half of the rotated pipe_cfg.

> > +             drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
> > +                                 new_plane_state->fb->width, new_plane_state->fb->height,
> > +                                 new_plane_state->rotation);
> > +
> >       ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
> >       if (ret)
> >               return ret;



--
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling
  2023-05-12 22:18   ` Abhinav Kumar
@ 2023-05-14 17:02     ` Dmitry Baryshkov
  0 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-14 17:02 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On Sat, 13 May 2023 at 01:18, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> > As the debugfs is fully cleared on drm device removal, drop the
> > encoder-specific cleanup function, remove debugfs_root from dpu_encoder
> > struct and also remove phys_encoder late_register() ops which has been
> > unused since the driver being added.
> >
>
> Agreed, late_register of encoder_phys is unused, so we can drop that.
>
> For the other two things which this patch does:
>
> 1) remove debugfs_root from dpu_encoder
> 2) remove early_unregister of dpu_encoder
>
> I think this has been posted separately here
> https://patchwork.freedesktop.org/patch/534802/?series=117150&rev=1 for
> which I had given my feedback about why it cant be removed

Sure. And this patch predates your feedback.

>
> So these 2 parts have to be kept till we sort out that feedback
>
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 22 +++----------------
> >   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  3 ---
> >   2 files changed, 3 insertions(+), 22 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 97d8d777f178..28729c77364f 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -142,7 +142,6 @@ enum dpu_enc_rc_states {
> >    * @crtc_kickoff_cb:                Callback into CRTC that will flush & start
> >    *                          all CTL paths
> >    * @crtc_kickoff_cb_data:   Opaque user data given to crtc_kickoff_cb
> > - * @debugfs_root:            Debug file system root file node
> >    * @enc_lock:                       Lock around physical encoder
> >    *                          create/destroy/enable/disable
> >    * @frame_busy_mask:                Bitmask tracking which phys_enc we are still
> > @@ -186,7 +185,6 @@ struct dpu_encoder_virt {
> >       struct drm_crtc *crtc;
> >       struct drm_connector *connector;
> >
> > -     struct dentry *debugfs_root;
> >       struct mutex enc_lock;
> >       DECLARE_BITMAP(frame_busy_mask, MAX_PHYS_ENCODERS_PER_VIRTUAL);
> >       void (*crtc_frame_event_cb)(void *, u32 event);
> > @@ -2134,7 +2132,7 @@ DEFINE_SHOW_ATTRIBUTE(_dpu_encoder_status);
> >   static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
> >   {
> >       struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> > -     int i;
> > +     struct dentry *debugfs_root;
> >
> >       char name[DPU_NAME_SIZE];
> >
> > @@ -2146,18 +2144,12 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
> >       snprintf(name, DPU_NAME_SIZE, "encoder%u", drm_enc->base.id);
> >
> >       /* create overall sub-directory for the encoder */
> > -     dpu_enc->debugfs_root = debugfs_create_dir(name,
> > +     debugfs_root = debugfs_create_dir(name,
> >                       drm_enc->dev->primary->debugfs_root);
> >
> >       /* don't error check these */
> >       debugfs_create_file("status", 0600,
> > -             dpu_enc->debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
> > -
> > -     for (i = 0; i < dpu_enc->num_phys_encs; i++)
> > -             if (dpu_enc->phys_encs[i]->ops.late_register)
> > -                     dpu_enc->phys_encs[i]->ops.late_register(
> > -                                     dpu_enc->phys_encs[i],
> > -                                     dpu_enc->debugfs_root);
> > +             debugfs_root, dpu_enc, &_dpu_encoder_status_fops);
> >
> >       return 0;
> >   }
> > @@ -2173,13 +2165,6 @@ static int dpu_encoder_late_register(struct drm_encoder *encoder)
> >       return _dpu_encoder_init_debugfs(encoder);
> >   }
> >
> > -static void dpu_encoder_early_unregister(struct drm_encoder *encoder)
> > -{
> > -     struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder);
> > -
> > -     debugfs_remove_recursive(dpu_enc->debugfs_root);
> > -}
> > -
> >   static int dpu_encoder_virt_add_phys_encs(
> >               struct msm_display_info *disp_info,
> >               struct dpu_encoder_virt *dpu_enc,
> > @@ -2406,7 +2391,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
> >   static const struct drm_encoder_funcs dpu_encoder_funcs = {
> >               .destroy = dpu_encoder_destroy,
> >               .late_register = dpu_encoder_late_register,
> > -             .early_unregister = dpu_encoder_early_unregister,
> >   };
> >
> >   int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > index 1d434b22180d..9e29079a6fc4 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> > @@ -63,7 +63,6 @@ struct dpu_encoder_phys;
> >   /**
> >    * struct dpu_encoder_phys_ops - Interface the physical encoders provide to
> >    *  the containing virtual encoder.
> > - * @late_register:           DRM Call. Add Userspace interfaces, debugfs.
> >    * @prepare_commit:         MSM Atomic Call, start of atomic commit sequence
> >    * @is_master:                      Whether this phys_enc is the current master
> >    *                          encoder. Can be switched at enable time. Based
> > @@ -93,8 +92,6 @@ struct dpu_encoder_phys;
> >    */
> >
> >   struct dpu_encoder_phys_ops {
> > -     int (*late_register)(struct dpu_encoder_phys *encoder,
> > -                     struct dentry *debugfs_root);
> >       void (*prepare_commit)(struct dpu_encoder_phys *encoder);
> >       bool (*is_master)(struct dpu_encoder_phys *encoder);
> >       void (*atomic_mode_set)(struct dpu_encoder_phys *encoder,



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements
  2023-05-12 22:39   ` Abhinav Kumar
@ 2023-05-14 17:06     ` Dmitry Baryshkov
  2023-05-17 23:53       ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-14 17:06 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On Sat, 13 May 2023 at 01:39, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> > The struct dpu_rm_requirements was used to wrap display topology and
> > hw resources, which meant INTF indices. As of commit ef58e0ad3436
> > ("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
> > resources struct was removed, leaving struct dpu_rm_requirements
> > containing a single field (topology). Remove the useless wrapper.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > ---
>
> Irrespective of where we plan to have the topology, this change doesn't
> seem incorrect as such.
>
> The only thing I can think of is when we need more information to be
> passed to the RM to allocate the blocks in addition to the topology this
> struct could have been expanded.
>
> So one example I can think of is lets say I want to add CDM block
> support. Then that information is outside of topology today because I
> will use CDM if my output format is yuv. It has nothing to do with
> topology but that block still needs to come from RM.

I'd say, it is a part of the topology. CDM blocks are a part of the
pipeline, aren't they?

If you prefer, we can rename msm_display_topology to dpu_rm_requirements itself.

> I know that usually I have lost on these type of discussions saying that
> if the code is not there yet, it should be dropped but I do have a plan
> to add that support soon probably by the next cycle. That time we will
> need some sort of wrapper to hold the topology and "extra" information
> to allocate the blocks.
>
> One alternative ofcourse is to expand dpu_rm_reserve() to accept
> something like "needs_cdm" but this is not scalable.
>
> Thoughts?
>
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 69 +++++++--------------
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  2 +-
> >   3 files changed, 23 insertions(+), 50 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 4ee708264f3b..a2cb23dea0b8 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -638,7 +638,7 @@ static int dpu_encoder_virt_atomic_check(
> >
> >               if (!crtc_state->active_changed || crtc_state->enable)
> >                       ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> > -                                     drm_enc, crtc_state, topology);
> > +                                     drm_enc, crtc_state, &topology);
> >       }
> >
> >       trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > index f4dda88a73f7..952e139c0234 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > @@ -24,15 +24,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
> >       return res_map[idx] && res_map[idx] != enc_id;
> >   }
> >
> > -/**
> > - * struct dpu_rm_requirements - Reservation requirements parameter bundle
> > - * @topology:  selected topology for the display
> > - * @hw_res:     Hardware resources required as reported by the encoders
> > - */
> > -struct dpu_rm_requirements {
> > -     struct msm_display_topology topology;
> > -};
> > -
> >   int dpu_rm_destroy(struct dpu_rm *rm)
> >   {
> >       int i;
> > @@ -329,14 +320,13 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
> >    *      mixer in rm->pingpong_blks[].
> >    * @dspp_idx: output parameter, index of dspp block attached to the layer
> >    *      mixer in rm->dspp_blks[].
> > - * @reqs: input parameter, rm requirements for HW blocks needed in the
> > - *      datapath.
> > + * @topology:  selected topology for the display
> >    * Return: true if lm matches all requirements, false otherwise
> >    */
> >   static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> >               struct dpu_global_state *global_state,
> >               uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > -             struct dpu_rm_requirements *reqs)
> > +             struct msm_display_topology *topology)
> >   {
> >       const struct dpu_lm_cfg *lm_cfg;
> >       int idx;
> > @@ -361,7 +351,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> >       }
> >       *pp_idx = idx;
> >
> > -     if (!reqs->topology.num_dspp)
> > +     if (!topology->num_dspp)
> >               return true;
> >
> >       idx = lm_cfg->dspp - DSPP_0;
> > @@ -383,7 +373,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> >   static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >                              struct dpu_global_state *global_state,
> >                              uint32_t enc_id,
> > -                            struct dpu_rm_requirements *reqs)
> > +                            struct msm_display_topology *topology)
> >
> >   {
> >       int lm_idx[MAX_BLOCKS];
> > @@ -391,14 +381,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >       int dspp_idx[MAX_BLOCKS] = {0};
> >       int i, j, lm_count = 0;
> >
> > -     if (!reqs->topology.num_lm) {
> > -             DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
> > +     if (!topology->num_lm) {
> > +             DPU_ERROR("invalid number of lm: %d\n", topology->num_lm);
> >               return -EINVAL;
> >       }
> >
> >       /* Find a primary mixer */
> >       for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> > -                     lm_count < reqs->topology.num_lm; i++) {
> > +                     lm_count < topology->num_lm; i++) {
> >               if (!rm->mixer_blks[i])
> >                       continue;
> >
> > @@ -407,7 +397,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >
> >               if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
> >                               enc_id, i, &pp_idx[lm_count],
> > -                             &dspp_idx[lm_count], reqs)) {
> > +                             &dspp_idx[lm_count], topology)) {
> >                       continue;
> >               }
> >
> > @@ -415,7 +405,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >
> >               /* Valid primary mixer found, find matching peers */
> >               for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
> > -                             lm_count < reqs->topology.num_lm; j++) {
> > +                             lm_count < topology->num_lm; j++) {
> >                       if (!rm->mixer_blks[j])
> >                               continue;
> >
> > @@ -428,7 +418,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >                       if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
> >                                       global_state, enc_id, j,
> >                                       &pp_idx[lm_count], &dspp_idx[lm_count],
> > -                                     reqs)) {
> > +                                     topology)) {
> >                               continue;
> >                       }
> >
> > @@ -437,7 +427,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >               }
> >       }
> >
> > -     if (lm_count != reqs->topology.num_lm) {
> > +     if (lm_count != topology->num_lm) {
> >               DPU_DEBUG("unable to find appropriate mixers\n");
> >               return -ENAVAIL;
> >       }
> > @@ -446,7 +436,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> >               global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
> >               global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
> >               global_state->dspp_to_enc_id[dspp_idx[i]] =
> > -                     reqs->topology.num_dspp ? enc_id : 0;
> > +                     topology->num_dspp ? enc_id : 0;
> >
> >               trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
> >                                        pp_idx[i] + PINGPONG_0);
> > @@ -539,44 +529,30 @@ static int _dpu_rm_make_reservation(
> >               struct dpu_rm *rm,
> >               struct dpu_global_state *global_state,
> >               struct drm_encoder *enc,
> > -             struct dpu_rm_requirements *reqs)
> > +             struct msm_display_topology *topology)
> >   {
> >       int ret;
> >
> > -     ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
> > +     ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
> >       if (ret) {
> >               DPU_ERROR("unable to find appropriate mixers\n");
> >               return ret;
> >       }
> >
> >       ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> > -                             &reqs->topology);
> > +                                topology);
> >       if (ret) {
> >               DPU_ERROR("unable to find appropriate CTL\n");
> >               return ret;
> >       }
> >
> > -     ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
> > +     ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
> >       if (ret)
> >               return ret;
> >
> >       return ret;
> >   }
> >
> > -static int _dpu_rm_populate_requirements(
> > -             struct drm_encoder *enc,
> > -             struct dpu_rm_requirements *reqs,
> > -             struct msm_display_topology req_topology)
> > -{
> > -     reqs->topology = req_topology;
> > -
> > -     DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> > -                   reqs->topology.num_lm, reqs->topology.num_dsc,
> > -                   reqs->topology.num_intf);
> > -
> > -     return 0;
> > -}
> > -
> >   static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> >                                 uint32_t enc_id)
> >   {
> > @@ -608,9 +584,8 @@ int dpu_rm_reserve(
> >               struct dpu_global_state *global_state,
> >               struct drm_encoder *enc,
> >               struct drm_crtc_state *crtc_state,
> > -             struct msm_display_topology topology)
> > +             struct msm_display_topology *topology)
> >   {
> > -     struct dpu_rm_requirements reqs;
> >       int ret;
> >
> >       /* Check if this is just a page-flip */
> > @@ -625,13 +600,11 @@ int dpu_rm_reserve(
> >       DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> >                     enc->base.id, crtc_state->crtc->base.id);
> >
> > -     ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
> > -     if (ret) {
> > -             DPU_ERROR("failed to populate hw requirements\n");
> > -             return ret;
> > -     }
> > +     DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> > +                   topology->num_lm, topology->num_dsc,
> > +                   topology->num_intf);
> >
> > -     ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
> > +     ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
> >       if (ret)
> >               DPU_ERROR("failed to reserve hw resources: %d\n", ret);
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > index d62c2edb2460..f05697462856 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > @@ -71,7 +71,7 @@ int dpu_rm_reserve(struct dpu_rm *rm,
> >               struct dpu_global_state *global_state,
> >               struct drm_encoder *drm_enc,
> >               struct drm_crtc_state *crtc_state,
> > -             struct msm_display_topology topology);
> > +             struct msm_display_topology *topology);
> >
> >   /**
> >    * dpu_rm_reserve - Given the encoder for the display chain, release any



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes
  2023-05-14 17:01     ` Dmitry Baryshkov
@ 2023-05-15 18:45       ` Abhinav Kumar
  2023-05-15 19:12         ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-15 18:45 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 5/14/2023 10:01 AM, Dmitry Baryshkov wrote:
> On Sat, 13 May 2023 at 01:12, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>> Take into account the plane rotation and flipping when calculating src
>>> positions for the wide plane parts.
>>>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>
>> Do we need to have a fixes tag for this? This means we dont consider
>> rotation while calculating src position today which is a bug?
> 
> Hmm, I thought that I had a check forbidding rotation with the current
> approach, but I don't see it. Most probably I thought about it and
> then forgot to add it.
> The proper fix should be to disallow it for static SSPP case. I'll
> include the patch into v3.
> 
>>
>>> ---
>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++++++++++++++---------
>>>    1 file changed, 17 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>> index 2e63eb0a2f3f..d43e04fc4578 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>> @@ -887,16 +887,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>>>                return -EINVAL;
>>>        }
>>>
>>> -     pipe_cfg->src_rect = new_plane_state->src;
>>> -
>>> -     /* state->src is 16.16, src_rect is not */
>>> -     pipe_cfg->src_rect.x1 >>= 16;
>>> -     pipe_cfg->src_rect.x2 >>= 16;
>>> -     pipe_cfg->src_rect.y1 >>= 16;
>>> -     pipe_cfg->src_rect.y2 >>= 16;
>>> -
>>> -     pipe_cfg->dst_rect = new_plane_state->dst;
>>> -
>>>        fb_rect.x2 = new_plane_state->fb->width;
>>>        fb_rect.y2 = new_plane_state->fb->height;
>>>
>>> @@ -912,6 +902,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>>>
>>>        max_linewidth = pdpu->catalog->caps->max_linewidth;
>>>
>>> +     /* state->src is 16.16, src_rect is not */
>>> +     drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
>>> +
>>> +     pipe_cfg->dst_rect = new_plane_state->dst;
>>> +
>>> +     drm_rect_rotate(&pipe_cfg->src_rect,
>>> +                     new_plane_state->fb->width, new_plane_state->fb->height,
>>> +                     new_plane_state->rotation);
>>> +
>>>        if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
>>>                /*
>>>                 * In parallel multirect case only the half of the usual width
>>> @@ -959,6 +958,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>>>                r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
>>>        }
>>>
>>> +     drm_rect_rotate_inv(&pipe_cfg->src_rect,
>>> +                         new_plane_state->fb->width, new_plane_state->fb->height,
>>> +                         new_plane_state->rotation);
>>> +     if (r_pipe->sspp)
>>
>> Dont you need to check for if (r_pipe_cfg) here and not if
>> (r_pipe->sspp) because parameter you are passing is the r_pipe_cfg to
>> drm_rect_rotate_inv().
> 
> Of course not. r_pipe_cfg is a pointer to the field in pstate. We know
> that it can not be NULL.
> 

Ack, and my bad for not checking that r_pipe_cfg points to a field in 
pstate but .... it was just weird though that you are checking for 
r_pipe->sspp before calling a method which really doesnt care if its 
null or not. How about you use drm_rect_visible(r_pipe_cfg->src_rect)

If its not set, it wont be visible too.

>>
>> So we rotated the pipe_cfg once, then rotated_inv it to restore the
>> rectangle to its original state, but r_pipe_cfg's rectangle was never
>> rotated as it was not allocated before this function so it will remain
>> in inverse rotated state now right?
> 
> No. r_pipe_cfg is set beforehand to the half of the rotated pipe_cfg.
> 

Ok i got it now. Instead of directly operating on the plane_state's 
rectangle which makes you to invert again why not just use a temporary 
drm_rect which stores the rotated pipe_cfg->src_rect. That way you dont 
have to invert anything?

>>> +             drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
>>> +                                 new_plane_state->fb->width, new_plane_state->fb->height,
>>> +                                 new_plane_state->rotation);
>>> +
>>>        ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
>>>        if (ret)
>>>                return ret;
> 
> 
> 
> --
> With best wishes
> Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes
  2023-05-15 18:45       ` Abhinav Kumar
@ 2023-05-15 19:12         ` Dmitry Baryshkov
  2023-05-15 19:32           ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-15 19:12 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On Mon, 15 May 2023 at 21:45, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 5/14/2023 10:01 AM, Dmitry Baryshkov wrote:
> > On Sat, 13 May 2023 at 01:12, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> >>> Take into account the plane rotation and flipping when calculating src
> >>> positions for the wide plane parts.
> >>>
> >>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >>
> >> Do we need to have a fixes tag for this? This means we dont consider
> >> rotation while calculating src position today which is a bug?
> >
> > Hmm, I thought that I had a check forbidding rotation with the current
> > approach, but I don't see it. Most probably I thought about it and
> > then forgot to add it.
> > The proper fix should be to disallow it for static SSPP case. I'll
> > include the patch into v3.
> >
> >>
> >>> ---
> >>>    drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++++++++++++++---------
> >>>    1 file changed, 17 insertions(+), 10 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> >>> index 2e63eb0a2f3f..d43e04fc4578 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> >>> @@ -887,16 +887,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
> >>>                return -EINVAL;
> >>>        }
> >>>
> >>> -     pipe_cfg->src_rect = new_plane_state->src;
> >>> -
> >>> -     /* state->src is 16.16, src_rect is not */
> >>> -     pipe_cfg->src_rect.x1 >>= 16;
> >>> -     pipe_cfg->src_rect.x2 >>= 16;
> >>> -     pipe_cfg->src_rect.y1 >>= 16;
> >>> -     pipe_cfg->src_rect.y2 >>= 16;
> >>> -
> >>> -     pipe_cfg->dst_rect = new_plane_state->dst;
> >>> -
> >>>        fb_rect.x2 = new_plane_state->fb->width;
> >>>        fb_rect.y2 = new_plane_state->fb->height;
> >>>
> >>> @@ -912,6 +902,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
> >>>
> >>>        max_linewidth = pdpu->catalog->caps->max_linewidth;
> >>>
> >>> +     /* state->src is 16.16, src_rect is not */
> >>> +     drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
> >>> +
> >>> +     pipe_cfg->dst_rect = new_plane_state->dst;
> >>> +
> >>> +     drm_rect_rotate(&pipe_cfg->src_rect,
> >>> +                     new_plane_state->fb->width, new_plane_state->fb->height,
> >>> +                     new_plane_state->rotation);
> >>> +
> >>>        if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
> >>>                /*
> >>>                 * In parallel multirect case only the half of the usual width
> >>> @@ -959,6 +958,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
> >>>                r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
> >>>        }
> >>>
> >>> +     drm_rect_rotate_inv(&pipe_cfg->src_rect,
> >>> +                         new_plane_state->fb->width, new_plane_state->fb->height,
> >>> +                         new_plane_state->rotation);
> >>> +     if (r_pipe->sspp)
> >>
> >> Dont you need to check for if (r_pipe_cfg) here and not if
> >> (r_pipe->sspp) because parameter you are passing is the r_pipe_cfg to
> >> drm_rect_rotate_inv().
> >
> > Of course not. r_pipe_cfg is a pointer to the field in pstate. We know
> > that it can not be NULL.
> >
>
> Ack, and my bad for not checking that r_pipe_cfg points to a field in
> pstate but .... it was just weird though that you are checking for
> r_pipe->sspp before calling a method which really doesnt care if its
> null or not. How about you use drm_rect_visible(r_pipe_cfg->src_rect)
>
> If its not set, it wont be visible too.

I think it is better for the uniformity to check for r_pipe->sspp:
this is the condition that is used all over the driver to check that
r_pipe is used.

>
> >>
> >> So we rotated the pipe_cfg once, then rotated_inv it to restore the
> >> rectangle to its original state, but r_pipe_cfg's rectangle was never
> >> rotated as it was not allocated before this function so it will remain
> >> in inverse rotated state now right?
> >
> > No. r_pipe_cfg is set beforehand to the half of the rotated pipe_cfg.
> >
>
> Ok i got it now. Instead of directly operating on the plane_state's
> rectangle which makes you to invert again why not just use a temporary
> drm_rect which stores the rotated pipe_cfg->src_rect. That way you dont
> have to invert anything?

I don't think this will work. I explicitly rotate & invert rotation to
get correct coordinates for both source and destination rectangles.
Doing it otherwise would require us to manually implement this in the
DPU driver.

>
> >>> +             drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
> >>> +                                 new_plane_state->fb->width, new_plane_state->fb->height,
> >>> +                                 new_plane_state->rotation);
> >>> +
> >>>        ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
> >>>        if (ret)
> >>>                return ret;
> >
> >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes
  2023-05-15 19:12         ` Dmitry Baryshkov
@ 2023-05-15 19:32           ` Abhinav Kumar
  0 siblings, 0 replies; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-15 19:32 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 5/15/2023 12:12 PM, Dmitry Baryshkov wrote:
> On Mon, 15 May 2023 at 21:45, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 5/14/2023 10:01 AM, Dmitry Baryshkov wrote:
>>> On Sat, 13 May 2023 at 01:12, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>> Take into account the plane rotation and flipping when calculating src
>>>>> positions for the wide plane parts.
>>>>>
>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>
>>>> Do we need to have a fixes tag for this? This means we dont consider
>>>> rotation while calculating src position today which is a bug?
>>>
>>> Hmm, I thought that I had a check forbidding rotation with the current
>>> approach, but I don't see it. Most probably I thought about it and
>>> then forgot to add it.
>>> The proper fix should be to disallow it for static SSPP case. I'll
>>> include the patch into v3.
>>>
>>>>
>>>>> ---
>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 27 ++++++++++++++---------
>>>>>     1 file changed, 17 insertions(+), 10 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>>>> index 2e63eb0a2f3f..d43e04fc4578 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>>>> @@ -887,16 +887,6 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>>>>>                 return -EINVAL;
>>>>>         }
>>>>>
>>>>> -     pipe_cfg->src_rect = new_plane_state->src;
>>>>> -
>>>>> -     /* state->src is 16.16, src_rect is not */
>>>>> -     pipe_cfg->src_rect.x1 >>= 16;
>>>>> -     pipe_cfg->src_rect.x2 >>= 16;
>>>>> -     pipe_cfg->src_rect.y1 >>= 16;
>>>>> -     pipe_cfg->src_rect.y2 >>= 16;
>>>>> -
>>>>> -     pipe_cfg->dst_rect = new_plane_state->dst;
>>>>> -
>>>>>         fb_rect.x2 = new_plane_state->fb->width;
>>>>>         fb_rect.y2 = new_plane_state->fb->height;
>>>>>
>>>>> @@ -912,6 +902,15 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>>>>>
>>>>>         max_linewidth = pdpu->catalog->caps->max_linewidth;
>>>>>
>>>>> +     /* state->src is 16.16, src_rect is not */
>>>>> +     drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);
>>>>> +
>>>>> +     pipe_cfg->dst_rect = new_plane_state->dst;
>>>>> +
>>>>> +     drm_rect_rotate(&pipe_cfg->src_rect,
>>>>> +                     new_plane_state->fb->width, new_plane_state->fb->height,
>>>>> +                     new_plane_state->rotation);
>>>>> +
>>>>>         if (drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) {
>>>>>                 /*
>>>>>                  * In parallel multirect case only the half of the usual width
>>>>> @@ -959,6 +958,14 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>>>>>                 r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2;
>>>>>         }
>>>>>
>>>>> +     drm_rect_rotate_inv(&pipe_cfg->src_rect,
>>>>> +                         new_plane_state->fb->width, new_plane_state->fb->height,
>>>>> +                         new_plane_state->rotation);
>>>>> +     if (r_pipe->sspp)
>>>>
>>>> Dont you need to check for if (r_pipe_cfg) here and not if
>>>> (r_pipe->sspp) because parameter you are passing is the r_pipe_cfg to
>>>> drm_rect_rotate_inv().
>>>
>>> Of course not. r_pipe_cfg is a pointer to the field in pstate. We know
>>> that it can not be NULL.
>>>
>>
>> Ack, and my bad for not checking that r_pipe_cfg points to a field in
>> pstate but .... it was just weird though that you are checking for
>> r_pipe->sspp before calling a method which really doesnt care if its
>> null or not. How about you use drm_rect_visible(r_pipe_cfg->src_rect)
>>
>> If its not set, it wont be visible too.
> 
> I think it is better for the uniformity to check for r_pipe->sspp:
> this is the condition that is used all over the driver to check that
> r_pipe is used.
> 

hmmm .... okay .... not entirely convinced this was the right way to 
begin with then because some places do need a valid sspp for the 
function getting called so thats fine but some do not.

its incorrect uniformity, but I am not going to complain about it now. 
will think of cleaning it up once this lands.

>>
>>>>
>>>> So we rotated the pipe_cfg once, then rotated_inv it to restore the
>>>> rectangle to its original state, but r_pipe_cfg's rectangle was never
>>>> rotated as it was not allocated before this function so it will remain
>>>> in inverse rotated state now right?
>>>
>>> No. r_pipe_cfg is set beforehand to the half of the rotated pipe_cfg.
>>>
>>
>> Ok i got it now. Instead of directly operating on the plane_state's
>> rectangle which makes you to invert again why not just use a temporary
>> drm_rect which stores the rotated pipe_cfg->src_rect. That way you dont
>> have to invert anything?
> 
> I don't think this will work. I explicitly rotate & invert rotation to
> get correct coordinates for both source and destination rectangles.
> Doing it otherwise would require us to manually implement this in the
> DPU driver.
> 

Ok got it, i guess this will need more changes within the if (src_width 
 > max_width) .... this is fine then.

Will ack this once i finish reviews on the others.

>>
>>>>> +             drm_rect_rotate_inv(&r_pipe_cfg->src_rect,
>>>>> +                                 new_plane_state->fb->width, new_plane_state->fb->height,
>>>>> +                                 new_plane_state->rotation);
>>>>> +
>>>>>         ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt);
>>>>>         if (ret)
>>>>>                 return ret;
>>>
>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
> 
> 
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements
  2023-05-14 17:06     ` Dmitry Baryshkov
@ 2023-05-17 23:53       ` Abhinav Kumar
  2023-05-18 23:19         ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-17 23:53 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 5/14/2023 10:06 AM, Dmitry Baryshkov wrote:
> On Sat, 13 May 2023 at 01:39, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>> The struct dpu_rm_requirements was used to wrap display topology and
>>> hw resources, which meant INTF indices. As of commit ef58e0ad3436
>>> ("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
>>> resources struct was removed, leaving struct dpu_rm_requirements
>>> containing a single field (topology). Remove the useless wrapper.
>>>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> ---
>>
>> Irrespective of where we plan to have the topology, this change doesn't
>> seem incorrect as such.
>>
>> The only thing I can think of is when we need more information to be
>> passed to the RM to allocate the blocks in addition to the topology this
>> struct could have been expanded.
>>
>> So one example I can think of is lets say I want to add CDM block
>> support. Then that information is outside of topology today because I
>> will use CDM if my output format is yuv. It has nothing to do with
>> topology but that block still needs to come from RM.
> 
> I'd say, it is a part of the topology. CDM blocks are a part of the
> pipeline, aren't they?
> 
> If you prefer, we can rename msm_display_topology to dpu_rm_requirements itself.
> 

I am fine with renaming msm_display_topology to dpu_rm_requirements.

Because making CDM part of topology wont be right.

>> I know that usually I have lost on these type of discussions saying that
>> if the code is not there yet, it should be dropped but I do have a plan
>> to add that support soon probably by the next cycle. That time we will
>> need some sort of wrapper to hold the topology and "extra" information
>> to allocate the blocks.
>>
>> One alternative ofcourse is to expand dpu_rm_reserve() to accept
>> something like "needs_cdm" but this is not scalable.
>>
>> Thoughts?
>>
>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 69 +++++++--------------
>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  2 +-
>>>    3 files changed, 23 insertions(+), 50 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> index 4ee708264f3b..a2cb23dea0b8 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> @@ -638,7 +638,7 @@ static int dpu_encoder_virt_atomic_check(
>>>
>>>                if (!crtc_state->active_changed || crtc_state->enable)
>>>                        ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>>> -                                     drm_enc, crtc_state, topology);
>>> +                                     drm_enc, crtc_state, &topology);
>>>        }
>>>
>>>        trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> index f4dda88a73f7..952e139c0234 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> @@ -24,15 +24,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
>>>        return res_map[idx] && res_map[idx] != enc_id;
>>>    }
>>>
>>> -/**
>>> - * struct dpu_rm_requirements - Reservation requirements parameter bundle
>>> - * @topology:  selected topology for the display
>>> - * @hw_res:     Hardware resources required as reported by the encoders
>>> - */
>>> -struct dpu_rm_requirements {
>>> -     struct msm_display_topology topology;
>>> -};
>>> -
>>>    int dpu_rm_destroy(struct dpu_rm *rm)
>>>    {
>>>        int i;
>>> @@ -329,14 +320,13 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
>>>     *      mixer in rm->pingpong_blks[].
>>>     * @dspp_idx: output parameter, index of dspp block attached to the layer
>>>     *      mixer in rm->dspp_blks[].
>>> - * @reqs: input parameter, rm requirements for HW blocks needed in the
>>> - *      datapath.
>>> + * @topology:  selected topology for the display
>>>     * Return: true if lm matches all requirements, false otherwise
>>>     */
>>>    static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>                struct dpu_global_state *global_state,
>>>                uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>>> -             struct dpu_rm_requirements *reqs)
>>> +             struct msm_display_topology *topology)
>>>    {
>>>        const struct dpu_lm_cfg *lm_cfg;
>>>        int idx;
>>> @@ -361,7 +351,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>        }
>>>        *pp_idx = idx;
>>>
>>> -     if (!reqs->topology.num_dspp)
>>> +     if (!topology->num_dspp)
>>>                return true;
>>>
>>>        idx = lm_cfg->dspp - DSPP_0;
>>> @@ -383,7 +373,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>    static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>                               struct dpu_global_state *global_state,
>>>                               uint32_t enc_id,
>>> -                            struct dpu_rm_requirements *reqs)
>>> +                            struct msm_display_topology *topology)
>>>
>>>    {
>>>        int lm_idx[MAX_BLOCKS];
>>> @@ -391,14 +381,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>        int dspp_idx[MAX_BLOCKS] = {0};
>>>        int i, j, lm_count = 0;
>>>
>>> -     if (!reqs->topology.num_lm) {
>>> -             DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
>>> +     if (!topology->num_lm) {
>>> +             DPU_ERROR("invalid number of lm: %d\n", topology->num_lm);
>>>                return -EINVAL;
>>>        }
>>>
>>>        /* Find a primary mixer */
>>>        for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>>> -                     lm_count < reqs->topology.num_lm; i++) {
>>> +                     lm_count < topology->num_lm; i++) {
>>>                if (!rm->mixer_blks[i])
>>>                        continue;
>>>
>>> @@ -407,7 +397,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>
>>>                if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
>>>                                enc_id, i, &pp_idx[lm_count],
>>> -                             &dspp_idx[lm_count], reqs)) {
>>> +                             &dspp_idx[lm_count], topology)) {
>>>                        continue;
>>>                }
>>>
>>> @@ -415,7 +405,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>
>>>                /* Valid primary mixer found, find matching peers */
>>>                for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
>>> -                             lm_count < reqs->topology.num_lm; j++) {
>>> +                             lm_count < topology->num_lm; j++) {
>>>                        if (!rm->mixer_blks[j])
>>>                                continue;
>>>
>>> @@ -428,7 +418,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>                        if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
>>>                                        global_state, enc_id, j,
>>>                                        &pp_idx[lm_count], &dspp_idx[lm_count],
>>> -                                     reqs)) {
>>> +                                     topology)) {
>>>                                continue;
>>>                        }
>>>
>>> @@ -437,7 +427,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>                }
>>>        }
>>>
>>> -     if (lm_count != reqs->topology.num_lm) {
>>> +     if (lm_count != topology->num_lm) {
>>>                DPU_DEBUG("unable to find appropriate mixers\n");
>>>                return -ENAVAIL;
>>>        }
>>> @@ -446,7 +436,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>                global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
>>>                global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
>>>                global_state->dspp_to_enc_id[dspp_idx[i]] =
>>> -                     reqs->topology.num_dspp ? enc_id : 0;
>>> +                     topology->num_dspp ? enc_id : 0;
>>>
>>>                trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
>>>                                         pp_idx[i] + PINGPONG_0);
>>> @@ -539,44 +529,30 @@ static int _dpu_rm_make_reservation(
>>>                struct dpu_rm *rm,
>>>                struct dpu_global_state *global_state,
>>>                struct drm_encoder *enc,
>>> -             struct dpu_rm_requirements *reqs)
>>> +             struct msm_display_topology *topology)
>>>    {
>>>        int ret;
>>>
>>> -     ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
>>> +     ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
>>>        if (ret) {
>>>                DPU_ERROR("unable to find appropriate mixers\n");
>>>                return ret;
>>>        }
>>>
>>>        ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
>>> -                             &reqs->topology);
>>> +                                topology);
>>>        if (ret) {
>>>                DPU_ERROR("unable to find appropriate CTL\n");
>>>                return ret;
>>>        }
>>>
>>> -     ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
>>> +     ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
>>>        if (ret)
>>>                return ret;
>>>
>>>        return ret;
>>>    }
>>>
>>> -static int _dpu_rm_populate_requirements(
>>> -             struct drm_encoder *enc,
>>> -             struct dpu_rm_requirements *reqs,
>>> -             struct msm_display_topology req_topology)
>>> -{
>>> -     reqs->topology = req_topology;
>>> -
>>> -     DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>> -                   reqs->topology.num_lm, reqs->topology.num_dsc,
>>> -                   reqs->topology.num_intf);
>>> -
>>> -     return 0;
>>> -}
>>> -
>>>    static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>>>                                  uint32_t enc_id)
>>>    {
>>> @@ -608,9 +584,8 @@ int dpu_rm_reserve(
>>>                struct dpu_global_state *global_state,
>>>                struct drm_encoder *enc,
>>>                struct drm_crtc_state *crtc_state,
>>> -             struct msm_display_topology topology)
>>> +             struct msm_display_topology *topology)
>>>    {
>>> -     struct dpu_rm_requirements reqs;
>>>        int ret;
>>>
>>>        /* Check if this is just a page-flip */
>>> @@ -625,13 +600,11 @@ int dpu_rm_reserve(
>>>        DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>>>                      enc->base.id, crtc_state->crtc->base.id);
>>>
>>> -     ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
>>> -     if (ret) {
>>> -             DPU_ERROR("failed to populate hw requirements\n");
>>> -             return ret;
>>> -     }
>>> +     DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>> +                   topology->num_lm, topology->num_dsc,
>>> +                   topology->num_intf);
>>>
>>> -     ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
>>> +     ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
>>>        if (ret)
>>>                DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> index d62c2edb2460..f05697462856 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> @@ -71,7 +71,7 @@ int dpu_rm_reserve(struct dpu_rm *rm,
>>>                struct dpu_global_state *global_state,
>>>                struct drm_encoder *drm_enc,
>>>                struct drm_crtc_state *crtc_state,
>>> -             struct msm_display_topology topology);
>>> +             struct msm_display_topology *topology);
>>>
>>>    /**
>>>     * dpu_rm_reserve - Given the encoder for the display chain, release any
> 
> 
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements
  2023-05-17 23:53       ` Abhinav Kumar
@ 2023-05-18 23:19         ` Abhinav Kumar
  0 siblings, 0 replies; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-18 23:19 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 5/17/2023 4:53 PM, Abhinav Kumar wrote:
> 
> 
> On 5/14/2023 10:06 AM, Dmitry Baryshkov wrote:
>> On Sat, 13 May 2023 at 01:39, Abhinav Kumar 
>> <quic_abhinavk@quicinc.com> wrote:
>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>> The struct dpu_rm_requirements was used to wrap display topology and
>>>> hw resources, which meant INTF indices. As of commit ef58e0ad3436
>>>> ("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
>>>> resources struct was removed, leaving struct dpu_rm_requirements
>>>> containing a single field (topology). Remove the useless wrapper.
>>>>
>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>> ---
>>>
>>> Irrespective of where we plan to have the topology, this change doesn't
>>> seem incorrect as such.
>>>
>>> The only thing I can think of is when we need more information to be
>>> passed to the RM to allocate the blocks in addition to the topology this
>>> struct could have been expanded.
>>>
>>> So one example I can think of is lets say I want to add CDM block
>>> support. Then that information is outside of topology today because I
>>> will use CDM if my output format is yuv. It has nothing to do with
>>> topology but that block still needs to come from RM.
>>
>> I'd say, it is a part of the topology. CDM blocks are a part of the
>> pipeline, aren't they?
>>
>> If you prefer, we can rename msm_display_topology to 
>> dpu_rm_requirements itself.
>>
> 
> I am fine with renaming msm_display_topology to dpu_rm_requirements.
> 
> Because making CDM part of topology wont be right.
> 

Just to add, perhaps rename it to dpu_rm_display_requirements

>>> I know that usually I have lost on these type of discussions saying that
>>> if the code is not there yet, it should be dropped but I do have a plan
>>> to add that support soon probably by the next cycle. That time we will
>>> need some sort of wrapper to hold the topology and "extra" information
>>> to allocate the blocks.
>>>
>>> One alternative ofcourse is to expand dpu_rm_reserve() to accept
>>> something like "needs_cdm" but this is not scalable.
>>>
>>> Thoughts?
>>>
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 69 
>>>> +++++++--------------
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  2 +-
>>>>    3 files changed, 23 insertions(+), 50 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> index 4ee708264f3b..a2cb23dea0b8 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> @@ -638,7 +638,7 @@ static int dpu_encoder_virt_atomic_check(
>>>>
>>>>                if (!crtc_state->active_changed || crtc_state->enable)
>>>>                        ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>>>> -                                     drm_enc, crtc_state, topology);
>>>> +                                     drm_enc, crtc_state, &topology);
>>>>        }
>>>>
>>>>        trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), 
>>>> adj_mode->flags);
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> index f4dda88a73f7..952e139c0234 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> @@ -24,15 +24,6 @@ static inline bool reserved_by_other(uint32_t 
>>>> *res_map, int idx,
>>>>        return res_map[idx] && res_map[idx] != enc_id;
>>>>    }
>>>>
>>>> -/**
>>>> - * struct dpu_rm_requirements - Reservation requirements parameter 
>>>> bundle
>>>> - * @topology:  selected topology for the display
>>>> - * @hw_res:     Hardware resources required as reported by the 
>>>> encoders
>>>> - */
>>>> -struct dpu_rm_requirements {
>>>> -     struct msm_display_topology topology;
>>>> -};
>>>> -
>>>>    int dpu_rm_destroy(struct dpu_rm *rm)
>>>>    {
>>>>        int i;
>>>> @@ -329,14 +320,13 @@ static bool _dpu_rm_check_lm_peer(struct 
>>>> dpu_rm *rm, int primary_idx,
>>>>     *      mixer in rm->pingpong_blks[].
>>>>     * @dspp_idx: output parameter, index of dspp block attached to 
>>>> the layer
>>>>     *      mixer in rm->dspp_blks[].
>>>> - * @reqs: input parameter, rm requirements for HW blocks needed in the
>>>> - *      datapath.
>>>> + * @topology:  selected topology for the display
>>>>     * Return: true if lm matches all requirements, false otherwise
>>>>     */
>>>>    static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm 
>>>> *rm,
>>>>                struct dpu_global_state *global_state,
>>>>                uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>>>> -             struct dpu_rm_requirements *reqs)
>>>> +             struct msm_display_topology *topology)
>>>>    {
>>>>        const struct dpu_lm_cfg *lm_cfg;
>>>>        int idx;
>>>> @@ -361,7 +351,7 @@ static bool 
>>>> _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>>        }
>>>>        *pp_idx = idx;
>>>>
>>>> -     if (!reqs->topology.num_dspp)
>>>> +     if (!topology->num_dspp)
>>>>                return true;
>>>>
>>>>        idx = lm_cfg->dspp - DSPP_0;
>>>> @@ -383,7 +373,7 @@ static bool 
>>>> _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>>    static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>                               struct dpu_global_state *global_state,
>>>>                               uint32_t enc_id,
>>>> -                            struct dpu_rm_requirements *reqs)
>>>> +                            struct msm_display_topology *topology)
>>>>
>>>>    {
>>>>        int lm_idx[MAX_BLOCKS];
>>>> @@ -391,14 +381,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>        int dspp_idx[MAX_BLOCKS] = {0};
>>>>        int i, j, lm_count = 0;
>>>>
>>>> -     if (!reqs->topology.num_lm) {
>>>> -             DPU_ERROR("invalid number of lm: %d\n", 
>>>> reqs->topology.num_lm);
>>>> +     if (!topology->num_lm) {
>>>> +             DPU_ERROR("invalid number of lm: %d\n", 
>>>> topology->num_lm);
>>>>                return -EINVAL;
>>>>        }
>>>>
>>>>        /* Find a primary mixer */
>>>>        for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>>>> -                     lm_count < reqs->topology.num_lm; i++) {
>>>> +                     lm_count < topology->num_lm; i++) {
>>>>                if (!rm->mixer_blks[i])
>>>>                        continue;
>>>>
>>>> @@ -407,7 +397,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>
>>>>                if (!_dpu_rm_check_lm_and_get_connected_blks(rm, 
>>>> global_state,
>>>>                                enc_id, i, &pp_idx[lm_count],
>>>> -                             &dspp_idx[lm_count], reqs)) {
>>>> +                             &dspp_idx[lm_count], topology)) {
>>>>                        continue;
>>>>                }
>>>>
>>>> @@ -415,7 +405,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>
>>>>                /* Valid primary mixer found, find matching peers */
>>>>                for (j = i + 1; j < ARRAY_SIZE(rm->mixer_blks) &&
>>>> -                             lm_count < reqs->topology.num_lm; j++) {
>>>> +                             lm_count < topology->num_lm; j++) {
>>>>                        if (!rm->mixer_blks[j])
>>>>                                continue;
>>>>
>>>> @@ -428,7 +418,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>                        if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
>>>>                                        global_state, enc_id, j,
>>>>                                        &pp_idx[lm_count], 
>>>> &dspp_idx[lm_count],
>>>> -                                     reqs)) {
>>>> +                                     topology)) {
>>>>                                continue;
>>>>                        }
>>>>
>>>> @@ -437,7 +427,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>                }
>>>>        }
>>>>
>>>> -     if (lm_count != reqs->topology.num_lm) {
>>>> +     if (lm_count != topology->num_lm) {
>>>>                DPU_DEBUG("unable to find appropriate mixers\n");
>>>>                return -ENAVAIL;
>>>>        }
>>>> @@ -446,7 +436,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>                global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
>>>>                global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
>>>>                global_state->dspp_to_enc_id[dspp_idx[i]] =
>>>> -                     reqs->topology.num_dspp ? enc_id : 0;
>>>> +                     topology->num_dspp ? enc_id : 0;
>>>>
>>>>                trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
>>>>                                         pp_idx[i] + PINGPONG_0);
>>>> @@ -539,44 +529,30 @@ static int _dpu_rm_make_reservation(
>>>>                struct dpu_rm *rm,
>>>>                struct dpu_global_state *global_state,
>>>>                struct drm_encoder *enc,
>>>> -             struct dpu_rm_requirements *reqs)
>>>> +             struct msm_display_topology *topology)
>>>>    {
>>>>        int ret;
>>>>
>>>> -     ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
>>>> +     ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, 
>>>> topology);
>>>>        if (ret) {
>>>>                DPU_ERROR("unable to find appropriate mixers\n");
>>>>                return ret;
>>>>        }
>>>>
>>>>        ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
>>>> -                             &reqs->topology);
>>>> +                                topology);
>>>>        if (ret) {
>>>>                DPU_ERROR("unable to find appropriate CTL\n");
>>>>                return ret;
>>>>        }
>>>>
>>>> -     ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, 
>>>> &reqs->topology);
>>>> +     ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
>>>>        if (ret)
>>>>                return ret;
>>>>
>>>>        return ret;
>>>>    }
>>>>
>>>> -static int _dpu_rm_populate_requirements(
>>>> -             struct drm_encoder *enc,
>>>> -             struct dpu_rm_requirements *reqs,
>>>> -             struct msm_display_topology req_topology)
>>>> -{
>>>> -     reqs->topology = req_topology;
>>>> -
>>>> -     DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>>> -                   reqs->topology.num_lm, reqs->topology.num_dsc,
>>>> -                   reqs->topology.num_intf);
>>>> -
>>>> -     return 0;
>>>> -}
>>>> -
>>>>    static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>>>>                                  uint32_t enc_id)
>>>>    {
>>>> @@ -608,9 +584,8 @@ int dpu_rm_reserve(
>>>>                struct dpu_global_state *global_state,
>>>>                struct drm_encoder *enc,
>>>>                struct drm_crtc_state *crtc_state,
>>>> -             struct msm_display_topology topology)
>>>> +             struct msm_display_topology *topology)
>>>>    {
>>>> -     struct dpu_rm_requirements reqs;
>>>>        int ret;
>>>>
>>>>        /* Check if this is just a page-flip */
>>>> @@ -625,13 +600,11 @@ int dpu_rm_reserve(
>>>>        DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>>>>                      enc->base.id, crtc_state->crtc->base.id);
>>>>
>>>> -     ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
>>>> -     if (ret) {
>>>> -             DPU_ERROR("failed to populate hw requirements\n");
>>>> -             return ret;
>>>> -     }
>>>> +     DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>>> +                   topology->num_lm, topology->num_dsc,
>>>> +                   topology->num_intf);
>>>>
>>>> -     ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
>>>> +     ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
>>>>        if (ret)
>>>>                DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>> index d62c2edb2460..f05697462856 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>> @@ -71,7 +71,7 @@ int dpu_rm_reserve(struct dpu_rm *rm,
>>>>                struct dpu_global_state *global_state,
>>>>                struct drm_encoder *drm_enc,
>>>>                struct drm_crtc_state *crtc_state,
>>>> -             struct msm_display_topology topology);
>>>> +             struct msm_display_topology *topology);
>>>>
>>>>    /**
>>>>     * dpu_rm_reserve - Given the encoder for the display chain, 
>>>> release any
>>
>>
>>

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
  2023-03-21  1:18 ` [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Dmitry Baryshkov
@ 2023-05-18 23:46   ` Abhinav Kumar
  2023-05-19  1:50     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-18 23:46 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> Up to now the driver has been using encoder to allocate hardware
> resources. Switch it to use CRTC id in preparation for the next step.
> 

This decision to use encoder id instead of CRTC has been there 
downstream for quite sometime. So most of the delay in reviewing this 
series was trying to understand why we had this in the first place and 
who knew that story.

You are right that from the perspective of clone mode mapping resources 
to CRTC is correct but using encoder id is what has been working so far 
without too much difficulty with a little more management  But another 
use-case can get simplified with this.

There is another angle to this. There are hardware blocks which can do 
writeback and the physical display concurrently. We call it concurrent 
writeback or CWB. This is present even on some of the chipsets already 
supported upstream.

Now, lets say we start a concurrent writeback session , in todays code 
we will allocate the resources with the encoder id of the writeback's 
encoder and the other physical display's encoder.

When the session stops, we can just deallocate the resources of the 
writeback encoder without touching the other encoder. So it will become 
easier to just free up the resources mapped to the encoder.

With clone mode implemented with CRTC id to map resources, we will have 
to probably do some extra book-keeping to handle concurrent writeback.

Thats the use-case which gets impacted with this but for others, there 
shouldnt be a major impact from what we see.

That being said, what benefit are you seeing from making that change now 
for this series? Why is it specifically needed for virtual planes?

I see in the commit text that you have mentioned this is in preparation 
for next step and next step talks about clone mode. But clone mode is 
not there yet. So why this change now?

Resource allocation is centered around LMs for the blocks we have seen 
so far like LM, SSPP  but  ....

DSC is already an exception because in earlier chipsets we saw that PP 
and DSC go together and cannot be muxed but later on that changed.

Now, I have explained this case but I am not getting why we need to make 
the change for this series. Is it absolutely necessary?

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  16 +--
>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  10 +-
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 119 ++++++++++----------
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  15 ++-
>   4 files changed, 77 insertions(+), 83 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index a2cb23dea0b8..270c85ea898a 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -634,11 +634,11 @@ static int dpu_encoder_virt_atomic_check(
>   	 * Dont allocate when active is false.
>   	 */
>   	if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> -		dpu_rm_release(global_state, drm_enc);
> +		dpu_rm_release(global_state, crtc_state->crtc);
>   
>   		if (!crtc_state->active_changed || crtc_state->enable)
>   			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> -					drm_enc, crtc_state, &topology);
> +					crtc_state->crtc, &topology);
>   	}
>   
>   	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> @@ -1034,14 +1034,14 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>   
>   	/* Query resource that have been reserved in atomic check step. */
>   	num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> -		drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
> +		drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>   		ARRAY_SIZE(hw_pp));
>   	num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> -		drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> +		drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>   	num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> -		drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> +		drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>   	dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> -		drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
> +		drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
>   		ARRAY_SIZE(hw_dspp));
>   
>   	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> @@ -1050,7 +1050,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>   
>   	if (dpu_enc->dsc) {
>   		num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> -							drm_enc->base.id, DPU_HW_BLK_DSC,
> +							drm_enc->crtc, DPU_HW_BLK_DSC,
>   							hw_dsc, ARRAY_SIZE(hw_dsc));
>   		for (i = 0; i < num_dsc; i++) {
>   			dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
> @@ -1994,7 +1994,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
>   	global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
>   
>   	num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
> -		phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> +		phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>   
>   	for (i = 0; i < num_lm; i++) {
>   		hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index ed80ed6784ee..934874eb2248 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -129,11 +129,11 @@ struct vsync_info {
>   struct dpu_global_state {
>   	struct drm_private_state base;
>   
> -	uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> -	uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> -	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> -	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> -	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> +	uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
> +	uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
> +	uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
> +	uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> +	uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>   };
>   
>   struct dpu_global_state
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 952e139c0234..f0a94008d17a 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -19,9 +19,9 @@
>   
>   
>   static inline bool reserved_by_other(uint32_t *res_map, int idx,
> -				     uint32_t enc_id)
> +				     uint32_t crtc_id)
>   {
> -	return res_map[idx] && res_map[idx] != enc_id;
> +	return res_map[idx] && res_map[idx] != crtc_id;
>   }
>   
>   int dpu_rm_destroy(struct dpu_rm *rm)
> @@ -312,7 +312,7 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
>    *	pingpong
>    * @rm: dpu resource manager handle
>    * @global_state: resources shared across multiple kms objects
> - * @enc_id: encoder id requesting for allocation
> + * @crtc_id: encoder id requesting for allocation
>    * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
>    *      if lm, and all other hardwired blocks connected to the lm (pp) is
>    *      available and appropriate
> @@ -325,14 +325,14 @@ static bool _dpu_rm_check_lm_peer(struct dpu_rm *rm, int primary_idx,
>    */
>   static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
> -		uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> +		uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>   		struct msm_display_topology *topology)
>   {
>   	const struct dpu_lm_cfg *lm_cfg;
>   	int idx;
>   
>   	/* Already reserved? */
> -	if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
> +	if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
>   		DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
>   		return false;
>   	}
> @@ -344,7 +344,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   		return false;
>   	}
>   
> -	if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
> +	if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
>   		DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
>   				lm_cfg->pingpong);
>   		return false;
> @@ -360,7 +360,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   		return false;
>   	}
>   
> -	if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
> +	if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
>   		DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
>   				lm_cfg->dspp);
>   		return false;
> @@ -372,7 +372,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>   
>   static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   			       struct dpu_global_state *global_state,
> -			       uint32_t enc_id,
> +			       uint32_t crtc_id,
>   			       struct msm_display_topology *topology)
>   
>   {
> @@ -396,7 +396,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   		lm_idx[lm_count] = i;
>   
>   		if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
> -				enc_id, i, &pp_idx[lm_count],
> +				crtc_id, i, &pp_idx[lm_count],
>   				&dspp_idx[lm_count], topology)) {
>   			continue;
>   		}
> @@ -416,7 +416,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   			}
>   
>   			if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
> -					global_state, enc_id, j,
> +					global_state, crtc_id, j,
>   					&pp_idx[lm_count], &dspp_idx[lm_count],
>   					topology)) {
>   				continue;
> @@ -433,12 +433,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   	}
>   
>   	for (i = 0; i < lm_count; i++) {
> -		global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
> -		global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
> -		global_state->dspp_to_enc_id[dspp_idx[i]] =
> -			topology->num_dspp ? enc_id : 0;
> +		global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
> +		global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
> +		global_state->dspp_to_crtc_id[dspp_idx[i]] =
> +			topology->num_dspp ? crtc_id : 0;
>   
> -		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
> +		trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
>   					 pp_idx[i] + PINGPONG_0);
>   	}
>   
> @@ -448,7 +448,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>   static int _dpu_rm_reserve_ctls(
>   		struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
> -		uint32_t enc_id,
> +		uint32_t crtc_id,
>   		const struct msm_display_topology *top)
>   {
>   	int ctl_idx[MAX_BLOCKS];
> @@ -467,7 +467,7 @@ static int _dpu_rm_reserve_ctls(
>   
>   		if (!rm->ctl_blks[j])
>   			continue;
> -		if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
> +		if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
>   			continue;
>   
>   		ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
> @@ -491,8 +491,8 @@ static int _dpu_rm_reserve_ctls(
>   		return -ENAVAIL;
>   
>   	for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
> -		global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
> -		trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
> +		global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
> +		trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
>   	}
>   
>   	return 0;
> @@ -500,7 +500,7 @@ static int _dpu_rm_reserve_ctls(
>   
>   static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>   			       struct dpu_global_state *global_state,
> -			       struct drm_encoder *enc,
> +			       uint32_t crtc_id,
>   			       const struct msm_display_topology *top)
>   {
>   	int num_dsc = top->num_dsc;
> @@ -513,14 +513,14 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>   			return -EIO;
>   		}
>   
> -		if (global_state->dsc_to_enc_id[i]) {
> +		if (global_state->dsc_to_crtc_id[i]) {
>   			DPU_ERROR("DSC %d is already allocated\n", i);
>   			return -EIO;
>   		}
>   	}
>   
>   	for (i = 0; i < num_dsc; i++)
> -		global_state->dsc_to_enc_id[i] = enc->base.id;
> +		global_state->dsc_to_crtc_id[i] = crtc_id;
>   
>   	return 0;
>   }
> @@ -528,25 +528,25 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>   static int _dpu_rm_make_reservation(
>   		struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
> -		struct drm_encoder *enc,
> +		uint32_t crtc_id,
>   		struct msm_display_topology *topology)
>   {
>   	int ret;
>   
> -	ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
> +	ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
>   	if (ret) {
>   		DPU_ERROR("unable to find appropriate mixers\n");
>   		return ret;
>   	}
>   
> -	ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> +	ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>   				   topology);
>   	if (ret) {
>   		DPU_ERROR("unable to find appropriate CTL\n");
>   		return ret;
>   	}
>   
> -	ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
> +	ret  = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
>   	if (ret)
>   		return ret;
>   
> @@ -554,97 +554,92 @@ static int _dpu_rm_make_reservation(
>   }
>   
>   static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> -				  uint32_t enc_id)
> +				  uint32_t crtc_id)
>   {
>   	int i;
>   
>   	for (i = 0; i < cnt; i++) {
> -		if (res_mapping[i] == enc_id)
> +		if (res_mapping[i] == crtc_id)
>   			res_mapping[i] = 0;
>   	}
>   }
>   
>   void dpu_rm_release(struct dpu_global_state *global_state,
> -		    struct drm_encoder *enc)
> +		    struct drm_crtc *crtc)
>   {
> -	_dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
> -		ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
> -	_dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
> -		ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
> -	_dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
> -		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
> -	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> -		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> -	_dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> -		ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> +	uint32_t crtc_id = crtc->base.id;
> +
> +	_dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
> +		ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
> +	_dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
> +		ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
> +	_dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
> +		ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
> +	_dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
> +		ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
> +	_dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> +		ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
>   }
>   
>   int dpu_rm_reserve(
>   		struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
> -		struct drm_encoder *enc,
> -		struct drm_crtc_state *crtc_state,
> +		struct drm_crtc *crtc,
>   		struct msm_display_topology *topology)
>   {
>   	int ret;
>   
> -	/* Check if this is just a page-flip */
> -	if (!drm_atomic_crtc_needs_modeset(crtc_state))
> -		return 0;
> -
>   	if (IS_ERR(global_state)) {
>   		DPU_ERROR("failed to global state\n");
>   		return PTR_ERR(global_state);
>   	}
>   
> -	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> -		      enc->base.id, crtc_state->crtc->base.id);
> +	DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
>   
>   	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>   		      topology->num_lm, topology->num_dsc,
>   		      topology->num_intf);
>   
> -	ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
> +	ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
>   	if (ret)
>   		DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>   
> -
> -
>   	return ret;
>   }
>   
>   int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> -	struct dpu_global_state *global_state, uint32_t enc_id,
> +	struct dpu_global_state *global_state, struct drm_crtc *crtc,
>   	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
>   {
> +	uint32_t crtc_id = crtc->base.id;
>   	struct dpu_hw_blk **hw_blks;
> -	uint32_t *hw_to_enc_id;
> +	uint32_t *hw_to_crtc_id;
>   	int i, num_blks, max_blks;
>   
>   	switch (type) {
>   	case DPU_HW_BLK_PINGPONG:
>   		hw_blks = rm->pingpong_blks;
> -		hw_to_enc_id = global_state->pingpong_to_enc_id;
> +		hw_to_crtc_id = global_state->pingpong_to_crtc_id;
>   		max_blks = ARRAY_SIZE(rm->pingpong_blks);
>   		break;
>   	case DPU_HW_BLK_LM:
>   		hw_blks = rm->mixer_blks;
> -		hw_to_enc_id = global_state->mixer_to_enc_id;
> +		hw_to_crtc_id = global_state->mixer_to_crtc_id;
>   		max_blks = ARRAY_SIZE(rm->mixer_blks);
>   		break;
>   	case DPU_HW_BLK_CTL:
>   		hw_blks = rm->ctl_blks;
> -		hw_to_enc_id = global_state->ctl_to_enc_id;
> +		hw_to_crtc_id = global_state->ctl_to_crtc_id;
>   		max_blks = ARRAY_SIZE(rm->ctl_blks);
>   		break;
>   	case DPU_HW_BLK_DSPP:
>   		hw_blks = rm->dspp_blks;
> -		hw_to_enc_id = global_state->dspp_to_enc_id;
> +		hw_to_crtc_id = global_state->dspp_to_crtc_id;
>   		max_blks = ARRAY_SIZE(rm->dspp_blks);
>   		break;
>   	case DPU_HW_BLK_DSC:
>   		hw_blks = rm->dsc_blks;
> -		hw_to_enc_id = global_state->dsc_to_enc_id;
> +		hw_to_crtc_id = global_state->dsc_to_crtc_id;
>   		max_blks = ARRAY_SIZE(rm->dsc_blks);
>   		break;
>   	default:
> @@ -654,17 +649,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>   
>   	num_blks = 0;
>   	for (i = 0; i < max_blks; i++) {
> -		if (hw_to_enc_id[i] != enc_id)
> +		if (hw_to_crtc_id[i] != crtc_id)
>   			continue;
>   
>   		if (num_blks == blks_size) {
> -			DPU_ERROR("More than %d resources assigned to enc %d\n",
> -				  blks_size, enc_id);
> +			DPU_ERROR("More than %d resources assigned to crtc %d\n",
> +				  blks_size, crtc_id);
>   			break;
>   		}
>   		if (!hw_blks[i]) {
> -			DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
> -				  type, enc_id);
> +			DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
> +				  type, crtc_id);
>   			break;
>   		}
>   		blks[num_blks++] = hw_blks[i];
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index f05697462856..f402bec8322b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -62,32 +62,31 @@ int dpu_rm_destroy(struct dpu_rm *rm);
>    *	HW blocks can then be accessed through dpu_rm_get_* functions.
>    *	HW Reservations should be released via dpu_rm_release_hw.
>    * @rm: DPU Resource Manager handle
> - * @drm_enc: DRM Encoder handle
> - * @crtc_state: Proposed Atomic DRM CRTC State handle
> + * @crtc: DRM CRTC handle
>    * @topology: Pointer to topology info for the display
>    * @Return: 0 on Success otherwise -ERROR
>    */
> -int dpu_rm_reserve(struct dpu_rm *rm,
> +int dpu_rm_reserve(
> +		struct dpu_rm *rm,
>   		struct dpu_global_state *global_state,
> -		struct drm_encoder *drm_enc,
> -		struct drm_crtc_state *crtc_state,
> +		struct drm_crtc *crtc,
>   		struct msm_display_topology *topology);
>   
>   /**
>    * dpu_rm_reserve - Given the encoder for the display chain, release any
>    *	HW blocks previously reserved for that use case.
>    * @rm: DPU Resource Manager handle
> - * @enc: DRM Encoder handle
> + * @crtc: DRM CRTC handle
>    * @Return: 0 on Success otherwise -ERROR
>    */
>   void dpu_rm_release(struct dpu_global_state *global_state,
> -		struct drm_encoder *enc);
> +		struct drm_crtc *crtc);
>   
>   /**
>    * Get hw resources of the given type that are assigned to this encoder.
>    */
>   int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> -	struct dpu_global_state *global_state, uint32_t enc_id,
> +	struct dpu_global_state *global_state, struct drm_crtc *crtc,
>   	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
>   
>   /**

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
  2023-05-18 23:46   ` Abhinav Kumar
@ 2023-05-19  1:50     ` Dmitry Baryshkov
  2023-05-22 22:22       ` [Freedreno] " Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-19  1:50 UTC (permalink / raw)
  To: Abhinav Kumar, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

On 19/05/2023 02:46, Abhinav Kumar wrote:
> 
> 
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>> Up to now the driver has been using encoder to allocate hardware
>> resources. Switch it to use CRTC id in preparation for the next step.
>>
> 
> This decision to use encoder id instead of CRTC has been there 
> downstream for quite sometime. So most of the delay in reviewing this 
> series was trying to understand why we had this in the first place and 
> who knew that story.
> 
> You are right that from the perspective of clone mode mapping resources 
> to CRTC is correct but using encoder id is what has been working so far 
> without too much difficulty with a little more management  But another 
> use-case can get simplified with this.

Thank you for the historical perspective and for the feedback.

I think that keeping resource allocation in dpu_encoder was required 
when INTF/WB themselves were allocated through the RM. However as 
INTF/WB blocks are now allocated in a static way, it doesn't make so 
much sense anymore.

> 
> There is another angle to this. There are hardware blocks which can do 
> writeback and the physical display concurrently. We call it concurrent 
> writeback or CWB. This is present even on some of the chipsets already 
> supported upstream.
> 
> Now, lets say we start a concurrent writeback session , in todays code 
> we will allocate the resources with the encoder id of the writeback's 
> encoder and the other physical display's encoder.
> 
> When the session stops, we can just deallocate the resources of the 
> writeback encoder without touching the other encoder. So it will become 
> easier to just free up the resources mapped to the encoder.

I have not looked into CWB programming. However from your description it 
would be as easy to do a full reallocation of the pipeline as just 
dropping the CWB/extra encoder. In fact this is what the driver was 
doing: in case of a modeset, drop all old resources and allocate full 
set of resources.

> With clone mode implemented with CRTC id to map resources, we will have 
> to probably do some extra book-keeping to handle concurrent writeback.

Probably not much. We'd have to describe the topology/requirements and 
then pass that to RM. I have been waiting for this patchset (and up to 
some point the DSC/ctl) to be reviewed before finalizing/submitting the 
patches that rework the CTL interface to use this kind of data structure.

> Thats the use-case which gets impacted with this but for others, there 
> shouldnt be a major impact from what we see.
> 
> That being said, what benefit are you seeing from making that change now 
> for this series? Why is it specifically needed for virtual planes?
> 
> I see in the commit text that you have mentioned this is in preparation 
> for next step and next step talks about clone mode. But clone mode is 
> not there yet. So why this change now?

There were several items that triggered this review.

First thing first. Current design allocates resources from 
dpu_encoder_virt_atomic_check(), then in 
dpu_encoder_virt_atomic_mode_set() the driver has to poke manually in 
the cstate and fill CTL and LM. This kept on bugging me for some time. 
The encoder should not be poking into the CRTC state.

Then came the virtual planes. I think you'd agree that for the virtual 
planes we assign SSPPs to the CRTCs. My initial design kept enc_id for 
all the resources except the SSPP blocks (which were allocated per 
crtc_id). This was not perfect from the symmetry point of view.

Above all, filling the cstate in mode_set was too late for atomic_check 
to look into allocated LM to see if it supports MIXER_SOURCESPLIT or 
not. See dpu_plane_atomic_check().

I started by moving the cstate filling from the 
dpu_encoder_virt_atomic_mode_set() to dpu_encoder_virt_atomic_check(). 
And then it just became natural to turn it to be CRTC-centric code. The 
encoder doesn't have to peek into CRTC state. CRTC/plane do not have to 
delay the checks becasuse the necessary data is provided by the other 
party at a later point.

> Resource allocation is centered around LMs for the blocks we have seen 
> so far like LM, SSPP  but  ....

And LM is a CRTC.

> DSC is already an exception because in earlier chipsets we saw that PP 
> and DSC go together and cannot be muxed but later on that changed.
> 
> Now, I have explained this case but I am not getting why we need to make 
> the change for this series. Is it absolutely necessary?

Strictly, we don't. I can work around all the deficiencies of the 
current code. But it is more natural to do it now rather than later.

> 
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  16 +--
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  10 +-
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 119 ++++++++++----------
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  15 ++-
>>   4 files changed, 77 insertions(+), 83 deletions(-)


[trimmed the patch contents, it is not relevant to this discussion]

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
  2023-05-19  1:50     ` Dmitry Baryshkov
@ 2023-05-22 22:22       ` Abhinav Kumar
  2023-05-23  7:25         ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-22 22:22 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: freedreno, linux-arm-msm, Bjorn Andersson, dri-devel,
	Stephen Boyd, Daniel Vetter, David Airlie

Sorry for the delay, other topics delayed my response on this one.

On 5/18/2023 6:50 PM, Dmitry Baryshkov wrote:
> On 19/05/2023 02:46, Abhinav Kumar wrote:
>>
>>
>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>> Up to now the driver has been using encoder to allocate hardware
>>> resources. Switch it to use CRTC id in preparation for the next step.
>>>
>>
>> This decision to use encoder id instead of CRTC has been there 
>> downstream for quite sometime. So most of the delay in reviewing this 
>> series was trying to understand why we had this in the first place and 
>> who knew that story.
>>
>> You are right that from the perspective of clone mode mapping 
>> resources to CRTC is correct but using encoder id is what has been 
>> working so far without too much difficulty with a little more 
>> management  But another use-case can get simplified with this.
> 
> Thank you for the historical perspective and for the feedback.
> 
> I think that keeping resource allocation in dpu_encoder was required 
> when INTF/WB themselves were allocated through the RM. However as 
> INTF/WB blocks are now allocated in a static way, it doesn't make so 
> much sense anymore.
> 

No, whether intf/wb block themselves are allocated through RM or not did 
not really go into this. It was just about considering where all 
hardware blocks make sense to be mapped : crtc or encoder. At the end, 
considering the dsc, cwb and some more blocks encoder id was used.

>>
>> There is another angle to this. There are hardware blocks which can do 
>> writeback and the physical display concurrently. We call it concurrent 
>> writeback or CWB. This is present even on some of the chipsets already 
>> supported upstream.
>>
>> Now, lets say we start a concurrent writeback session , in todays code 
>> we will allocate the resources with the encoder id of the writeback's 
>> encoder and the other physical display's encoder.
>>
>> When the session stops, we can just deallocate the resources of the 
>> writeback encoder without touching the other encoder. So it will 
>> become easier to just free up the resources mapped to the encoder.
> 
> I have not looked into CWB programming. However from your description it 
> would be as easy to do a full reallocation of the pipeline as just 
> dropping the CWB/extra encoder. In fact this is what the driver was 
> doing: in case of a modeset, drop all old resources and allocate full 
> set of resources.
> 

Correct and the reason it was able to seamlessly drop all the old 
resources was because of the encoder_id mapping, for the cwb use-case 
using crtc id will not be so seamless to release the resources.

>> With clone mode implemented with CRTC id to map resources, we will 
>> have to probably do some extra book-keeping to handle concurrent 
>> writeback.
> 
> Probably not much. We'd have to describe the topology/requirements and 
> then pass that to RM. I have been waiting for this patchset (and up to 
> some point the DSC/ctl) to be reviewed before finalizing/submitting the 
> patches that rework the CTL interface to use this kind of data structure.
> 

There is some effort there from what I can see in the cwb case. I am 
unable to visualize how your rework will help that case. If you want to 
move this mapping to crtc id to that series to convince us how, then it 
is a better fit for that series.

>> Thats the use-case which gets impacted with this but for others, there 
>> shouldnt be a major impact from what we see.
>>
>> That being said, what benefit are you seeing from making that change 
>> now for this series? Why is it specifically needed for virtual planes?
>>
>> I see in the commit text that you have mentioned this is in 
>> preparation for next step and next step talks about clone mode. But 
>> clone mode is not there yet. So why this change now?
> 
> There were several items that triggered this review.
> 
> First thing first. Current design allocates resources from 
> dpu_encoder_virt_atomic_check(), then in 
> dpu_encoder_virt_atomic_mode_set() the driver has to poke manually in 
> the cstate and fill CTL and LM. This kept on bugging me for some time. 
> The encoder should not be poking into the CRTC state.
> 

Interesting point, but the DRM documentation seems to allow that and I 
think now thats one of the positives to have things in encoder's atomic 
check.

803 	 * This callback is used to validate encoder state for atomic drivers.
804 	 * Since the encoder is the object connecting the CRTC and connector it
805 	 * gets passed both states, to be able to validate interactions and
806 	 * update the CRTC to match what the encoder needs for the requested
807 	 * connector.
808 	 *

Encoder is the place where we have both the crtc and the connector state 
being passed down to. the crtc's atomic check doesnt have the states of 
encoder. So it just seems the encoder's atomic check is more centralized 
for the entire pipeline.

> Then came the virtual planes. I think you'd agree that for the virtual 
> planes we assign SSPPs to the CRTCs. My initial design kept enc_id for 
> all the resources except the SSPP blocks (which were allocated per 
> crtc_id). This was not perfect from the symmetry point of view.
> 

Yes for SSPPs, since they are connected to LMs and LM is mapped to CRTC 
yes its right that it will be better of to map to CRTC , only if we 
think about these two blocks in isolation. But if I would think that if 
we want to validate the pipeline encoder is more central.

> Above all, filling the cstate in mode_set was too late for atomic_check 
> to look into allocated LM to see if it supports MIXER_SOURCESPLIT or 
> not. See dpu_plane_atomic_check().
> 
> I started by moving the cstate filling from the 
> dpu_encoder_virt_atomic_mode_set() to dpu_encoder_virt_atomic_check(). 
> And then it just became natural to turn it to be CRTC-centric code. The 
> encoder doesn't have to peek into CRTC state. CRTC/plane do not have to 
> delay the checks becasuse the necessary data is provided by the other 
> party at a later point.
> 

I agree that moving from mode_set() to atomic_check() for the cstate had 
to be done. But like I wrote encoder being passed a crtc state is 
exactly for this purpose as its central to crtc and connector.

>> Resource allocation is centered around LMs for the blocks we have seen 
>> so far like LM, SSPP  but  ....
> 
> And LM is a CRTC.
> 
>> DSC is already an exception because in earlier chipsets we saw that PP 
>> and DSC go together and cannot be muxed but later on that changed.
>>
>> Now, I have explained this case but I am not getting why we need to 
>> make the change for this series. Is it absolutely necessary?
> 
> Strictly, we don't. I can work around all the deficiencies of the 
> current code. But it is more natural to do it now rather than later.
> 

Overall, like I wrote in my last response, I am not against the idea but 
from your reasoning so far and from the responses i have given above, I 
do not think that this series demands this change necessarily. I think 
without this change, the virtual plane series itself is pretty small to 
review and will be an easier task to land that first. We should deal 
with it on a need basis rather than just deciding to use virtual planes 
to make this design change.

>>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  16 +--
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  10 +-
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 119 ++++++++++----------
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  15 ++-
>>>   4 files changed, 77 insertions(+), 83 deletions(-)
> 
> 
> [trimmed the patch contents, it is not relevant to this discussion]
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
  2023-05-22 22:22       ` [Freedreno] " Abhinav Kumar
@ 2023-05-23  7:25         ` Dmitry Baryshkov
  0 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-23  7:25 UTC (permalink / raw)
  To: Abhinav Kumar, Rob Clark, Sean Paul
  Cc: freedreno, linux-arm-msm, Bjorn Andersson, dri-devel,
	Stephen Boyd, Daniel Vetter, David Airlie

On 23/05/2023 01:22, Abhinav Kumar wrote:
> Sorry for the delay, other topics delayed my response on this one.
> 
> On 5/18/2023 6:50 PM, Dmitry Baryshkov wrote:
>> On 19/05/2023 02:46, Abhinav Kumar wrote:
>>>
>>>
>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>> Up to now the driver has been using encoder to allocate hardware
>>>> resources. Switch it to use CRTC id in preparation for the next step.
>>>>
>>>
>>> This decision to use encoder id instead of CRTC has been there 
>>> downstream for quite sometime. So most of the delay in reviewing this 
>>> series was trying to understand why we had this in the first place 
>>> and who knew that story.
>>>
>>> You are right that from the perspective of clone mode mapping 
>>> resources to CRTC is correct but using encoder id is what has been 
>>> working so far without too much difficulty with a little more 
>>> management  But another use-case can get simplified with this.
>>
>> Thank you for the historical perspective and for the feedback.
>>
>> I think that keeping resource allocation in dpu_encoder was required 
>> when INTF/WB themselves were allocated through the RM. However as 
>> INTF/WB blocks are now allocated in a static way, it doesn't make so 
>> much sense anymore.
>>
> 
> No, whether intf/wb block themselves are allocated through RM or not did 
> not really go into this. It was just about considering where all 
> hardware blocks make sense to be mapped : crtc or encoder. At the end, 
> considering the dsc, cwb and some more blocks encoder id was used.

Ack, thanks for the historical perspective. Didn't know that.

> 
>>>
>>> There is another angle to this. There are hardware blocks which can 
>>> do writeback and the physical display concurrently. We call it 
>>> concurrent writeback or CWB. This is present even on some of the 
>>> chipsets already supported upstream.
>>>
>>> Now, lets say we start a concurrent writeback session , in todays 
>>> code we will allocate the resources with the encoder id of the 
>>> writeback's encoder and the other physical display's encoder.
>>>
>>> When the session stops, we can just deallocate the resources of the 
>>> writeback encoder without touching the other encoder. So it will 
>>> become easier to just free up the resources mapped to the encoder.
>>
>> I have not looked into CWB programming. However from your description 
>> it would be as easy to do a full reallocation of the pipeline as just 
>> dropping the CWB/extra encoder. In fact this is what the driver was 
>> doing: in case of a modeset, drop all old resources and allocate full 
>> set of resources.
>>
> 
> Correct and the reason it was able to seamlessly drop all the old 
> resources was because of the encoder_id mapping, for the cwb use-case 
> using crtc id will not be so seamless to release the resources.

Can you please tell, why? At all the times we can drop all resources and 
then reacquire them. In the worst case it results in wasted time, but 
there should no be troubles doing this acquisition.

Also see below.	

>>> With clone mode implemented with CRTC id to map resources, we will 
>>> have to probably do some extra book-keeping to handle concurrent 
>>> writeback.
>>
>> Probably not much. We'd have to describe the topology/requirements and 
>> then pass that to RM. I have been waiting for this patchset (and up to 
>> some point the DSC/ctl) to be reviewed before finalizing/submitting 
>> the patches that rework the CTL interface to use this kind of data 
>> structure.
>>
> 
> There is some effort there from what I can see in the cwb case. I am 
> unable to visualize how your rework will help that case. If you want to 
> move this mapping to crtc id to that series to convince us how, then it 
> is a better fit for that series.

-ENOTFINISHED. Anyway, I think it is separate from the topology changes too.

> 
>>> Thats the use-case which gets impacted with this but for others, 
>>> there shouldnt be a major impact from what we see.
>>>
>>> That being said, what benefit are you seeing from making that change 
>>> now for this series? Why is it specifically needed for virtual planes?
>>>
>>> I see in the commit text that you have mentioned this is in 
>>> preparation for next step and next step talks about clone mode. But 
>>> clone mode is not there yet. So why this change now?
>>
>> There were several items that triggered this review.
>>
>> First thing first. Current design allocates resources from 
>> dpu_encoder_virt_atomic_check(), then in 
>> dpu_encoder_virt_atomic_mode_set() the driver has to poke manually in 
>> the cstate and fill CTL and LM. This kept on bugging me for some time. 
>> The encoder should not be poking into the CRTC state.
>>
> 
> Interesting point, but the DRM documentation seems to allow that and I 
> think now thats one of the positives to have things in encoder's atomic 
> check.
> 
> 803      * This callback is used to validate encoder state for atomic 
> drivers.
> 804      * Since the encoder is the object connecting the CRTC and 
> connector it
> 805      * gets passed both states, to be able to validate interactions and
> 806      * update the CRTC to match what the encoder needs for the 
> requested
> 807      * connector.
> 808      *
> 
> Encoder is the place where we have both the crtc and the connector state 
> being passed down to. the crtc's atomic check doesnt have the states of 
> encoder. So it just seems the encoder's atomic check is more centralized 
> for the entire pipeline.

First. Once [1] lands, the driver will not use connector state.

Regarding the encoder vs crtc state. Currently the CRTC's atomic_check() 
code can not influence resource allocation. Encoder's atomic_check() 
happens earlier. This results in code like msm_atomic_check().

If display resources are allocated from CRTC's atomic_check(), the 
mentioned function can go away by moving this check to 
dpu_crtc_atomic_check().

Last, but not least, let me point our the text you have quoted: "... 
update the CRTC to match what the encoder needs for the requested 
connector.". In our case the driver doesn't update the CRTC state 
according to the needs of the requested connector. Instead, it updates 
the CRTC state for what is needed for the CRTC. It is the CRTC itself 
who needs one or two LMs, not the connector.

[1] https://patchwork.freedesktop.org/series/117979/

> 
>> Then came the virtual planes. I think you'd agree that for the virtual 
>> planes we assign SSPPs to the CRTCs. My initial design kept enc_id for 
>> all the resources except the SSPP blocks (which were allocated per 
>> crtc_id). This was not perfect from the symmetry point of view.
>>
> 
> Yes for SSPPs, since they are connected to LMs and LM is mapped to CRTC 
> yes its right that it will be better of to map to CRTC , only if we 
> think about these two blocks in isolation. But if I would think that if 
> we want to validate the pipeline encoder is more central.

I don't agree here. Especially if we have cloned output (=CWB?) support.
There will be two encoders/bridge-chains/connectors being driven by a 
single CRTC. CRTC is the spider in the centre of the web with the 
threads going around to the connectors.

And this is pretty much supported by the fact that the encoder doesn't 
have its own atomic_state. IIRC, quite frequently encoder is just a shim 
between the CRTC and bridge-chain/connector.

>> Above all, filling the cstate in mode_set was too late for 
>> atomic_check to look into allocated LM to see if it supports 
>> MIXER_SOURCESPLIT or not. See dpu_plane_atomic_check().
>>
>> I started by moving the cstate filling from the 
>> dpu_encoder_virt_atomic_mode_set() to dpu_encoder_virt_atomic_check(). 
>> And then it just became natural to turn it to be CRTC-centric code. 
>> The encoder doesn't have to peek into CRTC state. CRTC/plane do not 
>> have to delay the checks becasuse the necessary data is provided by 
>> the other party at a later point.
>>
> 
> I agree that moving from mode_set() to atomic_check() for the cstate had 
> to be done. But like I wrote encoder being passed a crtc state is 
> exactly for this purpose as its central to crtc and connector.
> 
>>> Resource allocation is centered around LMs for the blocks we have 
>>> seen so far like LM, SSPP  but  ....
>>
>> And LM is a CRTC.
>>
>>> DSC is already an exception because in earlier chipsets we saw that 
>>> PP and DSC go together and cannot be muxed but later on that changed.
>>>
>>> Now, I have explained this case but I am not getting why we need to 
>>> make the change for this series. Is it absolutely necessary?
>>
>> Strictly, we don't. I can work around all the deficiencies of the 
>> current code. But it is more natural to do it now rather than later.
>>
> 
> Overall, like I wrote in my last response, I am not against the idea but 
> from your reasoning so far and from the responses i have given above, I 
> do not think that this series demands this change necessarily. I think 
> without this change, the virtual plane series itself is pretty small to 
> review and will be an easier task to land that first. We should deal 
> with it on a need basis rather than just deciding to use virtual planes 
> to make this design change.

To save time on arguing, I'll take a look at rebasing patches. Please 
continue review with patches 1,2,9-13.

> 
>>>
>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>> ---
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  16 +--
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  10 +-
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 119 
>>>> ++++++++++----------
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  15 ++-
>>>>   4 files changed, 77 insertions(+), 83 deletions(-)
>>
>>
>> [trimmed the patch contents, it is not relevant to this discussion]
>>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check
  2023-03-21  1:18 ` [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check Dmitry Baryshkov
@ 2023-05-24 22:46   ` Abhinav Kumar
  2023-05-24 23:04     ` [Freedreno] " Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-24 22:46 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> In preparation to virtualized planes support, move pstate->pipe
> initialization from dpu_plane_reset() to dpu_plane_atomic_check(). In
> case of virtual planes the plane's pipe will not be known up to the
> point of atomic_check() callback.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---

Will legacy paths be broken with this? So lets say there is no 
atomic_check we will not have a valid sspp anymore.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check
  2023-05-24 22:46   ` Abhinav Kumar
@ 2023-05-24 23:04     ` Abhinav Kumar
  2023-05-25  1:40       ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-24 23:04 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: freedreno, linux-arm-msm, Bjorn Andersson, dri-devel,
	Stephen Boyd, Daniel Vetter, David Airlie



On 5/24/2023 3:46 PM, Abhinav Kumar wrote:
> 
> 
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>> In preparation to virtualized planes support, move pstate->pipe
>> initialization from dpu_plane_reset() to dpu_plane_atomic_check(). In
>> case of virtual planes the plane's pipe will not be known up to the
>> point of atomic_check() callback.
>>
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> ---
> 
> Will legacy paths be broken with this? So lets say there is no 
> atomic_check we will not have a valid sspp anymore.

I think it should still work, even if goes through the modeset crtc, it 
should still call drm_atomic_commit() internally which should have the 
call to atomic_check, once you confirm this , i can ack this particular 
change.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-03-21  1:18 ` [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps Dmitry Baryshkov
@ 2023-05-24 23:16   ` Abhinav Kumar
  2023-05-25  1:47     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-24 23:16 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> As we are going to add virtual planes, add the list of supported formats
> to the hw catalog entry. It will be used to setup universal planes, with
> later selecting a pipe depending on whether the YUV format is used for
> the framebuffer.
> 

If your usage of format_list is going to be internal to dpu_plane.c, I 
can think of another idea for this change.

This essentially translates to if (num_vig >= 1)

If we can just have a small helper to detect that from the catalog can 
we use that instead of adding formats to the dpu caps?

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 +++++++++++++++++++
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
>   2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> index 212d546b6c5d..2d6944a9679a 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>   	.max_hdeci_exp = MAX_HORZ_DECIMATION,
>   	.max_vdeci_exp = MAX_VERT_DECIMATION,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps qcm2290_dpu_caps = {
> @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
>   	.has_idle_pc = true,
>   	.max_linewidth = 2160,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sdm845_dpu_caps = {
> @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>   	.max_hdeci_exp = MAX_HORZ_DECIMATION,
>   	.max_vdeci_exp = MAX_VERT_DECIMATION,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sc7180_dpu_caps = {
> @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
>   	.has_idle_pc = true,
>   	.max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sm6115_dpu_caps = {
> @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
>   	.has_idle_pc = true,
>   	.max_linewidth = 2160,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sm8150_dpu_caps = {
> @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>   	.max_hdeci_exp = MAX_HORZ_DECIMATION,
>   	.max_vdeci_exp = MAX_VERT_DECIMATION,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sc8180x_dpu_caps = {
> @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>   	.max_hdeci_exp = MAX_HORZ_DECIMATION,
>   	.max_vdeci_exp = MAX_VERT_DECIMATION,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sc8280xp_dpu_caps = {
> @@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
>   	.has_3d_merge = true,
>   	.max_linewidth = 5120,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sm8250_dpu_caps = {
> @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
>   	.has_3d_merge = true,
>   	.max_linewidth = 900,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sm8350_dpu_caps = {
> @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
>   	.has_3d_merge = true,
>   	.max_linewidth = 4096,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sm8450_dpu_caps = {
> @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
>   	.has_3d_merge = true,
>   	.max_linewidth = 5120,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sm8550_dpu_caps = {
> @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
>   	.has_3d_merge = true,
>   	.max_linewidth = 5120,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_caps sc7280_dpu_caps = {
> @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
>   	.has_idle_pc = true,
>   	.max_linewidth = 2400,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> +	.format_list = plane_formats_yuv,
> +	.num_formats = ARRAY_SIZE(plane_formats_yuv),
>   };
>   
>   static const struct dpu_mdp_cfg msm8998_mdp[] = {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> index 89b372cdca92..4847aae78db2 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
>    * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
>    * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
>    * @max_vdeci_exp      max vertical decimation supported (max is 2^value)
> + * @format_list: Pointer to list of supported formats
> + * @num_formats: Number of supported formats
>    */
>   struct dpu_caps {
>   	u32 max_mixer_width;
> @@ -419,6 +421,8 @@ struct dpu_caps {
>   	u32 pixel_ram_size;
>   	u32 max_hdeci_exp;
>   	u32 max_vdeci_exp;
> +	const u32 *format_list;
> +	u32 num_formats;
>   };
>   
>   /**

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps
  2023-03-21  1:18 ` [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps Dmitry Baryshkov
@ 2023-05-24 23:20   ` Abhinav Kumar
  2023-05-25  1:47     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-05-24 23:20 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> We need to know if the platform supports inline rotation on any of the
> SSPP blocks or not. Add this information to struct dpu_caps in a form of
> the boolean field has_inline_rot.
> 

So even for this one, will a helper to detect it from the list of sspps 
be better?

We are now duplicating information from sspp to dpu caps for convenience 
and nothing wrong with it if the helper will get called like every 
atomic check .

But looking at the next patch, it seems we use this information only 
once during dpu_plane_init(), so why not add a helper to find this out?

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 ++
>   2 files changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> index 2d6944a9679a..33527ec7c938 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> @@ -489,6 +489,7 @@ static const struct dpu_caps sc7280_dpu_caps = {
>   	.ubwc_version = DPU_HW_UBWC_VER_30,
>   	.has_dim_layer = true,
>   	.has_idle_pc = true,
> +	.has_inline_rot = true,
>   	.max_linewidth = 2400,
>   	.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>   	.format_list = plane_formats_yuv,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> index 4847aae78db2..cc64fb2e815f 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -400,6 +400,7 @@ struct dpu_rotation_cfg {
>    * @has_dim_layer      dim layer feature status
>    * @has_idle_pc        indicate if idle power collapse feature is supported
>    * @has_3d_merge       indicate if 3D merge is supported
> + * @has_inline_rot     indicate if inline rotation is supported
>    * @max_linewidth      max linewidth for sspp
>    * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
>    * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
> @@ -416,6 +417,7 @@ struct dpu_caps {
>   	bool has_dim_layer;
>   	bool has_idle_pc;
>   	bool has_3d_merge;
> +	bool has_inline_rot;
>   	/* SSPP limits */
>   	u32 max_linewidth;
>   	u32 pixel_ram_size;

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check
  2023-05-24 23:04     ` [Freedreno] " Abhinav Kumar
@ 2023-05-25  1:40       ` Dmitry Baryshkov
  2023-06-06 20:27         ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-25  1:40 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, freedreno, linux-arm-msm, Bjorn Andersson,
	dri-devel, Stephen Boyd, Daniel Vetter, David Airlie

On Thu, 25 May 2023 at 02:04, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 5/24/2023 3:46 PM, Abhinav Kumar wrote:
> >
> >
> > On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> >> In preparation to virtualized planes support, move pstate->pipe
> >> initialization from dpu_plane_reset() to dpu_plane_atomic_check(). In
> >> case of virtual planes the plane's pipe will not be known up to the
> >> point of atomic_check() callback.
> >>
> >> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >> ---
> >
> > Will legacy paths be broken with this? So lets say there is no
> > atomic_check we will not have a valid sspp anymore.
>
> I think it should still work, even if goes through the modeset crtc, it
> should still call drm_atomic_commit() internally which should have the
> call to atomic_check, once you confirm this , i can ack this particular
> change.

Can you please describe the scenario you have in mind? If I got you
correctly, you were asking about the non-commit IOCTLs. Because of the
atomic helpers being used (e.g. drm_atomic_helper_set_config()), they
will also result in a call to drm_atomic_commit(), which invokes
drm_atomic_check_only().

-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-05-24 23:16   ` Abhinav Kumar
@ 2023-05-25  1:47     ` Dmitry Baryshkov
  2023-06-06 21:14       ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-25  1:47 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On Thu, 25 May 2023 at 02:16, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> > As we are going to add virtual planes, add the list of supported formats
> > to the hw catalog entry. It will be used to setup universal planes, with
> > later selecting a pipe depending on whether the YUV format is used for
> > the framebuffer.
> >
>
> If your usage of format_list is going to be internal to dpu_plane.c, I
> can think of another idea for this change.
>
> This essentially translates to if (num_vig >= 1)
>
> If we can just have a small helper to detect that from the catalog can
> we use that instead of adding formats to the dpu caps?

I'd prefer to be explicit here. The list of supported formats might
vary between generations, might it not? Also we don't have a case of
the devices not having VIG planes. Even the qcm2290 (which doesn't
have CSC) lists YUV as supported.

Note: I think at some point we should have a closer look at the list
of supported formats and crosscheck that we do not have either
unsupported formats being listed, or missing formats which are not
listed as supported.

>
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > ---
> >   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 +++++++++++++++++++
> >   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
> >   2 files changed, 30 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> > index 212d546b6c5d..2d6944a9679a 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> > @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> >       .max_hdeci_exp = MAX_HORZ_DECIMATION,
> >       .max_vdeci_exp = MAX_VERT_DECIMATION,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps qcm2290_dpu_caps = {
> > @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
> >       .has_idle_pc = true,
> >       .max_linewidth = 2160,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sdm845_dpu_caps = {
> > @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> >       .max_hdeci_exp = MAX_HORZ_DECIMATION,
> >       .max_vdeci_exp = MAX_VERT_DECIMATION,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sc7180_dpu_caps = {
> > @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
> >       .has_idle_pc = true,
> >       .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sm6115_dpu_caps = {
> > @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
> >       .has_idle_pc = true,
> >       .max_linewidth = 2160,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sm8150_dpu_caps = {
> > @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> >       .max_hdeci_exp = MAX_HORZ_DECIMATION,
> >       .max_vdeci_exp = MAX_VERT_DECIMATION,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sc8180x_dpu_caps = {
> > @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> >       .max_hdeci_exp = MAX_HORZ_DECIMATION,
> >       .max_vdeci_exp = MAX_VERT_DECIMATION,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sc8280xp_dpu_caps = {
> > @@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
> >       .has_3d_merge = true,
> >       .max_linewidth = 5120,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sm8250_dpu_caps = {
> > @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
> >       .has_3d_merge = true,
> >       .max_linewidth = 900,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sm8350_dpu_caps = {
> > @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
> >       .has_3d_merge = true,
> >       .max_linewidth = 4096,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sm8450_dpu_caps = {
> > @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
> >       .has_3d_merge = true,
> >       .max_linewidth = 5120,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sm8550_dpu_caps = {
> > @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
> >       .has_3d_merge = true,
> >       .max_linewidth = 5120,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_caps sc7280_dpu_caps = {
> > @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
> >       .has_idle_pc = true,
> >       .max_linewidth = 2400,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> > +     .format_list = plane_formats_yuv,
> > +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
> >   };
> >
> >   static const struct dpu_mdp_cfg msm8998_mdp[] = {
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> > index 89b372cdca92..4847aae78db2 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> > @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
> >    * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
> >    * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
> >    * @max_vdeci_exp      max vertical decimation supported (max is 2^value)
> > + * @format_list: Pointer to list of supported formats
> > + * @num_formats: Number of supported formats
> >    */
> >   struct dpu_caps {
> >       u32 max_mixer_width;
> > @@ -419,6 +421,8 @@ struct dpu_caps {
> >       u32 pixel_ram_size;
> >       u32 max_hdeci_exp;
> >       u32 max_vdeci_exp;
> > +     const u32 *format_list;
> > +     u32 num_formats;
> >   };
> >
> >   /**



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps
  2023-05-24 23:20   ` Abhinav Kumar
@ 2023-05-25  1:47     ` Dmitry Baryshkov
  0 siblings, 0 replies; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-05-25  1:47 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On Thu, 25 May 2023 at 02:20, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> > We need to know if the platform supports inline rotation on any of the
> > SSPP blocks or not. Add this information to struct dpu_caps in a form of
> > the boolean field has_inline_rot.
> >
>
> So even for this one, will a helper to detect it from the list of sspps
> be better?
>
> We are now duplicating information from sspp to dpu caps for convenience
> and nothing wrong with it if the helper will get called like every
> atomic check .
>
> But looking at the next patch, it seems we use this information only
> once during dpu_plane_init(), so why not add a helper to find this out?

Sure, why not.

>
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 2 ++
> >   2 files changed, 3 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> > index 2d6944a9679a..33527ec7c938 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> > @@ -489,6 +489,7 @@ static const struct dpu_caps sc7280_dpu_caps = {
> >       .ubwc_version = DPU_HW_UBWC_VER_30,
> >       .has_dim_layer = true,
> >       .has_idle_pc = true,
> > +     .has_inline_rot = true,
> >       .max_linewidth = 2400,
> >       .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
> >       .format_list = plane_formats_yuv,
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> > index 4847aae78db2..cc64fb2e815f 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> > @@ -400,6 +400,7 @@ struct dpu_rotation_cfg {
> >    * @has_dim_layer      dim layer feature status
> >    * @has_idle_pc        indicate if idle power collapse feature is supported
> >    * @has_3d_merge       indicate if 3D merge is supported
> > + * @has_inline_rot     indicate if inline rotation is supported
> >    * @max_linewidth      max linewidth for sspp
> >    * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
> >    * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
> > @@ -416,6 +417,7 @@ struct dpu_caps {
> >       bool has_dim_layer;
> >       bool has_idle_pc;
> >       bool has_3d_merge;
> > +     bool has_inline_rot;
> >       /* SSPP limits */
> >       u32 max_linewidth;
> >       u32 pixel_ram_size;



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt
  2023-03-21  1:18 ` [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt Dmitry Baryshkov
@ 2023-06-06 20:25   ` Abhinav Kumar
  2023-06-06 20:29     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 20:25 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: freedreno, linux-arm-msm, Bjorn Andersson, dri-devel,
	Stephen Boyd, Daniel Vetter, David Airlie



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> Remove historical fields intfs_swapped and topology fields from struct
> dpu_encoder_virt and also remove even more historical docs.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ----------
>   1 file changed, 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 28729c77364f..4ee708264f3b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -130,18 +130,12 @@ enum dpu_enc_rc_states {
>    *			pingpong blocks can be different than num_phys_encs.
>    * @hw_dsc:		Handle to the DSC blocks used for the display.
>    * @dsc_mask:		Bitmask of used DSC blocks.
> - * @intfs_swapped:	Whether or not the phys_enc interfaces have been swapped
> - *			for partial update right-only cases, such as pingpong
> - *			split where virtual pingpong does not generate IRQs
>    * @crtc:		Pointer to the currently assigned crtc. Normally you
>    *			would use crtc->state->encoder_mask to determine the
>    *			link between encoder/crtc. However in this case we need
>    *			to track crtc in the disable() hook which is called
>    *			_after_ encoder_mask is cleared.
>    * @connector:		If a mode is set, cached pointer to the active connector
> - * @crtc_kickoff_cb:		Callback into CRTC that will flush & start
> - *				all CTL paths
> - * @crtc_kickoff_cb_data:	Opaque user data given to crtc_kickoff_cb

no concerns with the above 3

>    * @enc_lock:			Lock around physical encoder
>    *				create/destroy/enable/disable
>    * @frame_busy_mask:		Bitmask tracking which phys_enc we are still
> @@ -160,7 +154,6 @@ enum dpu_enc_rc_states {
>    * @delayed_off_work:		delayed worker to schedule disabling of
>    *				clks and resources after IDLE_TIMEOUT time.
>    * @vsync_event_work:		worker to handle vsync event for autorefresh
> - * @topology:                   topology of the display

As we are still going to go ahead with encoder based allocation for now, 
we should keep this topology and start using it for DP DSC's 1:1:1 topology.

>    * @idle_timeout:		idle timeout duration in milliseconds
>    * @wide_bus_en:		wide bus is enabled on this interface
>    * @dsc:			drm_dsc_config pointer, for DSC-enabled encoders
> @@ -180,8 +173,6 @@ struct dpu_encoder_virt {
>   
>   	unsigned int dsc_mask;
>   
> -	bool intfs_swapped;
> -
>   	struct drm_crtc *crtc;
>   	struct drm_connector *connector;
>   
> @@ -201,7 +192,6 @@ struct dpu_encoder_virt {
>   	enum dpu_enc_rc_states rc_state;
>   	struct delayed_work delayed_off_work;
>   	struct kthread_work vsync_event_work;
> -	struct msm_display_topology topology;
>   
>   	u32 idle_timeout;
>   

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check
  2023-05-25  1:40       ` Dmitry Baryshkov
@ 2023-06-06 20:27         ` Abhinav Kumar
  0 siblings, 0 replies; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 20:27 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Sean Paul, Bjorn Andersson, dri-devel, Stephen Boyd,
	linux-arm-msm, freedreno



On 5/24/2023 6:40 PM, Dmitry Baryshkov wrote:
> On Thu, 25 May 2023 at 02:04, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 5/24/2023 3:46 PM, Abhinav Kumar wrote:
>>>
>>>
>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>> In preparation to virtualized planes support, move pstate->pipe
>>>> initialization from dpu_plane_reset() to dpu_plane_atomic_check(). In
>>>> case of virtual planes the plane's pipe will not be known up to the
>>>> point of atomic_check() callback.
>>>>
>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>> ---
>>>
>>> Will legacy paths be broken with this? So lets say there is no
>>> atomic_check we will not have a valid sspp anymore.
>>
>> I think it should still work, even if goes through the modeset crtc, it
>> should still call drm_atomic_commit() internally which should have the
>> call to atomic_check, once you confirm this , i can ack this particular
>> change.
> 
> Can you please describe the scenario you have in mind? If I got you
> correctly, you were asking about the non-commit IOCTLs. Because of the
> atomic helpers being used (e.g. drm_atomic_helper_set_config()), they
> will also result in a call to drm_atomic_commit(), which invokes
> drm_atomic_check_only().
> 

Yes, that was pretty much the scenario I was referring to, thanks for 
confirming.


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt
  2023-06-06 20:25   ` [Freedreno] " Abhinav Kumar
@ 2023-06-06 20:29     ` Dmitry Baryshkov
  2023-06-06 20:36       ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-06 20:29 UTC (permalink / raw)
  To: Abhinav Kumar, Rob Clark, Sean Paul
  Cc: freedreno, linux-arm-msm, Bjorn Andersson, dri-devel,
	Stephen Boyd, Daniel Vetter, David Airlie

On 06/06/2023 23:25, Abhinav Kumar wrote:
> 
> 
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>> Remove historical fields intfs_swapped and topology fields from struct
>> dpu_encoder_virt and also remove even more historical docs.
>>
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ----------
>>   1 file changed, 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 28729c77364f..4ee708264f3b 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -130,18 +130,12 @@ enum dpu_enc_rc_states {
>>    *            pingpong blocks can be different than num_phys_encs.
>>    * @hw_dsc:        Handle to the DSC blocks used for the display.
>>    * @dsc_mask:        Bitmask of used DSC blocks.
>> - * @intfs_swapped:    Whether or not the phys_enc interfaces have 
>> been swapped
>> - *            for partial update right-only cases, such as pingpong
>> - *            split where virtual pingpong does not generate IRQs
>>    * @crtc:        Pointer to the currently assigned crtc. Normally you
>>    *            would use crtc->state->encoder_mask to determine the
>>    *            link between encoder/crtc. However in this case we need
>>    *            to track crtc in the disable() hook which is called
>>    *            _after_ encoder_mask is cleared.
>>    * @connector:        If a mode is set, cached pointer to the active 
>> connector
>> - * @crtc_kickoff_cb:        Callback into CRTC that will flush & start
>> - *                all CTL paths
>> - * @crtc_kickoff_cb_data:    Opaque user data given to crtc_kickoff_cb
> 
> no concerns with the above 3
> 
>>    * @enc_lock:            Lock around physical encoder
>>    *                create/destroy/enable/disable
>>    * @frame_busy_mask:        Bitmask tracking which phys_enc we are 
>> still
>> @@ -160,7 +154,6 @@ enum dpu_enc_rc_states {
>>    * @delayed_off_work:        delayed worker to schedule disabling of
>>    *                clks and resources after IDLE_TIMEOUT time.
>>    * @vsync_event_work:        worker to handle vsync event for 
>> autorefresh
>> - * @topology:                   topology of the display
> 
> As we are still going to go ahead with encoder based allocation for now, 
> we should keep this topology and start using it for DP DSC's 1:1:1 
> topology.

It is currently unused, so it can be dropped. Your patchset would have 
to reintroduce it.

And I'm still not happy about the encoder-based allocation. You 
persuaded me that it is irrelevant for the wide planes. So I'd split it 
and post the allocation patchset after the virtual-wide is fully 
reviewed (when would come that blissful moment, btw?).

> 
>>    * @idle_timeout:        idle timeout duration in milliseconds
>>    * @wide_bus_en:        wide bus is enabled on this interface
>>    * @dsc:            drm_dsc_config pointer, for DSC-enabled encoders
>> @@ -180,8 +173,6 @@ struct dpu_encoder_virt {
>>       unsigned int dsc_mask;
>> -    bool intfs_swapped;
>> -
>>       struct drm_crtc *crtc;
>>       struct drm_connector *connector;
>> @@ -201,7 +192,6 @@ struct dpu_encoder_virt {
>>       enum dpu_enc_rc_states rc_state;
>>       struct delayed_work delayed_off_work;
>>       struct kthread_work vsync_event_work;
>> -    struct msm_display_topology topology;
>>       u32 idle_timeout;

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt
  2023-06-06 20:29     ` Dmitry Baryshkov
@ 2023-06-06 20:36       ` Abhinav Kumar
  0 siblings, 0 replies; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 20:36 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: linux-arm-msm, Bjorn Andersson, dri-devel, Stephen Boyd, freedreno



On 6/6/2023 1:29 PM, Dmitry Baryshkov wrote:
> On 06/06/2023 23:25, Abhinav Kumar wrote:
>>
>>
>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>> Remove historical fields intfs_swapped and topology fields from struct
>>> dpu_encoder_virt and also remove even more historical docs.
>>>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 ----------
>>>   1 file changed, 10 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> index 28729c77364f..4ee708264f3b 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> @@ -130,18 +130,12 @@ enum dpu_enc_rc_states {
>>>    *            pingpong blocks can be different than num_phys_encs.
>>>    * @hw_dsc:        Handle to the DSC blocks used for the display.
>>>    * @dsc_mask:        Bitmask of used DSC blocks.
>>> - * @intfs_swapped:    Whether or not the phys_enc interfaces have 
>>> been swapped
>>> - *            for partial update right-only cases, such as pingpong
>>> - *            split where virtual pingpong does not generate IRQs
>>>    * @crtc:        Pointer to the currently assigned crtc. Normally you
>>>    *            would use crtc->state->encoder_mask to determine the
>>>    *            link between encoder/crtc. However in this case we need
>>>    *            to track crtc in the disable() hook which is called
>>>    *            _after_ encoder_mask is cleared.
>>>    * @connector:        If a mode is set, cached pointer to the 
>>> active connector
>>> - * @crtc_kickoff_cb:        Callback into CRTC that will flush & start
>>> - *                all CTL paths
>>> - * @crtc_kickoff_cb_data:    Opaque user data given to crtc_kickoff_cb
>>
>> no concerns with the above 3
>>
>>>    * @enc_lock:            Lock around physical encoder
>>>    *                create/destroy/enable/disable
>>>    * @frame_busy_mask:        Bitmask tracking which phys_enc we are 
>>> still
>>> @@ -160,7 +154,6 @@ enum dpu_enc_rc_states {
>>>    * @delayed_off_work:        delayed worker to schedule disabling of
>>>    *                clks and resources after IDLE_TIMEOUT time.
>>>    * @vsync_event_work:        worker to handle vsync event for 
>>> autorefresh
>>> - * @topology:                   topology of the display
>>
>> As we are still going to go ahead with encoder based allocation for 
>> now, we should keep this topology and start using it for DP DSC's 
>> 1:1:1 topology.
> 
> It is currently unused, so it can be dropped. Your patchset would have 
> to reintroduce it.
> 

Ok same old argument which I tend to always lose. We will add it back 
with DP DSC.

> And I'm still not happy about the encoder-based allocation. You 
> persuaded me that it is irrelevant for the wide planes. So I'd split it 
> and post the allocation patchset after the virtual-wide is fully 
> reviewed (when would come that blissful moment, btw?).
> 

Post the allocation with a compelling feature for us to be convinced.

The moment is happening as we speak :)

>>
>>>    * @idle_timeout:        idle timeout duration in milliseconds
>>>    * @wide_bus_en:        wide bus is enabled on this interface
>>>    * @dsc:            drm_dsc_config pointer, for DSC-enabled encoders
>>> @@ -180,8 +173,6 @@ struct dpu_encoder_virt {
>>>       unsigned int dsc_mask;
>>> -    bool intfs_swapped;
>>> -
>>>       struct drm_crtc *crtc;
>>>       struct drm_connector *connector;
>>> @@ -201,7 +192,6 @@ struct dpu_encoder_virt {
>>>       enum dpu_enc_rc_states rc_state;
>>>       struct delayed_work delayed_off_work;
>>>       struct kthread_work vsync_event_work;
>>> -    struct msm_display_topology topology;
>>>       u32 idle_timeout;
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-05-25  1:47     ` Dmitry Baryshkov
@ 2023-06-06 21:14       ` Abhinav Kumar
  2023-06-06 21:29         ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 21:14 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
> On Thu, 25 May 2023 at 02:16, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>> As we are going to add virtual planes, add the list of supported formats
>>> to the hw catalog entry. It will be used to setup universal planes, with
>>> later selecting a pipe depending on whether the YUV format is used for
>>> the framebuffer.
>>>
>>
>> If your usage of format_list is going to be internal to dpu_plane.c, I
>> can think of another idea for this change.
>>
>> This essentially translates to if (num_vig >= 1)
>>
>> If we can just have a small helper to detect that from the catalog can
>> we use that instead of adding formats to the dpu caps?
> 
> I'd prefer to be explicit here. The list of supported formats might
> vary between generations, might it not? Also we don't have a case of
> the devices not having VIG planes. Even the qcm2290 (which doesn't
> have CSC) lists YUV as supported.
> 

the list of formats is tied to the sspps the dpu generation has and the 
capabilities of those sspps.

qcm2290 is really an interesting case. It has one vig sspp but no csc 
block for that vig sspp, hence it cannot support non-RGB formats.

I have confirmed that downstream is incorrect to populate yuv formats 
for qcm2290.

I still think that having atleast one vig sspp with csc sub-blk is the 
right condition to check if we want to decide if the dpu for that 
chipset supports yuv formats. Extra csc-blk check to handle qcm2290.

Having a small helper in dpu_plane.c is good enough for that because 
with virtual planes, you only need to know "if such a plane exists and 
not which plane" and a full catalog change isnt needed IMO


> Note: I think at some point we should have a closer look at the list
> of supported formats and crosscheck that we do not have either
> unsupported formats being listed, or missing formats which are not
> listed as supported.
> 
>>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> ---
>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 +++++++++++++++++++
>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
>>>    2 files changed, 30 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>> index 212d546b6c5d..2d6944a9679a 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>> @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps qcm2290_dpu_caps = {
>>> @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
>>>        .has_idle_pc = true,
>>>        .max_linewidth = 2160,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sdm845_dpu_caps = {
>>> @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sc7180_dpu_caps = {
>>> @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
>>>        .has_idle_pc = true,
>>>        .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sm6115_dpu_caps = {
>>> @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
>>>        .has_idle_pc = true,
>>>        .max_linewidth = 2160,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sm8150_dpu_caps = {
>>> @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sc8180x_dpu_caps = {
>>> @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sc8280xp_dpu_caps = {
>>> @@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
>>>        .has_3d_merge = true,
>>>        .max_linewidth = 5120,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sm8250_dpu_caps = {
>>> @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
>>>        .has_3d_merge = true,
>>>        .max_linewidth = 900,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sm8350_dpu_caps = {
>>> @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
>>>        .has_3d_merge = true,
>>>        .max_linewidth = 4096,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sm8450_dpu_caps = {
>>> @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
>>>        .has_3d_merge = true,
>>>        .max_linewidth = 5120,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sm8550_dpu_caps = {
>>> @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
>>>        .has_3d_merge = true,
>>>        .max_linewidth = 5120,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_caps sc7280_dpu_caps = {
>>> @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
>>>        .has_idle_pc = true,
>>>        .max_linewidth = 2400,
>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>> +     .format_list = plane_formats_yuv,
>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>    };
>>>
>>>    static const struct dpu_mdp_cfg msm8998_mdp[] = {
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>> index 89b372cdca92..4847aae78db2 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>> @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
>>>     * @pixel_ram_size     size of latency hiding and de-tiling buffer in bytes
>>>     * @max_hdeci_exp      max horizontal decimation supported (max is 2^value)
>>>     * @max_vdeci_exp      max vertical decimation supported (max is 2^value)
>>> + * @format_list: Pointer to list of supported formats
>>> + * @num_formats: Number of supported formats
>>>     */
>>>    struct dpu_caps {
>>>        u32 max_mixer_width;
>>> @@ -419,6 +421,8 @@ struct dpu_caps {
>>>        u32 pixel_ram_size;
>>>        u32 max_hdeci_exp;
>>>        u32 max_vdeci_exp;
>>> +     const u32 *format_list;
>>> +     u32 num_formats;
>>>    };
>>>
>>>    /**
> 
> 
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 21:14       ` Abhinav Kumar
@ 2023-06-06 21:29         ` Dmitry Baryshkov
  2023-06-06 21:47           ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-06 21:29 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On 07/06/2023 00:14, Abhinav Kumar wrote:
> 
> 
> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>> <quic_abhinavk@quicinc.com> wrote:
>>>
>>>
>>>
>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>> As we are going to add virtual planes, add the list of supported 
>>>> formats
>>>> to the hw catalog entry. It will be used to setup universal planes, 
>>>> with
>>>> later selecting a pipe depending on whether the YUV format is used for
>>>> the framebuffer.
>>>>
>>>
>>> If your usage of format_list is going to be internal to dpu_plane.c, I
>>> can think of another idea for this change.
>>>
>>> This essentially translates to if (num_vig >= 1)
>>>
>>> If we can just have a small helper to detect that from the catalog can
>>> we use that instead of adding formats to the dpu caps?
>>
>> I'd prefer to be explicit here. The list of supported formats might
>> vary between generations, might it not? Also we don't have a case of
>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>> have CSC) lists YUV as supported.
>>
> 
> the list of formats is tied to the sspps the dpu generation has and the 
> capabilities of those sspps.
> 
> qcm2290 is really an interesting case. It has one vig sspp but no csc 
> block for that vig sspp, hence it cannot support non-RGB formats.
> 
> I have confirmed that downstream is incorrect to populate yuv formats 
> for qcm2290.
> 
> I still think that having atleast one vig sspp with csc sub-blk is the 
> right condition to check if we want to decide if the dpu for that 
> chipset supports yuv formats. Extra csc-blk check to handle qcm2290.
> 
> Having a small helper in dpu_plane.c is good enough for that because 
> with virtual planes, you only need to know "if such a plane exists and 
> not which plane" and a full catalog change isnt needed IMO

This goes down to the question: is the list of YUV and non-YUV formats 
static or not? Do all DPU devices support the same set of YUV and 
non-YUV formats? If it is static, we might as well drop 
dpu_sspp_sub_blks::format_list.

Note to myself: consider 
dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either migrate 
dpu_sspp_sub_blks::format_list users to these fields or drop them.

> 
> 
>> Note: I think at some point we should have a closer look at the list
>> of supported formats and crosscheck that we do not have either
>> unsupported formats being listed, or missing formats which are not
>> listed as supported.
>>
>>>
>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>> ---
>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 
>>>> +++++++++++++++++++
>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
>>>>    2 files changed, 30 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>> index 212d546b6c5d..2d6944a9679a 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>> @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps qcm2290_dpu_caps = {
>>>> @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
>>>>        .has_idle_pc = true,
>>>>        .max_linewidth = 2160,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sdm845_dpu_caps = {
>>>> @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sc7180_dpu_caps = {
>>>> @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
>>>>        .has_idle_pc = true,
>>>>        .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sm6115_dpu_caps = {
>>>> @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
>>>>        .has_idle_pc = true,
>>>>        .max_linewidth = 2160,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sm8150_dpu_caps = {
>>>> @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sc8180x_dpu_caps = {
>>>> @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sc8280xp_dpu_caps = {
>>>> @@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
>>>>        .has_3d_merge = true,
>>>>        .max_linewidth = 5120,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sm8250_dpu_caps = {
>>>> @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
>>>>        .has_3d_merge = true,
>>>>        .max_linewidth = 900,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sm8350_dpu_caps = {
>>>> @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
>>>>        .has_3d_merge = true,
>>>>        .max_linewidth = 4096,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sm8450_dpu_caps = {
>>>> @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
>>>>        .has_3d_merge = true,
>>>>        .max_linewidth = 5120,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sm8550_dpu_caps = {
>>>> @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
>>>>        .has_3d_merge = true,
>>>>        .max_linewidth = 5120,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_caps sc7280_dpu_caps = {
>>>> @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
>>>>        .has_idle_pc = true,
>>>>        .max_linewidth = 2400,
>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>> +     .format_list = plane_formats_yuv,
>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>    };
>>>>
>>>>    static const struct dpu_mdp_cfg msm8998_mdp[] = {
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>> index 89b372cdca92..4847aae78db2 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>> @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
>>>>     * @pixel_ram_size     size of latency hiding and de-tiling 
>>>> buffer in bytes
>>>>     * @max_hdeci_exp      max horizontal decimation supported (max 
>>>> is 2^value)
>>>>     * @max_vdeci_exp      max vertical decimation supported (max is 
>>>> 2^value)
>>>> + * @format_list: Pointer to list of supported formats
>>>> + * @num_formats: Number of supported formats
>>>>     */
>>>>    struct dpu_caps {
>>>>        u32 max_mixer_width;
>>>> @@ -419,6 +421,8 @@ struct dpu_caps {
>>>>        u32 pixel_ram_size;
>>>>        u32 max_hdeci_exp;
>>>>        u32 max_vdeci_exp;
>>>> +     const u32 *format_list;
>>>> +     u32 num_formats;
>>>>    };
>>>>
>>>>    /**
>>
>>
>>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 21:29         ` Dmitry Baryshkov
@ 2023-06-06 21:47           ` Abhinav Kumar
  2023-06-06 21:52             ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 21:47 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>
>>
>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>> <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>> As we are going to add virtual planes, add the list of supported 
>>>>> formats
>>>>> to the hw catalog entry. It will be used to setup universal planes, 
>>>>> with
>>>>> later selecting a pipe depending on whether the YUV format is used for
>>>>> the framebuffer.
>>>>>
>>>>
>>>> If your usage of format_list is going to be internal to dpu_plane.c, I
>>>> can think of another idea for this change.
>>>>
>>>> This essentially translates to if (num_vig >= 1)
>>>>
>>>> If we can just have a small helper to detect that from the catalog can
>>>> we use that instead of adding formats to the dpu caps?
>>>
>>> I'd prefer to be explicit here. The list of supported formats might
>>> vary between generations, might it not? Also we don't have a case of
>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>> have CSC) lists YUV as supported.
>>>
>>
>> the list of formats is tied to the sspps the dpu generation has and 
>> the capabilities of those sspps.
>>
>> qcm2290 is really an interesting case. It has one vig sspp but no csc 
>> block for that vig sspp, hence it cannot support non-RGB formats.
>>
>> I have confirmed that downstream is incorrect to populate yuv formats 
>> for qcm2290.
>>
>> I still think that having atleast one vig sspp with csc sub-blk is the 
>> right condition to check if we want to decide if the dpu for that 
>> chipset supports yuv formats. Extra csc-blk check to handle qcm2290.
>>
>> Having a small helper in dpu_plane.c is good enough for that because 
>> with virtual planes, you only need to know "if such a plane exists and 
>> not which plane" and a full catalog change isnt needed IMO
> 
> This goes down to the question: is the list of YUV and non-YUV formats 
> static or not? Do all DPU devices support the same set of YUV and 
> non-YUV formats? If it is static, we might as well drop 
> dpu_sspp_sub_blks::format_list.
> 

I would say yes based on the below reference:

https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858

We always add the same set of YUV formats for all Vig SSPPs irrespective 
of the chipsets.

> Note to myself: consider 
> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either migrate 
> dpu_sspp_sub_blks::format_list users to these fields or drop them.
> 

Yes, I agree. There is no need to have format list in the sub_blk as for 
one type of SSPP, it supports the same format across DPU generations.

>>
>>
>>> Note: I think at some point we should have a closer look at the list
>>> of supported formats and crosscheck that we do not have either
>>> unsupported formats being listed, or missing formats which are not
>>> listed as supported.
>>>
>>>>
>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>> ---
>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 
>>>>> +++++++++++++++++++
>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
>>>>>    2 files changed, 30 insertions(+)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>> index 212d546b6c5d..2d6944a9679a 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>> @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps qcm2290_dpu_caps = {
>>>>> @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
>>>>>        .has_idle_pc = true,
>>>>>        .max_linewidth = 2160,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sdm845_dpu_caps = {
>>>>> @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sc7180_dpu_caps = {
>>>>> @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
>>>>>        .has_idle_pc = true,
>>>>>        .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sm6115_dpu_caps = {
>>>>> @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
>>>>>        .has_idle_pc = true,
>>>>>        .max_linewidth = 2160,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sm8150_dpu_caps = {
>>>>> @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sc8180x_dpu_caps = {
>>>>> @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sc8280xp_dpu_caps = {
>>>>> @@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
>>>>>        .has_3d_merge = true,
>>>>>        .max_linewidth = 5120,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sm8250_dpu_caps = {
>>>>> @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
>>>>>        .has_3d_merge = true,
>>>>>        .max_linewidth = 900,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sm8350_dpu_caps = {
>>>>> @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
>>>>>        .has_3d_merge = true,
>>>>>        .max_linewidth = 4096,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sm8450_dpu_caps = {
>>>>> @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
>>>>>        .has_3d_merge = true,
>>>>>        .max_linewidth = 5120,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sm8550_dpu_caps = {
>>>>> @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
>>>>>        .has_3d_merge = true,
>>>>>        .max_linewidth = 5120,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_caps sc7280_dpu_caps = {
>>>>> @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
>>>>>        .has_idle_pc = true,
>>>>>        .max_linewidth = 2400,
>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>> +     .format_list = plane_formats_yuv,
>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>    };
>>>>>
>>>>>    static const struct dpu_mdp_cfg msm8998_mdp[] = {
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>> index 89b372cdca92..4847aae78db2 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>> @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
>>>>>     * @pixel_ram_size     size of latency hiding and de-tiling 
>>>>> buffer in bytes
>>>>>     * @max_hdeci_exp      max horizontal decimation supported (max 
>>>>> is 2^value)
>>>>>     * @max_vdeci_exp      max vertical decimation supported (max is 
>>>>> 2^value)
>>>>> + * @format_list: Pointer to list of supported formats
>>>>> + * @num_formats: Number of supported formats
>>>>>     */
>>>>>    struct dpu_caps {
>>>>>        u32 max_mixer_width;
>>>>> @@ -419,6 +421,8 @@ struct dpu_caps {
>>>>>        u32 pixel_ram_size;
>>>>>        u32 max_hdeci_exp;
>>>>>        u32 max_vdeci_exp;
>>>>> +     const u32 *format_list;
>>>>> +     u32 num_formats;
>>>>>    };
>>>>>
>>>>>    /**
>>>
>>>
>>>
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 21:47           ` Abhinav Kumar
@ 2023-06-06 21:52             ` Dmitry Baryshkov
  2023-06-06 22:47               ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-06 21:52 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On 07/06/2023 00:47, Abhinav Kumar wrote:
> 
> 
> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>
>>>
>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>> As we are going to add virtual planes, add the list of supported 
>>>>>> formats
>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>> planes, with
>>>>>> later selecting a pipe depending on whether the YUV format is used 
>>>>>> for
>>>>>> the framebuffer.
>>>>>>
>>>>>
>>>>> If your usage of format_list is going to be internal to dpu_plane.c, I
>>>>> can think of another idea for this change.
>>>>>
>>>>> This essentially translates to if (num_vig >= 1)
>>>>>
>>>>> If we can just have a small helper to detect that from the catalog can
>>>>> we use that instead of adding formats to the dpu caps?
>>>>
>>>> I'd prefer to be explicit here. The list of supported formats might
>>>> vary between generations, might it not? Also we don't have a case of
>>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>>> have CSC) lists YUV as supported.
>>>>
>>>
>>> the list of formats is tied to the sspps the dpu generation has and 
>>> the capabilities of those sspps.
>>>
>>> qcm2290 is really an interesting case. It has one vig sspp but no csc 
>>> block for that vig sspp, hence it cannot support non-RGB formats.
>>>
>>> I have confirmed that downstream is incorrect to populate yuv formats 
>>> for qcm2290.
>>>
>>> I still think that having atleast one vig sspp with csc sub-blk is 
>>> the right condition to check if we want to decide if the dpu for that 
>>> chipset supports yuv formats. Extra csc-blk check to handle qcm2290.
>>>
>>> Having a small helper in dpu_plane.c is good enough for that because 
>>> with virtual planes, you only need to know "if such a plane exists 
>>> and not which plane" and a full catalog change isnt needed IMO
>>
>> This goes down to the question: is the list of YUV and non-YUV formats 
>> static or not? Do all DPU devices support the same set of YUV and 
>> non-YUV formats? If it is static, we might as well drop 
>> dpu_sspp_sub_blks::format_list.
>>
> 
> I would say yes based on the below reference:
> 
> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
> 
> We always add the same set of YUV formats for all Vig SSPPs irrespective 
> of the chipsets.

Well, as your example pointed out, few lines below it starts adding 
formats to the list, so the format list is not static and depends on the 
generation.

> 
>> Note to myself: consider 
>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either migrate 
>> dpu_sspp_sub_blks::format_list users to these fields or drop them.
>>
> 
> Yes, I agree. There is no need to have format list in the sub_blk as for 
> one type of SSPP, it supports the same format across DPU generations.
> 
>>>
>>>
>>>> Note: I think at some point we should have a closer look at the list
>>>> of supported formats and crosscheck that we do not have either
>>>> unsupported formats being listed, or missing formats which are not
>>>> listed as supported.
>>>>
>>>>>
>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>>> ---
>>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 
>>>>>> +++++++++++++++++++
>>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
>>>>>>    2 files changed, 30 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>>> index 212d546b6c5d..2d6944a9679a 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>>> @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps = {
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps qcm2290_dpu_caps = {
>>>>>> @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps = {
>>>>>>        .has_idle_pc = true,
>>>>>>        .max_linewidth = 2160,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sdm845_dpu_caps = {
>>>>>> @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sc7180_dpu_caps = {
>>>>>> @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
>>>>>>        .has_idle_pc = true,
>>>>>>        .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sm6115_dpu_caps = {
>>>>>> @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
>>>>>>        .has_idle_pc = true,
>>>>>>        .max_linewidth = 2160,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sm8150_dpu_caps = {
>>>>>> @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sc8180x_dpu_caps = {
>>>>>> @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps = {
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sc8280xp_dpu_caps = {
>>>>>> @@ -404,6 +418,8 @@ static const struct dpu_caps sc8280xp_dpu_caps 
>>>>>> = {
>>>>>>        .has_3d_merge = true,
>>>>>>        .max_linewidth = 5120,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sm8250_dpu_caps = {
>>>>>> @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
>>>>>>        .has_3d_merge = true,
>>>>>>        .max_linewidth = 900,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sm8350_dpu_caps = {
>>>>>> @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
>>>>>>        .has_3d_merge = true,
>>>>>>        .max_linewidth = 4096,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sm8450_dpu_caps = {
>>>>>> @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
>>>>>>        .has_3d_merge = true,
>>>>>>        .max_linewidth = 5120,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sm8550_dpu_caps = {
>>>>>> @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
>>>>>>        .has_3d_merge = true,
>>>>>>        .max_linewidth = 5120,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_caps sc7280_dpu_caps = {
>>>>>> @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
>>>>>>        .has_idle_pc = true,
>>>>>>        .max_linewidth = 2400,
>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>> +     .format_list = plane_formats_yuv,
>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>    };
>>>>>>
>>>>>>    static const struct dpu_mdp_cfg msm8998_mdp[] = {
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>>> index 89b372cdca92..4847aae78db2 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>>> @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
>>>>>>     * @pixel_ram_size     size of latency hiding and de-tiling 
>>>>>> buffer in bytes
>>>>>>     * @max_hdeci_exp      max horizontal decimation supported (max 
>>>>>> is 2^value)
>>>>>>     * @max_vdeci_exp      max vertical decimation supported (max 
>>>>>> is 2^value)
>>>>>> + * @format_list: Pointer to list of supported formats
>>>>>> + * @num_formats: Number of supported formats
>>>>>>     */
>>>>>>    struct dpu_caps {
>>>>>>        u32 max_mixer_width;
>>>>>> @@ -419,6 +421,8 @@ struct dpu_caps {
>>>>>>        u32 pixel_ram_size;
>>>>>>        u32 max_hdeci_exp;
>>>>>>        u32 max_vdeci_exp;
>>>>>> +     const u32 *format_list;
>>>>>> +     u32 num_formats;
>>>>>>    };
>>>>>>
>>>>>>    /**
>>>>
>>>>
>>>>
>>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 21:52             ` Dmitry Baryshkov
@ 2023-06-06 22:47               ` Abhinav Kumar
  2023-06-06 22:50                 ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 22:47 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno



On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>
>>
>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>
>>>>
>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>> As we are going to add virtual planes, add the list of supported 
>>>>>>> formats
>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>> planes, with
>>>>>>> later selecting a pipe depending on whether the YUV format is 
>>>>>>> used for
>>>>>>> the framebuffer.
>>>>>>>
>>>>>>
>>>>>> If your usage of format_list is going to be internal to 
>>>>>> dpu_plane.c, I
>>>>>> can think of another idea for this change.
>>>>>>
>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>
>>>>>> If we can just have a small helper to detect that from the catalog 
>>>>>> can
>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>
>>>>> I'd prefer to be explicit here. The list of supported formats might
>>>>> vary between generations, might it not? Also we don't have a case of
>>>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>>>> have CSC) lists YUV as supported.
>>>>>
>>>>
>>>> the list of formats is tied to the sspps the dpu generation has and 
>>>> the capabilities of those sspps.
>>>>
>>>> qcm2290 is really an interesting case. It has one vig sspp but no 
>>>> csc block for that vig sspp, hence it cannot support non-RGB formats.
>>>>
>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>> formats for qcm2290.
>>>>
>>>> I still think that having atleast one vig sspp with csc sub-blk is 
>>>> the right condition to check if we want to decide if the dpu for 
>>>> that chipset supports yuv formats. Extra csc-blk check to handle 
>>>> qcm2290.
>>>>
>>>> Having a small helper in dpu_plane.c is good enough for that because 
>>>> with virtual planes, you only need to know "if such a plane exists 
>>>> and not which plane" and a full catalog change isnt needed IMO
>>>
>>> This goes down to the question: is the list of YUV and non-YUV 
>>> formats static or not? Do all DPU devices support the same set of YUV 
>>> and non-YUV formats? If it is static, we might as well drop 
>>> dpu_sspp_sub_blks::format_list.
>>>
>>
>> I would say yes based on the below reference:
>>
>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>
>> We always add the same set of YUV formats for all Vig SSPPs 
>> irrespective of the chipsets.
> 
> Well, as your example pointed out, few lines below it starts adding 
> formats to the list, so the format list is not static and depends on the 
> generation.
> 

No, the DPU revision checks are there to add P010 UBWC formats on top of 
the Vig formats.

At the moment, the latest downstream code (code which is not on CLO 
hence I cannot share) has dropped all that and just checks if P010 UBWC 
is supported for the Vig SSPP and adds all those.

So its still tied to the feature bit whether P010 UBWC is supported in 
the Vig SSPP and not at the chipset level.

>>
>>> Note to myself: consider 
>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>> migrate dpu_sspp_sub_blks::format_list users to these fields or drop 
>>> them.
>>>
>>
>> Yes, I agree. There is no need to have format list in the sub_blk as 
>> for one type of SSPP, it supports the same format across DPU generations.
>>
>>>>
>>>>
>>>>> Note: I think at some point we should have a closer look at the list
>>>>> of supported formats and crosscheck that we do not have either
>>>>> unsupported formats being listed, or missing formats which are not
>>>>> listed as supported.
>>>>>
>>>>>>
>>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>>>> ---
>>>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 26 
>>>>>>> +++++++++++++++++++
>>>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  4 +++
>>>>>>>    2 files changed, 30 insertions(+)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>>>> index 212d546b6c5d..2d6944a9679a 100644
>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>>>>>>> @@ -315,6 +315,8 @@ static const struct dpu_caps msm8998_dpu_caps 
>>>>>>> = {
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps qcm2290_dpu_caps = {
>>>>>>> @@ -324,6 +326,8 @@ static const struct dpu_caps qcm2290_dpu_caps 
>>>>>>> = {
>>>>>>>        .has_idle_pc = true,
>>>>>>>        .max_linewidth = 2160,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sdm845_dpu_caps = {
>>>>>>> @@ -339,6 +343,8 @@ static const struct dpu_caps sdm845_dpu_caps = {
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sc7180_dpu_caps = {
>>>>>>> @@ -350,6 +356,8 @@ static const struct dpu_caps sc7180_dpu_caps = {
>>>>>>>        .has_idle_pc = true,
>>>>>>>        .max_linewidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sm6115_dpu_caps = {
>>>>>>> @@ -361,6 +369,8 @@ static const struct dpu_caps sm6115_dpu_caps = {
>>>>>>>        .has_idle_pc = true,
>>>>>>>        .max_linewidth = 2160,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sm8150_dpu_caps = {
>>>>>>> @@ -376,6 +386,8 @@ static const struct dpu_caps sm8150_dpu_caps = {
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sc8180x_dpu_caps = {
>>>>>>> @@ -391,6 +403,8 @@ static const struct dpu_caps sc8180x_dpu_caps 
>>>>>>> = {
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>>        .max_hdeci_exp = MAX_HORZ_DECIMATION,
>>>>>>>        .max_vdeci_exp = MAX_VERT_DECIMATION,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sc8280xp_dpu_caps = {
>>>>>>> @@ -404,6 +418,8 @@ static const struct dpu_caps 
>>>>>>> sc8280xp_dpu_caps = {
>>>>>>>        .has_3d_merge = true,
>>>>>>>        .max_linewidth = 5120,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sm8250_dpu_caps = {
>>>>>>> @@ -417,6 +433,8 @@ static const struct dpu_caps sm8250_dpu_caps = {
>>>>>>>        .has_3d_merge = true,
>>>>>>>        .max_linewidth = 900,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sm8350_dpu_caps = {
>>>>>>> @@ -430,6 +448,8 @@ static const struct dpu_caps sm8350_dpu_caps = {
>>>>>>>        .has_3d_merge = true,
>>>>>>>        .max_linewidth = 4096,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sm8450_dpu_caps = {
>>>>>>> @@ -443,6 +463,8 @@ static const struct dpu_caps sm8450_dpu_caps = {
>>>>>>>        .has_3d_merge = true,
>>>>>>>        .max_linewidth = 5120,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sm8550_dpu_caps = {
>>>>>>> @@ -456,6 +478,8 @@ static const struct dpu_caps sm8550_dpu_caps = {
>>>>>>>        .has_3d_merge = true,
>>>>>>>        .max_linewidth = 5120,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_caps sc7280_dpu_caps = {
>>>>>>> @@ -467,6 +491,8 @@ static const struct dpu_caps sc7280_dpu_caps = {
>>>>>>>        .has_idle_pc = true,
>>>>>>>        .max_linewidth = 2400,
>>>>>>>        .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
>>>>>>> +     .format_list = plane_formats_yuv,
>>>>>>> +     .num_formats = ARRAY_SIZE(plane_formats_yuv),
>>>>>>>    };
>>>>>>>
>>>>>>>    static const struct dpu_mdp_cfg msm8998_mdp[] = {
>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>>>> index 89b372cdca92..4847aae78db2 100644
>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>>>>>>> @@ -404,6 +404,8 @@ struct dpu_rotation_cfg {
>>>>>>>     * @pixel_ram_size     size of latency hiding and de-tiling 
>>>>>>> buffer in bytes
>>>>>>>     * @max_hdeci_exp      max horizontal decimation supported 
>>>>>>> (max is 2^value)
>>>>>>>     * @max_vdeci_exp      max vertical decimation supported (max 
>>>>>>> is 2^value)
>>>>>>> + * @format_list: Pointer to list of supported formats
>>>>>>> + * @num_formats: Number of supported formats
>>>>>>>     */
>>>>>>>    struct dpu_caps {
>>>>>>>        u32 max_mixer_width;
>>>>>>> @@ -419,6 +421,8 @@ struct dpu_caps {
>>>>>>>        u32 pixel_ram_size;
>>>>>>>        u32 max_hdeci_exp;
>>>>>>>        u32 max_vdeci_exp;
>>>>>>> +     const u32 *format_list;
>>>>>>> +     u32 num_formats;
>>>>>>>    };
>>>>>>>
>>>>>>>    /**
>>>>>
>>>>>
>>>>>
>>>
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 22:47               ` Abhinav Kumar
@ 2023-06-06 22:50                 ` Dmitry Baryshkov
  2023-06-06 22:57                   ` [Freedreno] " Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-06 22:50 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Rob Clark, Sean Paul, Stephen Boyd, David Airlie, Daniel Vetter,
	Bjorn Andersson, linux-arm-msm, dri-devel, freedreno

On 07/06/2023 01:47, Abhinav Kumar wrote:
> 
> 
> On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
>> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>>
>>>
>>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>>
>>>>>
>>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>>> As we are going to add virtual planes, add the list of supported 
>>>>>>>> formats
>>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>>> planes, with
>>>>>>>> later selecting a pipe depending on whether the YUV format is 
>>>>>>>> used for
>>>>>>>> the framebuffer.
>>>>>>>>
>>>>>>>
>>>>>>> If your usage of format_list is going to be internal to 
>>>>>>> dpu_plane.c, I
>>>>>>> can think of another idea for this change.
>>>>>>>
>>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>>
>>>>>>> If we can just have a small helper to detect that from the 
>>>>>>> catalog can
>>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>>
>>>>>> I'd prefer to be explicit here. The list of supported formats might
>>>>>> vary between generations, might it not? Also we don't have a case of
>>>>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>>>>> have CSC) lists YUV as supported.
>>>>>>
>>>>>
>>>>> the list of formats is tied to the sspps the dpu generation has and 
>>>>> the capabilities of those sspps.
>>>>>
>>>>> qcm2290 is really an interesting case. It has one vig sspp but no 
>>>>> csc block for that vig sspp, hence it cannot support non-RGB formats.
>>>>>
>>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>>> formats for qcm2290.
>>>>>
>>>>> I still think that having atleast one vig sspp with csc sub-blk is 
>>>>> the right condition to check if we want to decide if the dpu for 
>>>>> that chipset supports yuv formats. Extra csc-blk check to handle 
>>>>> qcm2290.
>>>>>
>>>>> Having a small helper in dpu_plane.c is good enough for that 
>>>>> because with virtual planes, you only need to know "if such a plane 
>>>>> exists and not which plane" and a full catalog change isnt needed IMO
>>>>
>>>> This goes down to the question: is the list of YUV and non-YUV 
>>>> formats static or not? Do all DPU devices support the same set of 
>>>> YUV and non-YUV formats? If it is static, we might as well drop 
>>>> dpu_sspp_sub_blks::format_list.
>>>>
>>>
>>> I would say yes based on the below reference:
>>>
>>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>>
>>> We always add the same set of YUV formats for all Vig SSPPs 
>>> irrespective of the chipsets.
>>
>> Well, as your example pointed out, few lines below it starts adding 
>> formats to the list, so the format list is not static and depends on 
>> the generation.
>>
> 
> No, the DPU revision checks are there to add P010 UBWC formats on top of 
> the Vig formats.
> 
> At the moment, the latest downstream code (code which is not on CLO 
> hence I cannot share) has dropped all that and just checks if P010 UBWC 
> is supported for the Vig SSPP and adds all those.
> 
> So its still tied to the feature bit whether P010 UBWC is supported in 
> the Vig SSPP and not at the chipset level.

So, what is the difference? This means that depending on some conditions 
either we can support P010 UBWC or we can not. So the list of all 
suppored formats is not static.

> 
>>>
>>>> Note to myself: consider 
>>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>>> migrate dpu_sspp_sub_blks::format_list users to these fields or drop 
>>>> them.
>>>>
>>>
>>> Yes, I agree. There is no need to have format list in the sub_blk as 
>>> for one type of SSPP, it supports the same format across DPU 
>>> generations.
>>>
>>>>>
>>>>>
>>>>>> Note: I think at some point we should have a closer look at the list
>>>>>> of supported formats and crosscheck that we do not have either
>>>>>> unsupported formats being listed, or missing formats which are not
>>>>>> listed as supported.
>>>>>>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 22:50                 ` Dmitry Baryshkov
@ 2023-06-06 22:57                   ` Abhinav Kumar
  2023-06-06 22:59                     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 22:57 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Sean Paul, Bjorn Andersson, dri-devel, Stephen Boyd,
	Rob Clark, Daniel Vetter, linux-arm-msm, David Airlie



On 6/6/2023 3:50 PM, Dmitry Baryshkov wrote:
> On 07/06/2023 01:47, Abhinav Kumar wrote:
>>
>>
>> On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
>>> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>>>
>>>>
>>>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>>>
>>>>>>
>>>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>>>> As we are going to add virtual planes, add the list of 
>>>>>>>>> supported formats
>>>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>>>> planes, with
>>>>>>>>> later selecting a pipe depending on whether the YUV format is 
>>>>>>>>> used for
>>>>>>>>> the framebuffer.
>>>>>>>>>
>>>>>>>>
>>>>>>>> If your usage of format_list is going to be internal to 
>>>>>>>> dpu_plane.c, I
>>>>>>>> can think of another idea for this change.
>>>>>>>>
>>>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>>>
>>>>>>>> If we can just have a small helper to detect that from the 
>>>>>>>> catalog can
>>>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>>>
>>>>>>> I'd prefer to be explicit here. The list of supported formats might
>>>>>>> vary between generations, might it not? Also we don't have a case of
>>>>>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>>>>>> have CSC) lists YUV as supported.
>>>>>>>
>>>>>>
>>>>>> the list of formats is tied to the sspps the dpu generation has 
>>>>>> and the capabilities of those sspps.
>>>>>>
>>>>>> qcm2290 is really an interesting case. It has one vig sspp but no 
>>>>>> csc block for that vig sspp, hence it cannot support non-RGB formats.
>>>>>>
>>>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>>>> formats for qcm2290.
>>>>>>
>>>>>> I still think that having atleast one vig sspp with csc sub-blk is 
>>>>>> the right condition to check if we want to decide if the dpu for 
>>>>>> that chipset supports yuv formats. Extra csc-blk check to handle 
>>>>>> qcm2290.
>>>>>>
>>>>>> Having a small helper in dpu_plane.c is good enough for that 
>>>>>> because with virtual planes, you only need to know "if such a 
>>>>>> plane exists and not which plane" and a full catalog change isnt 
>>>>>> needed IMO
>>>>>
>>>>> This goes down to the question: is the list of YUV and non-YUV 
>>>>> formats static or not? Do all DPU devices support the same set of 
>>>>> YUV and non-YUV formats? If it is static, we might as well drop 
>>>>> dpu_sspp_sub_blks::format_list.
>>>>>
>>>>
>>>> I would say yes based on the below reference:
>>>>
>>>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>>>
>>>> We always add the same set of YUV formats for all Vig SSPPs 
>>>> irrespective of the chipsets.
>>>
>>> Well, as your example pointed out, few lines below it starts adding 
>>> formats to the list, so the format list is not static and depends on 
>>> the generation.
>>>
>>
>> No, the DPU revision checks are there to add P010 UBWC formats on top 
>> of the Vig formats.
>>
>> At the moment, the latest downstream code (code which is not on CLO 
>> hence I cannot share) has dropped all that and just checks if P010 
>> UBWC is supported for the Vig SSPP and adds all those.
>>
>> So its still tied to the feature bit whether P010 UBWC is supported in 
>> the Vig SSPP and not at the chipset level.
> 
> So, what is the difference? This means that depending on some conditions 
> either we can support P010 UBWC or we can not. So the list of all 
> suppored formats is not static.
> 

The difference is SSPP level vs chipset level. This patch was made with 
chipset level in mind and had to expand the format list for each chipset.

What I am suggesting is its a SSPP level decision. Please note its not 
just P010 UBWC but P010 UBWC FOR Vig SSPP.

So expanding each chipset's format list is not needed when the decision 
can be made just on the basis of the SSPP's feature flag OR the presence 
of the csc blk.

>>
>>>>
>>>>> Note to myself: consider 
>>>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>>>> migrate dpu_sspp_sub_blks::format_list users to these fields or 
>>>>> drop them.
>>>>>
>>>>
>>>> Yes, I agree. There is no need to have format list in the sub_blk as 
>>>> for one type of SSPP, it supports the same format across DPU 
>>>> generations.
>>>>
>>>>>>
>>>>>>
>>>>>>> Note: I think at some point we should have a closer look at the list
>>>>>>> of supported formats and crosscheck that we do not have either
>>>>>>> unsupported formats being listed, or missing formats which are not
>>>>>>> listed as supported.
>>>>>>>
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 22:57                   ` [Freedreno] " Abhinav Kumar
@ 2023-06-06 22:59                     ` Dmitry Baryshkov
  2023-06-06 23:14                       ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-06 22:59 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Sean Paul, Bjorn Andersson, dri-devel, Stephen Boyd,
	Rob Clark, Daniel Vetter, linux-arm-msm, David Airlie

On 07/06/2023 01:57, Abhinav Kumar wrote:
> 
> 
> On 6/6/2023 3:50 PM, Dmitry Baryshkov wrote:
>> On 07/06/2023 01:47, Abhinav Kumar wrote:
>>>
>>>
>>> On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
>>>> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>>>>
>>>>>
>>>>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>>>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>>>>> As we are going to add virtual planes, add the list of 
>>>>>>>>>> supported formats
>>>>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>>>>> planes, with
>>>>>>>>>> later selecting a pipe depending on whether the YUV format is 
>>>>>>>>>> used for
>>>>>>>>>> the framebuffer.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> If your usage of format_list is going to be internal to 
>>>>>>>>> dpu_plane.c, I
>>>>>>>>> can think of another idea for this change.
>>>>>>>>>
>>>>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>>>>
>>>>>>>>> If we can just have a small helper to detect that from the 
>>>>>>>>> catalog can
>>>>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>>>>
>>>>>>>> I'd prefer to be explicit here. The list of supported formats might
>>>>>>>> vary between generations, might it not? Also we don't have a 
>>>>>>>> case of
>>>>>>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>>>>>>> have CSC) lists YUV as supported.
>>>>>>>>
>>>>>>>
>>>>>>> the list of formats is tied to the sspps the dpu generation has 
>>>>>>> and the capabilities of those sspps.
>>>>>>>
>>>>>>> qcm2290 is really an interesting case. It has one vig sspp but no 
>>>>>>> csc block for that vig sspp, hence it cannot support non-RGB 
>>>>>>> formats.
>>>>>>>
>>>>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>>>>> formats for qcm2290.
>>>>>>>
>>>>>>> I still think that having atleast one vig sspp with csc sub-blk 
>>>>>>> is the right condition to check if we want to decide if the dpu 
>>>>>>> for that chipset supports yuv formats. Extra csc-blk check to 
>>>>>>> handle qcm2290.
>>>>>>>
>>>>>>> Having a small helper in dpu_plane.c is good enough for that 
>>>>>>> because with virtual planes, you only need to know "if such a 
>>>>>>> plane exists and not which plane" and a full catalog change isnt 
>>>>>>> needed IMO
>>>>>>
>>>>>> This goes down to the question: is the list of YUV and non-YUV 
>>>>>> formats static or not? Do all DPU devices support the same set of 
>>>>>> YUV and non-YUV formats? If it is static, we might as well drop 
>>>>>> dpu_sspp_sub_blks::format_list.
>>>>>>
>>>>>
>>>>> I would say yes based on the below reference:
>>>>>
>>>>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>>>>
>>>>> We always add the same set of YUV formats for all Vig SSPPs 
>>>>> irrespective of the chipsets.
>>>>
>>>> Well, as your example pointed out, few lines below it starts adding 
>>>> formats to the list, so the format list is not static and depends on 
>>>> the generation.
>>>>
>>>
>>> No, the DPU revision checks are there to add P010 UBWC formats on top 
>>> of the Vig formats.
>>>
>>> At the moment, the latest downstream code (code which is not on CLO 
>>> hence I cannot share) has dropped all that and just checks if P010 
>>> UBWC is supported for the Vig SSPP and adds all those.
>>>
>>> So its still tied to the feature bit whether P010 UBWC is supported 
>>> in the Vig SSPP and not at the chipset level.
>>
>> So, what is the difference? This means that depending on some 
>> conditions either we can support P010 UBWC or we can not. So the list 
>> of all suppored formats is not static.
>>
> 
> The difference is SSPP level vs chipset level. This patch was made with 
> chipset level in mind and had to expand the format list for each chipset.
> 
> What I am suggesting is its a SSPP level decision. Please note its not 
> just P010 UBWC but P010 UBWC FOR Vig SSPP.
> 
> So expanding each chipset's format list is not needed when the decision 
> can be made just on the basis of the SSPP's feature flag OR the presence 
> of the csc blk.

Maybe I misunderstand something. Is P010 UBWC format supported on VIG 
SSPPs on all generations? The code that you have pointed me suggests 
that is is not.

> 
>>>
>>>>>
>>>>>> Note to myself: consider 
>>>>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>>>>> migrate dpu_sspp_sub_blks::format_list users to these fields or 
>>>>>> drop them.
>>>>>>
>>>>>
>>>>> Yes, I agree. There is no need to have format list in the sub_blk 
>>>>> as for one type of SSPP, it supports the same format across DPU 
>>>>> generations.
>>>>>
>>>>>>>
>>>>>>>
>>>>>>>> Note: I think at some point we should have a closer look at the 
>>>>>>>> list
>>>>>>>> of supported formats and crosscheck that we do not have either
>>>>>>>> unsupported formats being listed, or missing formats which are not
>>>>>>>> listed as supported.
>>>>>>>>
>>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 22:59                     ` Dmitry Baryshkov
@ 2023-06-06 23:14                       ` Abhinav Kumar
  2023-06-06 23:21                         ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-06 23:14 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Bjorn Andersson, dri-devel, Stephen Boyd,
	linux-arm-msm, Sean Paul



On 6/6/2023 3:59 PM, Dmitry Baryshkov wrote:
> On 07/06/2023 01:57, Abhinav Kumar wrote:
>>
>>
>> On 6/6/2023 3:50 PM, Dmitry Baryshkov wrote:
>>> On 07/06/2023 01:47, Abhinav Kumar wrote:
>>>>
>>>>
>>>> On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
>>>>> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>>>>>
>>>>>>
>>>>>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>>>>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>>>>>> As we are going to add virtual planes, add the list of 
>>>>>>>>>>> supported formats
>>>>>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>>>>>> planes, with
>>>>>>>>>>> later selecting a pipe depending on whether the YUV format is 
>>>>>>>>>>> used for
>>>>>>>>>>> the framebuffer.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> If your usage of format_list is going to be internal to 
>>>>>>>>>> dpu_plane.c, I
>>>>>>>>>> can think of another idea for this change.
>>>>>>>>>>
>>>>>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>>>>>
>>>>>>>>>> If we can just have a small helper to detect that from the 
>>>>>>>>>> catalog can
>>>>>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>>>>>
>>>>>>>>> I'd prefer to be explicit here. The list of supported formats 
>>>>>>>>> might
>>>>>>>>> vary between generations, might it not? Also we don't have a 
>>>>>>>>> case of
>>>>>>>>> the devices not having VIG planes. Even the qcm2290 (which doesn't
>>>>>>>>> have CSC) lists YUV as supported.
>>>>>>>>>
>>>>>>>>
>>>>>>>> the list of formats is tied to the sspps the dpu generation has 
>>>>>>>> and the capabilities of those sspps.
>>>>>>>>
>>>>>>>> qcm2290 is really an interesting case. It has one vig sspp but 
>>>>>>>> no csc block for that vig sspp, hence it cannot support non-RGB 
>>>>>>>> formats.
>>>>>>>>
>>>>>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>>>>>> formats for qcm2290.
>>>>>>>>
>>>>>>>> I still think that having atleast one vig sspp with csc sub-blk 
>>>>>>>> is the right condition to check if we want to decide if the dpu 
>>>>>>>> for that chipset supports yuv formats. Extra csc-blk check to 
>>>>>>>> handle qcm2290.
>>>>>>>>
>>>>>>>> Having a small helper in dpu_plane.c is good enough for that 
>>>>>>>> because with virtual planes, you only need to know "if such a 
>>>>>>>> plane exists and not which plane" and a full catalog change isnt 
>>>>>>>> needed IMO
>>>>>>>
>>>>>>> This goes down to the question: is the list of YUV and non-YUV 
>>>>>>> formats static or not? Do all DPU devices support the same set of 
>>>>>>> YUV and non-YUV formats? If it is static, we might as well drop 
>>>>>>> dpu_sspp_sub_blks::format_list.
>>>>>>>
>>>>>>
>>>>>> I would say yes based on the below reference:
>>>>>>
>>>>>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>>>>>
>>>>>> We always add the same set of YUV formats for all Vig SSPPs 
>>>>>> irrespective of the chipsets.
>>>>>
>>>>> Well, as your example pointed out, few lines below it starts adding 
>>>>> formats to the list, so the format list is not static and depends 
>>>>> on the generation.
>>>>>
>>>>
>>>> No, the DPU revision checks are there to add P010 UBWC formats on 
>>>> top of the Vig formats.
>>>>
>>>> At the moment, the latest downstream code (code which is not on CLO 
>>>> hence I cannot share) has dropped all that and just checks if P010 
>>>> UBWC is supported for the Vig SSPP and adds all those.
>>>>
>>>> So its still tied to the feature bit whether P010 UBWC is supported 
>>>> in the Vig SSPP and not at the chipset level.
>>>
>>> So, what is the difference? This means that depending on some 
>>> conditions either we can support P010 UBWC or we can not. So the list 
>>> of all suppored formats is not static.
>>>
>>
>> The difference is SSPP level vs chipset level. This patch was made 
>> with chipset level in mind and had to expand the format list for each 
>> chipset.
>>
>> What I am suggesting is its a SSPP level decision. Please note its not 
>> just P010 UBWC but P010 UBWC FOR Vig SSPP.
>>
>> So expanding each chipset's format list is not needed when the 
>> decision can be made just on the basis of the SSPP's feature flag OR 
>> the presence of the csc blk.
> 
> Maybe I misunderstand something. Is P010 UBWC format supported on VIG 
> SSPPs on all generations? The code that you have pointed me suggests 
> that is is not.
> 

No, your understanding is correct that P010 UBWC format is supported 
only on Vig SSPPs of certain generations.

But my point is that, its still a SSPP level decision.

So even if we add P010 UBWC formats later to the list of supported 
formats, what we will do is add that feature bit alone in the Vig SSPP's 
feature mask of that chipset and based on that all the P010 UBWC formats 
for the virtual planes.

But if we follow your approach, we will add another array called 
plane_formats_p010_ubwc and add that to each chipset which will support it.

The only difference in idea is that, based on the SSPP's feature set of 
that chipset we can still determine that Vs adding it to each chipset.

>>
>>>>
>>>>>>
>>>>>>> Note to myself: consider 
>>>>>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>>>>>> migrate dpu_sspp_sub_blks::format_list users to these fields or 
>>>>>>> drop them.
>>>>>>>
>>>>>>
>>>>>> Yes, I agree. There is no need to have format list in the sub_blk 
>>>>>> as for one type of SSPP, it supports the same format across DPU 
>>>>>> generations.
>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>> Note: I think at some point we should have a closer look at the 
>>>>>>>>> list
>>>>>>>>> of supported formats and crosscheck that we do not have either
>>>>>>>>> unsupported formats being listed, or missing formats which are not
>>>>>>>>> listed as supported.
>>>>>>>>>
>>>
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 23:14                       ` Abhinav Kumar
@ 2023-06-06 23:21                         ` Dmitry Baryshkov
  2023-06-07  1:12                           ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-06 23:21 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Bjorn Andersson, dri-devel, Stephen Boyd,
	linux-arm-msm, Sean Paul

On 07/06/2023 02:14, Abhinav Kumar wrote:
> 
> 
> On 6/6/2023 3:59 PM, Dmitry Baryshkov wrote:
>> On 07/06/2023 01:57, Abhinav Kumar wrote:
>>>
>>>
>>> On 6/6/2023 3:50 PM, Dmitry Baryshkov wrote:
>>>> On 07/06/2023 01:47, Abhinav Kumar wrote:
>>>>>
>>>>>
>>>>> On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
>>>>>> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>>>>>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>>>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>>>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>>>>>>> As we are going to add virtual planes, add the list of 
>>>>>>>>>>>> supported formats
>>>>>>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>>>>>>> planes, with
>>>>>>>>>>>> later selecting a pipe depending on whether the YUV format 
>>>>>>>>>>>> is used for
>>>>>>>>>>>> the framebuffer.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> If your usage of format_list is going to be internal to 
>>>>>>>>>>> dpu_plane.c, I
>>>>>>>>>>> can think of another idea for this change.
>>>>>>>>>>>
>>>>>>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>>>>>>
>>>>>>>>>>> If we can just have a small helper to detect that from the 
>>>>>>>>>>> catalog can
>>>>>>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>>>>>>
>>>>>>>>>> I'd prefer to be explicit here. The list of supported formats 
>>>>>>>>>> might
>>>>>>>>>> vary between generations, might it not? Also we don't have a 
>>>>>>>>>> case of
>>>>>>>>>> the devices not having VIG planes. Even the qcm2290 (which 
>>>>>>>>>> doesn't
>>>>>>>>>> have CSC) lists YUV as supported.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> the list of formats is tied to the sspps the dpu generation has 
>>>>>>>>> and the capabilities of those sspps.
>>>>>>>>>
>>>>>>>>> qcm2290 is really an interesting case. It has one vig sspp but 
>>>>>>>>> no csc block for that vig sspp, hence it cannot support non-RGB 
>>>>>>>>> formats.
>>>>>>>>>
>>>>>>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>>>>>>> formats for qcm2290.
>>>>>>>>>
>>>>>>>>> I still think that having atleast one vig sspp with csc sub-blk 
>>>>>>>>> is the right condition to check if we want to decide if the dpu 
>>>>>>>>> for that chipset supports yuv formats. Extra csc-blk check to 
>>>>>>>>> handle qcm2290.
>>>>>>>>>
>>>>>>>>> Having a small helper in dpu_plane.c is good enough for that 
>>>>>>>>> because with virtual planes, you only need to know "if such a 
>>>>>>>>> plane exists and not which plane" and a full catalog change 
>>>>>>>>> isnt needed IMO
>>>>>>>>
>>>>>>>> This goes down to the question: is the list of YUV and non-YUV 
>>>>>>>> formats static or not? Do all DPU devices support the same set 
>>>>>>>> of YUV and non-YUV formats? If it is static, we might as well 
>>>>>>>> drop dpu_sspp_sub_blks::format_list.
>>>>>>>>
>>>>>>>
>>>>>>> I would say yes based on the below reference:
>>>>>>>
>>>>>>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>>>>>>
>>>>>>> We always add the same set of YUV formats for all Vig SSPPs 
>>>>>>> irrespective of the chipsets.
>>>>>>
>>>>>> Well, as your example pointed out, few lines below it starts 
>>>>>> adding formats to the list, so the format list is not static and 
>>>>>> depends on the generation.
>>>>>>
>>>>>
>>>>> No, the DPU revision checks are there to add P010 UBWC formats on 
>>>>> top of the Vig formats.
>>>>>
>>>>> At the moment, the latest downstream code (code which is not on CLO 
>>>>> hence I cannot share) has dropped all that and just checks if P010 
>>>>> UBWC is supported for the Vig SSPP and adds all those.
>>>>>
>>>>> So its still tied to the feature bit whether P010 UBWC is supported 
>>>>> in the Vig SSPP and not at the chipset level.
>>>>
>>>> So, what is the difference? This means that depending on some 
>>>> conditions either we can support P010 UBWC or we can not. So the 
>>>> list of all suppored formats is not static.
>>>>
>>>
>>> The difference is SSPP level vs chipset level. This patch was made 
>>> with chipset level in mind and had to expand the format list for each 
>>> chipset.
>>>
>>> What I am suggesting is its a SSPP level decision. Please note its 
>>> not just P010 UBWC but P010 UBWC FOR Vig SSPP.
>>>
>>> So expanding each chipset's format list is not needed when the 
>>> decision can be made just on the basis of the SSPP's feature flag OR 
>>> the presence of the csc blk.
>>
>> Maybe I misunderstand something. Is P010 UBWC format supported on VIG 
>> SSPPs on all generations? The code that you have pointed me suggests 
>> that is is not.
>>
> 
> No, your understanding is correct that P010 UBWC format is supported 
> only on Vig SSPPs of certain generations.
> 
> But my point is that, its still a SSPP level decision.
> 
> So even if we add P010 UBWC formats later to the list of supported 
> formats, what we will do is add that feature bit alone in the Vig SSPP's 
> feature mask of that chipset and based on that all the P010 UBWC formats 
> for the virtual planes.
> 
> But if we follow your approach, we will add another array called 
> plane_formats_p010_ubwc and add that to each chipset which will support it.

sspp->sblk->formats_list is constant, so we will have to add another 
formats array anyway.

> The only difference in idea is that, based on the SSPP's feature set of 
> that chipset we can still determine that Vs adding it to each chipset.
> 
>>>
>>>>>
>>>>>>>
>>>>>>>> Note to myself: consider 
>>>>>>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>>>>>>> migrate dpu_sspp_sub_blks::format_list users to these fields or 
>>>>>>>> drop them.
>>>>>>>>
>>>>>>>
>>>>>>> Yes, I agree. There is no need to have format list in the sub_blk 
>>>>>>> as for one type of SSPP, it supports the same format across DPU 
>>>>>>> generations.
>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> Note: I think at some point we should have a closer look at 
>>>>>>>>>> the list
>>>>>>>>>> of supported formats and crosscheck that we do not have either
>>>>>>>>>> unsupported formats being listed, or missing formats which are 
>>>>>>>>>> not
>>>>>>>>>> listed as supported.
>>>>>>>>>>
>>>>
>>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [Freedreno] [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps
  2023-06-06 23:21                         ` Dmitry Baryshkov
@ 2023-06-07  1:12                           ` Abhinav Kumar
  0 siblings, 0 replies; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-07  1:12 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Bjorn Andersson, dri-devel, Stephen Boyd,
	linux-arm-msm, Sean Paul



On 6/6/2023 4:21 PM, Dmitry Baryshkov wrote:
> On 07/06/2023 02:14, Abhinav Kumar wrote:
>>
>>
>> On 6/6/2023 3:59 PM, Dmitry Baryshkov wrote:
>>> On 07/06/2023 01:57, Abhinav Kumar wrote:
>>>>
>>>>
>>>> On 6/6/2023 3:50 PM, Dmitry Baryshkov wrote:
>>>>> On 07/06/2023 01:47, Abhinav Kumar wrote:
>>>>>>
>>>>>>
>>>>>> On 6/6/2023 2:52 PM, Dmitry Baryshkov wrote:
>>>>>>> On 07/06/2023 00:47, Abhinav Kumar wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 6/6/2023 2:29 PM, Dmitry Baryshkov wrote:
>>>>>>>>> On 07/06/2023 00:14, Abhinav Kumar wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 5/24/2023 6:47 PM, Dmitry Baryshkov wrote:
>>>>>>>>>>> On Thu, 25 May 2023 at 02:16, Abhinav Kumar 
>>>>>>>>>>> <quic_abhinavk@quicinc.com> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>>>>>>>>>>> As we are going to add virtual planes, add the list of 
>>>>>>>>>>>>> supported formats
>>>>>>>>>>>>> to the hw catalog entry. It will be used to setup universal 
>>>>>>>>>>>>> planes, with
>>>>>>>>>>>>> later selecting a pipe depending on whether the YUV format 
>>>>>>>>>>>>> is used for
>>>>>>>>>>>>> the framebuffer.
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> If your usage of format_list is going to be internal to 
>>>>>>>>>>>> dpu_plane.c, I
>>>>>>>>>>>> can think of another idea for this change.
>>>>>>>>>>>>
>>>>>>>>>>>> This essentially translates to if (num_vig >= 1)
>>>>>>>>>>>>
>>>>>>>>>>>> If we can just have a small helper to detect that from the 
>>>>>>>>>>>> catalog can
>>>>>>>>>>>> we use that instead of adding formats to the dpu caps?
>>>>>>>>>>>
>>>>>>>>>>> I'd prefer to be explicit here. The list of supported formats 
>>>>>>>>>>> might
>>>>>>>>>>> vary between generations, might it not? Also we don't have a 
>>>>>>>>>>> case of
>>>>>>>>>>> the devices not having VIG planes. Even the qcm2290 (which 
>>>>>>>>>>> doesn't
>>>>>>>>>>> have CSC) lists YUV as supported.
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> the list of formats is tied to the sspps the dpu generation 
>>>>>>>>>> has and the capabilities of those sspps.
>>>>>>>>>>
>>>>>>>>>> qcm2290 is really an interesting case. It has one vig sspp but 
>>>>>>>>>> no csc block for that vig sspp, hence it cannot support 
>>>>>>>>>> non-RGB formats.
>>>>>>>>>>
>>>>>>>>>> I have confirmed that downstream is incorrect to populate yuv 
>>>>>>>>>> formats for qcm2290.
>>>>>>>>>>
>>>>>>>>>> I still think that having atleast one vig sspp with csc 
>>>>>>>>>> sub-blk is the right condition to check if we want to decide 
>>>>>>>>>> if the dpu for that chipset supports yuv formats. Extra 
>>>>>>>>>> csc-blk check to handle qcm2290.
>>>>>>>>>>
>>>>>>>>>> Having a small helper in dpu_plane.c is good enough for that 
>>>>>>>>>> because with virtual planes, you only need to know "if such a 
>>>>>>>>>> plane exists and not which plane" and a full catalog change 
>>>>>>>>>> isnt needed IMO
>>>>>>>>>
>>>>>>>>> This goes down to the question: is the list of YUV and non-YUV 
>>>>>>>>> formats static or not? Do all DPU devices support the same set 
>>>>>>>>> of YUV and non-YUV formats? If it is static, we might as well 
>>>>>>>>> drop dpu_sspp_sub_blks::format_list.
>>>>>>>>>
>>>>>>>>
>>>>>>>> I would say yes based on the below reference:
>>>>>>>>
>>>>>>>> https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog.c#L3858
>>>>>>>>
>>>>>>>> We always add the same set of YUV formats for all Vig SSPPs 
>>>>>>>> irrespective of the chipsets.
>>>>>>>
>>>>>>> Well, as your example pointed out, few lines below it starts 
>>>>>>> adding formats to the list, so the format list is not static and 
>>>>>>> depends on the generation.
>>>>>>>
>>>>>>
>>>>>> No, the DPU revision checks are there to add P010 UBWC formats on 
>>>>>> top of the Vig formats.
>>>>>>
>>>>>> At the moment, the latest downstream code (code which is not on 
>>>>>> CLO hence I cannot share) has dropped all that and just checks if 
>>>>>> P010 UBWC is supported for the Vig SSPP and adds all those.
>>>>>>
>>>>>> So its still tied to the feature bit whether P010 UBWC is 
>>>>>> supported in the Vig SSPP and not at the chipset level.
>>>>>
>>>>> So, what is the difference? This means that depending on some 
>>>>> conditions either we can support P010 UBWC or we can not. So the 
>>>>> list of all suppored formats is not static.
>>>>>
>>>>
>>>> The difference is SSPP level vs chipset level. This patch was made 
>>>> with chipset level in mind and had to expand the format list for 
>>>> each chipset.
>>>>
>>>> What I am suggesting is its a SSPP level decision. Please note its 
>>>> not just P010 UBWC but P010 UBWC FOR Vig SSPP.
>>>>
>>>> So expanding each chipset's format list is not needed when the 
>>>> decision can be made just on the basis of the SSPP's feature flag OR 
>>>> the presence of the csc blk.
>>>
>>> Maybe I misunderstand something. Is P010 UBWC format supported on VIG 
>>> SSPPs on all generations? The code that you have pointed me suggests 
>>> that is is not.
>>>
>>
>> No, your understanding is correct that P010 UBWC format is supported 
>> only on Vig SSPPs of certain generations.
>>
>> But my point is that, its still a SSPP level decision.
>>
>> So even if we add P010 UBWC formats later to the list of supported 
>> formats, what we will do is add that feature bit alone in the Vig 
>> SSPP's feature mask of that chipset and based on that all the P010 
>> UBWC formats for the virtual planes.
>>
>> But if we follow your approach, we will add another array called 
>> plane_formats_p010_ubwc and add that to each chipset which will 
>> support it.
> 
> sspp->sblk->formats_list is constant, so we will have to add another 
> formats array anyway.
> 
Not to each chipset. Yes you will have one new array for P010 UBWC 
formats which you will use to do the plane_init() if any of the Vig 
SSPPs have the feature bit set.

As opposed to adding the format_list to each chipset like you are doing now.

Its just a decision of whether you want to expand the catalog to have 
this for each chipset OR not when you can easily make that decision at 
run time using the SSPP's capabilities.

BTW, all of this is just discussion for future. For this series, I think 
we both agree that you can just check if the chipset has any Vigs with 
CSC to populate YUV in the format list.

>> The only difference in idea is that, based on the SSPP's feature set 
>> of that chipset we can still determine that Vs adding it to each chipset.
>>
>>>>
>>>>>>
>>>>>>>>
>>>>>>>>> Note to myself: consider 
>>>>>>>>> dpu_mdss_cfg::{dma_formats,cursor_formats,vig_formats}. Either 
>>>>>>>>> migrate dpu_sspp_sub_blks::format_list users to these fields or 
>>>>>>>>> drop them.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Yes, I agree. There is no need to have format list in the 
>>>>>>>> sub_blk as for one type of SSPP, it supports the same format 
>>>>>>>> across DPU generations.
>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> Note: I think at some point we should have a closer look at 
>>>>>>>>>>> the list
>>>>>>>>>>> of supported formats and crosscheck that we do not have either
>>>>>>>>>>> unsupported formats being listed, or missing formats which 
>>>>>>>>>>> are not
>>>>>>>>>>> listed as supported.
>>>>>>>>>>>
>>>>>
>>>
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes
  2023-03-21  1:18 ` [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes Dmitry Baryshkov
@ 2023-06-07 21:05   ` Abhinav Kumar
  2023-06-07 21:56     ` Dmitry Baryshkov
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-07 21:05 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
> Only several SSPP blocks support such features as YUV output or scaling,
> thus different DRM planes have different features.  Properly utilizing
> all planes requires the attention of the compositor, who should
> prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
> to end up in a situation when all featureful planes are already
> allocated for simple windows, leaving no spare plane for YUV playback.
> 
> To solve this problem make all planes virtual. Each plane is registered
> as if it supports all possible features, but then at the runtime during
> the atomic_check phase the driver selects backing SSPP block for each
> plane.
> 
> Note, this does not provide support for using two different SSPP blocks
> for a single plane or using two rectangles of an SSPP to drive two
> planes. Each plane still gets its own SSPP and can utilize either a solo
> rectangle or both multirect rectangles depending on the resolution.
> 
> Note #2: By default support for virtual planes is turned off and the
> driver still uses old code path with preallocated SSPP block for each
> plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
> kernel parameter.
> 
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---

There will be some rebase needed to switch back to encoder based 
allocation so I am not going to comment on those parts and will let you 
handle that when you post v3.

But my questions/comments below are for other things.

>   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  59 +++++--
>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 120 ++++++++++----
>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 187 ++++++++++++++++++----
>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  24 ++-
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c    |  65 ++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h    |  24 +++
>   7 files changed, 413 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 8ef191fd002d..cdece21b81c9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1273,6 +1273,29 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
>   	return 0;
>   }
>   
> +static int dpu_crtc_assign_plane_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
> +{
> +	struct dpu_global_state *global_state;
> +	struct drm_plane *plane;
> +	int rc;
> +
> +	global_state = dpu_kms_get_global_state(crtc_state->state);
> +	if (IS_ERR(global_state))
> +		return PTR_ERR(global_state);
> +
> +	dpu_rm_release_all_sspp(global_state, crtc);
> +
> +	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
> +		rc = dpu_plane_virtual_assign_resources(plane, crtc,
> +							global_state,
> +							crtc_state->state);
> +		if (rc)
> +			return rc;
> +	}
> +
> +	return 0;
> +}
> +
>   static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>   		struct drm_atomic_state *state)
>   {
> @@ -1281,7 +1304,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>   	struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
>   	struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
>   
> -	const struct drm_plane_state *pstate;
>   	struct drm_plane *plane;
>   
>   	int rc = 0;
> @@ -1294,6 +1316,13 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>   			return rc;
>   	}
>   
> +	if (dpu_use_virtual_planes &&
> +	    crtc_state->planes_changed) {
> +		rc = dpu_crtc_assign_plane_resources(crtc, crtc_state);
> +		if (rc < 0)
> +			return rc;
> +	}

Can you please explain a bit more about the planes_changed condition?

1) Are we doing this because the plane's atomic check happens before the 
CRTC atomic check?

2) So the DRM core sets this to true already when plane is switching 
CRTCs or being connected to a CRTC for the first time, we need to handle 
the conditions additional to that right?

3) If (2) is correct, arent there other conditions then to be handled 
for setting planes_changed to true?

Some examples include, switching from a scaling to non-scaling scenario, 
needing rotation vs not needing etc.

Basically it seems like all of this is handled within the reserve_sspp() 
function but if planes_changes is not set then that wont get invoked at all.


> +
>   	if (!crtc_state->enable || !crtc_state->active) {
>   		DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
>   				crtc->base.id, crtc_state->enable,
> @@ -1311,20 +1340,30 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>   	if (cstate->num_mixers)
>   		_dpu_crtc_setup_lm_bounds(crtc, crtc_state);
>   
> -	/* FIXME: move this to dpu_plane_atomic_check? */
> -	drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
> -		struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate);
> -
> -		if (IS_ERR_OR_NULL(pstate)) {
> -			rc = PTR_ERR(pstate);
> -			DPU_ERROR("%s: failed to get plane%d state, %d\n",
> -					dpu_crtc->name, plane->base.id, rc);
> -			return rc;
> +	drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
> +		const struct drm_plane_state *pstate;
> +		struct dpu_plane_state *dpu_pstate;
> +
> +		pstate = drm_atomic_get_plane_state(crtc_state->state, plane);
> +		if (IS_ERR(pstate))
> +			return PTR_ERR(pstate);
> +
> +		if (dpu_use_virtual_planes) {
> +			/*
> +			 * In case of virtual planes, the plane's atomic_check
> +			 * is a shortcut. Perform actual check here, after
> +			 * allocating SSPPs.
> +			 */
> +			rc = dpu_plane_atomic_check(plane, crtc_state->state);
> +			if (rc)
> +				return rc;
>   		}
>   
>   		if (!pstate->visible)
>   			continue;
>   
> +		/* FIXME: move this to dpu_plane_atomic_check? */
> +		dpu_pstate = to_dpu_plane_state(pstate);

Anything prevents us from doing it even now instead of a FIXME?

>   		dpu_pstate->needs_dirtyfb = needs_dirtyfb;
>   	}
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index 35194262e628..487bb19ee9d6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -50,6 +50,9 @@
>   #define DPU_DEBUGFS_DIR "msm_dpu"
>   #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
>   
> +bool dpu_use_virtual_planes = false;
> +module_param(dpu_use_virtual_planes, bool, 0);
> +
>   static int dpu_kms_hw_init(struct msm_kms *kms);
>   static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
>   
> @@ -735,38 +738,54 @@ static int _dpu_kms_setup_displays(struct drm_device *dev,
>   	return rc;
>   }
>   
> -#define MAX_PLANES 20
> -static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
> +static int dpu_kms_create_virtual_planes(struct dpu_kms *dpu_kms,
> +					 int max_crtc_count,
> +					 struct drm_plane **primary_planes,
> +					 struct drm_plane **cursor_planes)
>   {
> -	struct drm_device *dev;
> -	struct drm_plane *primary_planes[MAX_PLANES], *plane;
> -	struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
> -	struct drm_crtc *crtc;
> -	struct drm_encoder *encoder;
> -	unsigned int num_encoders;
> +	const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
> +	struct drm_device *dev = dpu_kms->dev;
> +	int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
> +	struct drm_plane *plane;
>   
> -	struct msm_drm_private *priv;
> -	const struct dpu_mdss_cfg *catalog;
> +	/* Create the planes, keeping track of one primary/cursor per crtc */
> +	for (i = 0; i < catalog->sspp_count; i++) {
> +		enum drm_plane_type type;
>   
> -	int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
> -	int max_crtc_count;
> -	dev = dpu_kms->dev;
> -	priv = dev->dev_private;
> -	catalog = dpu_kms->catalog;
> +		if (primary_planes_idx < max_crtc_count)
> +			type = DRM_PLANE_TYPE_PRIMARY;
> +		else if (cursor_planes_idx < max_crtc_count)
> +			type = DRM_PLANE_TYPE_CURSOR;
> +		else
> +			type = DRM_PLANE_TYPE_OVERLAY;
>   
> -	/*
> -	 * Create encoder and query display drivers to create
> -	 * bridges and connectors
> -	 */
> -	ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
> -	if (ret)
> -		return ret;
> +		DPU_DEBUG("Create plane type %d\n", type);
>   
> -	num_encoders = 0;
> -	drm_for_each_encoder(encoder, dev)
> -		num_encoders++;
> +		plane = dpu_plane_init_virtual(dev, type, (1UL << max_crtc_count) - 1);
> +		if (IS_ERR(plane)) {
> +			DPU_ERROR("dpu_plane_init failed\n");
> +			ret = PTR_ERR(plane);
> +			return ret;
> +		}
>   
> -	max_crtc_count = min(catalog->mixer_count, num_encoders);
> +		if (type == DRM_PLANE_TYPE_CURSOR)
> +			cursor_planes[cursor_planes_idx++] = plane;
> +		else if (type == DRM_PLANE_TYPE_PRIMARY)
> +			primary_planes[primary_planes_idx++] = plane;
> +	}
> +
> +	return primary_planes_idx;
> +}
> +
> +static int dpu_kms_create_planes(struct dpu_kms *dpu_kms,
> +				 int max_crtc_count,
> +				 struct drm_plane **primary_planes,
> +				 struct drm_plane **cursor_planes)
> +{
> +	const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
> +	struct drm_device *dev = dpu_kms->dev;
> +	int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
> +	struct drm_plane *plane;
>   
>   	/* Create the planes, keeping track of one primary/cursor per crtc */
>   	for (i = 0; i < catalog->sspp_count; i++) {
> @@ -784,8 +803,8 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
>   			  type, catalog->sspp[i].features,
>   			  catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR));
>   
> -		plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
> -				       (1UL << max_crtc_count) - 1);
> +		plane = dpu_plane_init_sspp(dev, catalog->sspp[i].id, type,
> +					    (1UL << max_crtc_count) - 1);
>   		if (IS_ERR(plane)) {
>   			DPU_ERROR("dpu_plane_init failed\n");
>   			ret = PTR_ERR(plane);
> @@ -798,7 +817,50 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
>   			primary_planes[primary_planes_idx++] = plane;
>   	}
>   
> -	max_crtc_count = min(max_crtc_count, primary_planes_idx);
> +	return primary_planes_idx;
> +}
> +
> +#define MAX_PLANES 20
> +static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
> +{
> +	struct drm_device *dev;
> +	struct drm_plane *primary_planes[MAX_PLANES];
> +	struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
> +	struct drm_crtc *crtc;
> +	struct drm_encoder *encoder;
> +	unsigned int num_encoders;
> +
> +	struct msm_drm_private *priv;
> +	const struct dpu_mdss_cfg *catalog;
> +	int i, ret;
> +	int max_crtc_count;
> +
> +	dev = dpu_kms->dev;
> +	priv = dev->dev_private;
> +	catalog = dpu_kms->catalog;
> +
> +	/*
> +	 * Create encoder and query display drivers to create
> +	 * bridges and connectors
> +	 */
> +	ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
> +	if (ret)
> +		return ret;
> +
> +	num_encoders = 0;
> +	drm_for_each_encoder(encoder, dev)
> +		num_encoders++;
> +
> +	max_crtc_count = min(catalog->mixer_count, num_encoders);
> +
> +	if (dpu_use_virtual_planes)
> +		ret = dpu_kms_create_virtual_planes(dpu_kms, max_crtc_count, primary_planes, cursor_planes);
> +	else
> +		ret = dpu_kms_create_planes(dpu_kms, max_crtc_count, primary_planes, cursor_planes);
> +	if (ret < 0)
> +		return ret;
> +
> +	max_crtc_count = min(max_crtc_count, ret);
>   
>   	/* Create one CRTC per encoder */
>   	for (i = 0; i < max_crtc_count; i++) {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 934874eb2248..9f6478f0ced6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -65,6 +65,8 @@
>   
>   #define DPU_NAME_SIZE  12
>   
> +extern bool dpu_use_virtual_planes;
> +
>   struct dpu_kms {
>   	struct msm_kms base;
>   	struct drm_device *dev;
> @@ -134,6 +136,8 @@ struct dpu_global_state {
>   	uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
>   	uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>   	uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> +
> +	uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE];
>   };
>   
>   struct dpu_global_state
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> index cf17075676d5..ee906c276aa5 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
> @@ -837,8 +837,77 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu,
>   	return 0;
>   }
>   
> -static int dpu_plane_atomic_check(struct drm_plane *plane,
> -				  struct drm_atomic_state *state)
> +static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
> +					  struct drm_atomic_state *state)
> +{
> +	struct drm_plane_state *plane_state =
> +		drm_atomic_get_plane_state(state, plane);
> +	struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
> +	const struct dpu_format *format;
> +	struct drm_crtc_state *crtc_state;
> +
> +	/*
> +	 * Main part of checks, including drm_atomic_helper_check_plane_state()
> +	 * is called from dpu_crtc_atomic_check(). Do minimal processing here.
> +	 */
> +
> +	if (!plane_state->fb) {
> +		plane_state->visible = false;
> +
> +		/* resources are freed by dpu_crtc_atomic_check(), but clean them here */
> +		pstate->pipe.sspp = NULL;
> +		pstate->r_pipe.sspp = NULL;
> +
> +		return 0;
> +	}
> +
> +	format = to_dpu_format(msm_framebuffer_format(plane_state->fb));
> +	crtc_state = drm_atomic_get_new_crtc_state(state, plane_state->crtc);
> +
> +	/* force resource reallocation if the format of FB has changed */
> +	if (pstate->saved_fmt != format) {
> +		crtc_state->planes_changed = true;
> +		pstate->saved_fmt = format;
> +	}
> +
> +	return 0;
> +}
> +
> +int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
> +				       struct drm_crtc *crtc,
> +				       struct dpu_global_state *global_state,
> +				       struct drm_atomic_state *state)
> +{
> +	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
> +	struct dpu_plane_state *pstate;
> +	struct drm_plane_state *plane_state;
> +	struct dpu_hw_sspp *hw_sspp;
> +	bool yuv, scale, rot90;
> +
> +	plane_state = drm_atomic_get_plane_state(state, plane);
> +	if (IS_ERR(plane_state))
> +		return PTR_ERR(plane_state);
> +
> +	yuv = plane_state->fb ?
> +		DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(plane_state->fb))) :
> +		false;
> +	scale = (plane_state->src_w >> 16 != plane_state->crtc_w) ||
> +		(plane_state->src_h >> 16 != plane_state->crtc_h);
> +
> +	rot90 = drm_rotation_90_or_270(plane_state->rotation);
> +
> +	hw_sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, yuv, scale, rot90);

I think this parameter list is going to explode. Shall we introduce a 
dpu_plane_sspp_requirements to store these?

> +	if (!hw_sspp)
> +		return -ENODEV;
> +
> +	pstate = to_dpu_plane_state(plane_state);
> +	pstate->pipe.sspp = hw_sspp;
> +
> +	return 0;
> +}
> +
> +int dpu_plane_atomic_check(struct drm_plane *plane,
> +			   struct drm_atomic_state *state)
>   {
>   	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
>   										 plane);
> @@ -863,8 +932,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
>   		crtc_state = drm_atomic_get_new_crtc_state(state,
>   							   new_plane_state->crtc);
>   
> -	pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
> -	r_pipe->sspp = NULL;
> +	if (pdpu->pipe != SSPP_NONE) {
> +		pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
> +		r_pipe->sspp = NULL;
> +	}
>   
>   	pipe_hw_caps = pstate->pipe.sspp->cap;
>   	sblk = pstate->pipe.sspp->cap->sblk;
> @@ -1358,12 +1429,14 @@ static void dpu_plane_atomic_print_state(struct drm_printer *p,
>   
>   	drm_printf(p, "\tstage=%d\n", pstate->stage);
>   
> -	drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
> -	drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode));
> -	drm_printf(p, "\tmultirect_index[0]=%s\n",
> -		   dpu_get_multirect_index(pipe->multirect_index));
> -	drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect));
> -	drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect));
> +	if (pipe->sspp) {
> +		drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
> +		drm_printf(p, "\tmultirect_mode[0]=%s\n", dpu_get_multirect_mode(pipe->multirect_mode));
> +		drm_printf(p, "\tmultirect_index[0]=%s\n",
> +			   dpu_get_multirect_index(pipe->multirect_index));
> +		drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect));
> +		drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect));
> +	}
>   
>   	if (r_pipe->sspp) {
>   		drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
> @@ -1453,18 +1526,30 @@ static const struct drm_plane_helper_funcs dpu_plane_helper_funcs = {
>   		.atomic_update = dpu_plane_atomic_update,
>   };
>   
> +/*
> + * For virtual planes atomic_check is called from dpu_crtc_atomic_check(),
> + * after CRTC code assigning SSPP.
> + */
> +static const struct drm_plane_helper_funcs dpu_plane_virtual_helper_funcs = {
> +	.prepare_fb = dpu_plane_prepare_fb,
> +	.cleanup_fb = dpu_plane_cleanup_fb,
> +	.atomic_check = dpu_plane_virtual_atomic_check,
> +	.atomic_update = dpu_plane_atomic_update,
> +};
> +
>   /* initialize plane */
> -struct drm_plane *dpu_plane_init(struct drm_device *dev,
> -		uint32_t pipe, enum drm_plane_type type,
> -		unsigned long possible_crtcs)
> +static struct drm_plane *dpu_plane_init(struct drm_device *dev,
> +					enum drm_plane_type type,
> +					unsigned long possible_crtcs,
> +					bool inline_rotation,
> +					const uint32_t *format_list,
> +					uint32_t num_formats,
> +					enum dpu_sspp pipe)
>   {
>   	struct drm_plane *plane = NULL;
> -	const uint32_t *format_list;
>   	struct dpu_plane *pdpu;
>   	struct msm_drm_private *priv = dev->dev_private;
>   	struct dpu_kms *kms = to_dpu_kms(priv->kms);
> -	struct dpu_hw_sspp *pipe_hw;
> -	uint32_t num_formats;
>   	uint32_t supported_rotations;
>   	int ret = -EINVAL;
>   
> @@ -1480,16 +1565,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
>   	plane = &pdpu->base;
>   	pdpu->pipe = pipe;
>   
> -	/* initialize underlying h/w driver */
> -	pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
> -	if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
> -		DPU_ERROR("[%u]SSPP is invalid\n", pipe);
> -		goto clean_plane;
> -	}
> -
> -	format_list = pipe_hw->cap->sblk->format_list;
> -	num_formats = pipe_hw->cap->sblk->num_formats;
> -
>   	ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
>   				format_list, num_formats,
>   				supported_format_modifiers, type, NULL);
> @@ -1510,7 +1585,7 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
>   
>   	supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180;
>   
> -	if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION))
> +	if (inline_rotation)
>   		supported_rotations |= DRM_MODE_ROTATE_MASK;
>   
>   	drm_plane_create_rotation_property(plane,
> @@ -1519,8 +1594,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
>   	drm_plane_enable_fb_damage_clips(plane);
>   
>   	/* success! finalize initialization */
> -	drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
> -
>   	mutex_init(&pdpu->lock);
>   
>   	DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
> @@ -1531,3 +1604,59 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
>   	kfree(pdpu);
>   	return ERR_PTR(ret);
>   }
> +
> +struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
> +				      uint32_t pipe, enum drm_plane_type type,
> +				      unsigned long possible_crtcs)
> +{
> +	struct drm_plane *plane = NULL;
> +	struct msm_drm_private *priv = dev->dev_private;
> +	struct dpu_kms *kms = to_dpu_kms(priv->kms);
> +	struct dpu_hw_sspp *pipe_hw;
> +
> +	/* initialize underlying h/w driver */
> +	pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
> +	if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
> +		DPU_ERROR("[%u]SSPP is invalid\n", pipe);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +
> +	plane = dpu_plane_init(dev, type, possible_crtcs,
> +			       pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION),
> +			       pipe_hw->cap->sblk->format_list,
> +			       pipe_hw->cap->sblk->num_formats,
> +			       pipe);
> +	if (IS_ERR(plane))
> +		return plane;
> +
> +	drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
> +
> +	DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
> +					pipe, plane->base.id);
> +
> +	return plane;
> +}
> +
> +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
> +					 enum drm_plane_type type,
> +					 unsigned long possible_crtcs)
> +{
> +	struct drm_plane *plane = NULL;
> +	struct msm_drm_private *priv = dev->dev_private;
> +	struct dpu_kms *kms = to_dpu_kms(priv->kms);
> +
> +	plane = dpu_plane_init(dev, type, possible_crtcs,
> +			       kms->catalog->caps->has_inline_rot,
> +			       kms->catalog->caps->format_list,
> +			       kms->catalog->caps->num_formats,
> +			       SSPP_NONE);
> +	if (IS_ERR(plane))
> +		return plane;
> +
> +	drm_plane_helper_add(plane, &dpu_plane_virtual_helper_funcs);
> +
> +	DPU_DEBUG("%s created virtual id:%u\n", plane->name, plane->base.id);
> +
> +	return plane;
> +}

Overall I am satisfied with the split of the dpu_plane_init() function 
into virtual vs non-virtual and happy its protected with a modparam.

> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
> index abd6b21a049b..cb1e31ef0d3f 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
> @@ -31,6 +31,7 @@
>    * @plane_clk: calculated clk per plane
>    * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly flushed
>    * @rotation: simplified drm rotation hint
> + * @saved_fmt: format used by the plane's FB, saved for for virtual plane support
>    */
>   struct dpu_plane_state {
>   	struct drm_plane_state base;
> @@ -48,6 +49,8 @@ struct dpu_plane_state {
>   
>   	bool needs_dirtyfb;
>   	unsigned int rotation;
> +
> +	const struct dpu_format *saved_fmt;
>   };
>   
>   #define to_dpu_plane_state(x) \
> @@ -66,17 +69,27 @@ void dpu_plane_flush(struct drm_plane *plane);
>   void dpu_plane_set_error(struct drm_plane *plane, bool error);
>   
>   /**
> - * dpu_plane_init - create new dpu plane for the given pipe
> + * dpu_plane_init_sspp - create new dpu plane for the given pipe
>    * @dev:   Pointer to DRM device
>    * @pipe:  dpu hardware pipe identifier
>    * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
>    * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
>    *
>    */
> -struct drm_plane *dpu_plane_init(struct drm_device *dev,
> +struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
>   		uint32_t pipe, enum drm_plane_type type,
>   		unsigned long possible_crtcs);
>   
> +/**
> + * dpu_plane_init_virtual - create new dpu virtualized plane
> + * @dev:   Pointer to DRM device
> + * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
> + * @possible_crtcs: bitmask of crtc that can be attached to the given pipe
> + */
> +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
> +					 enum drm_plane_type type,
> +					 unsigned long possible_crtcs);
> +
>   /**
>    * dpu_plane_color_fill - enables color fill on plane
>    * @plane:  Pointer to DRM plane object
> @@ -93,4 +106,11 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable);
>   static inline void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable) {}
>   #endif
>   
> +int dpu_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state);
> +
> +int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
> +				       struct drm_crtc *crtc,
> +				       struct dpu_global_state *global_state,
> +				       struct drm_atomic_state *state);
> +
>   #endif /* _DPU_PLANE_H_ */
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index f0a94008d17a..6130ac87d7e3 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -607,6 +607,71 @@ int dpu_rm_reserve(
>   	return ret;
>   }
>   
> +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
> +					struct dpu_global_state *global_state,
> +					struct drm_crtc *crtc,
> +					bool yuv, bool scale, bool rot90)
> +{

as noted above, lets consider adding a dpu_plane_sspp_requirements 
struct instead of just expanding the param list.

> +	uint32_t crtc_id = crtc->base.id;
> +	struct dpu_hw_sspp *hw_sspp;
> +	bool retry = false;
> +	int i;
> +
> +retry_loop:
> +	for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) {
> +		if (!rm->hw_sspp[i])
> +			continue;
> +
> +		if (global_state->sspp_to_crtc_id[i])
> +			continue;
> +
> +		hw_sspp = rm->hw_sspp[i];
> +
> +		/* skip incompatible planes */
> +		if (scale && !(hw_sspp->cap->features & DPU_SSPP_SCALER))
> +			continue;
> +
> +		if (yuv && !(hw_sspp->cap->features & DPU_SSPP_CSC_ANY))
> +			continue;
> +
> +		if (rot90 && !(hw_sspp->cap->features & DPU_SSPP_INLINE_ROTATION))
> +			continue;
> +

These are sufficient conditions to start with for the use-cases I can 
think of.

> +		/*
> +		 * For non-yuv, non-scaled planes try to find simple (DMA)
> +		 * plane, fallback to VIG on a second try.
> +		 *
> +		 * This way we'd leave VIG sspps to be later used for YUV formats.
> +		 */
> +
> +		if (!scale && !yuv && !rot90 && !retry &&
> +		    (hw_sspp->cap->features &
> +		     (DPU_SSPP_SCALER | DPU_SSPP_CSC_ANY | DPU_SSPP_INLINE_ROTATION)))
> +			continue;
> +
> +		global_state->sspp_to_crtc_id[hw_sspp->idx - SSPP_NONE] = crtc_id;
> +
> +		return hw_sspp;
> +	}
> +
> +	/* If we were looking for DMA plane, retry looking for VIG plane */
> +	if (!scale && !yuv && !retry) {
> +		retry = true;
> +		goto retry_loop;
> +	}
> +
> +	return NULL;
> +}
> +
> +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
> +			     struct drm_crtc *crtc)
> +{
> +	uint32_t crtc_id = crtc->base.id;
> +
> +	_dpu_rm_clear_mapping(global_state->sspp_to_crtc_id,
> +		ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id);
> +}
> +
>   int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>   	struct dpu_global_state *global_state, struct drm_crtc *crtc,
>   	enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index f402bec8322b..5bf6740ecb45 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -82,6 +82,30 @@ int dpu_rm_reserve(
>   void dpu_rm_release(struct dpu_global_state *global_state,
>   		struct drm_crtc *crtc);
>   
> +/**
> + * dpu_rm_reserve_sspp - Reserve the required SSPP for the provided CRTC
> + * @rm: DPU Resource Manager handle
> + * @global_state: private global state
> + * @crtc: DRM CRTC handle
> + * @yuv: required SSPP supporting YUV formats
> + * @scale: required SSPP supporting scaling
> + * @rot90: required SSPP supporting inline 90 degree rotation
> + */
> +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
> +					struct dpu_global_state *global_state,
> +					struct drm_crtc *crtc,
> +					bool yuv, bool scale, bool rot90);
> +
> +/**
> + * dpu_rm_release_all_sspp - Given the CRTC, release all SSPP
> + *	blocks previously reserved for that use case.
> + * @rm: DPU Resource Manager handle
> + * @crtc: DRM CRTC handle
> + * @Return: 0 on Success otherwise -ERROR
> + */
> +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
> +			     struct drm_crtc *crtc);
> +
>   /**
>    * Get hw resources of the given type that are assigned to this encoder.
>    */

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes
  2023-06-07 21:05   ` Abhinav Kumar
@ 2023-06-07 21:56     ` Dmitry Baryshkov
  2023-06-08 19:51       ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Dmitry Baryshkov @ 2023-06-07 21:56 UTC (permalink / raw)
  To: Abhinav Kumar, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno

On 08/06/2023 00:05, Abhinav Kumar wrote:
> 
> 
> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>> Only several SSPP blocks support such features as YUV output or scaling,
>> thus different DRM planes have different features.  Properly utilizing
>> all planes requires the attention of the compositor, who should
>> prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
>> to end up in a situation when all featureful planes are already
>> allocated for simple windows, leaving no spare plane for YUV playback.
>>
>> To solve this problem make all planes virtual. Each plane is registered
>> as if it supports all possible features, but then at the runtime during
>> the atomic_check phase the driver selects backing SSPP block for each
>> plane.
>>
>> Note, this does not provide support for using two different SSPP blocks
>> for a single plane or using two rectangles of an SSPP to drive two
>> planes. Each plane still gets its own SSPP and can utilize either a solo
>> rectangle or both multirect rectangles depending on the resolution.
>>
>> Note #2: By default support for virtual planes is turned off and the
>> driver still uses old code path with preallocated SSPP block for each
>> plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
>> kernel parameter.
>>
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> ---
> 
> There will be some rebase needed to switch back to encoder based 
> allocation so I am not going to comment on those parts and will let you 
> handle that when you post v3.
> 
> But my questions/comments below are for other things.
> 
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  59 +++++--
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 120 ++++++++++----
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 187 ++++++++++++++++++----
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  24 ++-
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c    |  65 ++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h    |  24 +++
>>   7 files changed, 413 insertions(+), 70 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index 8ef191fd002d..cdece21b81c9 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -1273,6 +1273,29 @@ static int dpu_crtc_assign_resources(struct 
>> drm_crtc *crtc, struct drm_crtc_stat
>>       return 0;
>>   }
>> +static int dpu_crtc_assign_plane_resources(struct drm_crtc *crtc, 
>> struct drm_crtc_state *crtc_state)
>> +{
>> +    struct dpu_global_state *global_state;
>> +    struct drm_plane *plane;
>> +    int rc;
>> +
>> +    global_state = dpu_kms_get_global_state(crtc_state->state);
>> +    if (IS_ERR(global_state))
>> +        return PTR_ERR(global_state);
>> +
>> +    dpu_rm_release_all_sspp(global_state, crtc);
>> +
>> +    drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
>> +        rc = dpu_plane_virtual_assign_resources(plane, crtc,
>> +                            global_state,
>> +                            crtc_state->state);
>> +        if (rc)
>> +            return rc;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>>           struct drm_atomic_state *state)
>>   {
>> @@ -1281,7 +1304,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc 
>> *crtc,
>>       struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
>>       struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
>> -    const struct drm_plane_state *pstate;
>>       struct drm_plane *plane;
>>       int rc = 0;
>> @@ -1294,6 +1316,13 @@ static int dpu_crtc_atomic_check(struct 
>> drm_crtc *crtc,
>>               return rc;
>>       }
>> +    if (dpu_use_virtual_planes &&
>> +        crtc_state->planes_changed) {
>> +        rc = dpu_crtc_assign_plane_resources(crtc, crtc_state);
>> +        if (rc < 0)
>> +            return rc;
>> +    }
> 
> Can you please explain a bit more about the planes_changed condition?
> 
> 1) Are we doing this because the plane's atomic check happens before the 
> CRTC atomic check?

Yes. Another alternative would be to stop using 
drm_atomic_helper_check() and implement our own code instead, inverting 
the plane / CRTC check order.

> 
> 2) So the DRM core sets this to true already when plane is switching 
> CRTCs or being connected to a CRTC for the first time, we need to handle 
> the conditions additional to that right?

Nit: it is not possible to switch CRTCs. Plane first has to be 
disconnected and then to be connected to another CRTC.

> 
> 3) If (2) is correct, arent there other conditions then to be handled 
> for setting planes_changed to true?
> 
> Some examples include, switching from a scaling to non-scaling scenario, 
> needing rotation vs not needing etc.

Setting the plane_changed is not required. Both 
drm_atomic_helper_disable_plane() and drm_atomic_helper_update_plane() 
will add the plane to the state. Then drm_atomic_helper_check_planes() 
will call drm_atomic_helper_plane_changed(), setting 
{old_,new_}crtc_state->planes_changed.

I should check if the format check below is required or not. It looks 
like I can drop that clause too.


> 
> Basically it seems like all of this is handled within the reserve_sspp() 
> function but if planes_changes is not set then that wont get invoked at 
> all.
> 
> 
>> +
>>       if (!crtc_state->enable || !crtc_state->active) {
>>           DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip 
>> atomic_check\n",
>>                   crtc->base.id, crtc_state->enable,
>> @@ -1311,20 +1340,30 @@ static int dpu_crtc_atomic_check(struct 
>> drm_crtc *crtc,
>>       if (cstate->num_mixers)
>>           _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
>> -    /* FIXME: move this to dpu_plane_atomic_check? */
>> -    drm_atomic_crtc_state_for_each_plane_state(plane, pstate, 
>> crtc_state) {
>> -        struct dpu_plane_state *dpu_pstate = to_dpu_plane_state(pstate);
>> -
>> -        if (IS_ERR_OR_NULL(pstate)) {
>> -            rc = PTR_ERR(pstate);
>> -            DPU_ERROR("%s: failed to get plane%d state, %d\n",
>> -                    dpu_crtc->name, plane->base.id, rc);
>> -            return rc;
>> +    drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
>> +        const struct drm_plane_state *pstate;
>> +        struct dpu_plane_state *dpu_pstate;
>> +
>> +        pstate = drm_atomic_get_plane_state(crtc_state->state, plane);
>> +        if (IS_ERR(pstate))
>> +            return PTR_ERR(pstate);
>> +
>> +        if (dpu_use_virtual_planes) {
>> +            /*
>> +             * In case of virtual planes, the plane's atomic_check
>> +             * is a shortcut. Perform actual check here, after
>> +             * allocating SSPPs.
>> +             */
>> +            rc = dpu_plane_atomic_check(plane, crtc_state->state);
>> +            if (rc)
>> +                return rc;
>>           }
>>           if (!pstate->visible)
>>               continue;
>> +        /* FIXME: move this to dpu_plane_atomic_check? */
>> +        dpu_pstate = to_dpu_plane_state(pstate);
> 
> Anything prevents us from doing it even now instead of a FIXME?

The question mark at the end. I'm not sure that moving it to the 
plane_atomic_check would actually help. And please note that it is the 
old code (and old FIXME) being moved around.

> 
>>           dpu_pstate->needs_dirtyfb = needs_dirtyfb;
>>       }
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> index 35194262e628..487bb19ee9d6 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>> @@ -50,6 +50,9 @@
>>   #define DPU_DEBUGFS_DIR "msm_dpu"
>>   #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
>> +bool dpu_use_virtual_planes = false;
>> +module_param(dpu_use_virtual_planes, bool, 0);
>> +
>>   static int dpu_kms_hw_init(struct msm_kms *kms);
>>   static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
>> @@ -735,38 +738,54 @@ static int _dpu_kms_setup_displays(struct 
>> drm_device *dev,
>>       return rc;
>>   }
>> -#define MAX_PLANES 20
>> -static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
>> +static int dpu_kms_create_virtual_planes(struct dpu_kms *dpu_kms,
>> +                     int max_crtc_count,
>> +                     struct drm_plane **primary_planes,
>> +                     struct drm_plane **cursor_planes)
>>   {
>> -    struct drm_device *dev;
>> -    struct drm_plane *primary_planes[MAX_PLANES], *plane;
>> -    struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
>> -    struct drm_crtc *crtc;
>> -    struct drm_encoder *encoder;
>> -    unsigned int num_encoders;
>> +    const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
>> +    struct drm_device *dev = dpu_kms->dev;
>> +    int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
>> +    struct drm_plane *plane;
>> -    struct msm_drm_private *priv;
>> -    const struct dpu_mdss_cfg *catalog;
>> +    /* Create the planes, keeping track of one primary/cursor per 
>> crtc */
>> +    for (i = 0; i < catalog->sspp_count; i++) {
>> +        enum drm_plane_type type;
>> -    int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
>> -    int max_crtc_count;
>> -    dev = dpu_kms->dev;
>> -    priv = dev->dev_private;
>> -    catalog = dpu_kms->catalog;
>> +        if (primary_planes_idx < max_crtc_count)
>> +            type = DRM_PLANE_TYPE_PRIMARY;
>> +        else if (cursor_planes_idx < max_crtc_count)
>> +            type = DRM_PLANE_TYPE_CURSOR;
>> +        else
>> +            type = DRM_PLANE_TYPE_OVERLAY;
>> -    /*
>> -     * Create encoder and query display drivers to create
>> -     * bridges and connectors
>> -     */
>> -    ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
>> -    if (ret)
>> -        return ret;
>> +        DPU_DEBUG("Create plane type %d\n", type);
>> -    num_encoders = 0;
>> -    drm_for_each_encoder(encoder, dev)
>> -        num_encoders++;
>> +        plane = dpu_plane_init_virtual(dev, type, (1UL << 
>> max_crtc_count) - 1);
>> +        if (IS_ERR(plane)) {
>> +            DPU_ERROR("dpu_plane_init failed\n");
>> +            ret = PTR_ERR(plane);
>> +            return ret;
>> +        }
>> -    max_crtc_count = min(catalog->mixer_count, num_encoders);
>> +        if (type == DRM_PLANE_TYPE_CURSOR)
>> +            cursor_planes[cursor_planes_idx++] = plane;
>> +        else if (type == DRM_PLANE_TYPE_PRIMARY)
>> +            primary_planes[primary_planes_idx++] = plane;
>> +    }
>> +
>> +    return primary_planes_idx;
>> +}
>> +
>> +static int dpu_kms_create_planes(struct dpu_kms *dpu_kms,
>> +                 int max_crtc_count,
>> +                 struct drm_plane **primary_planes,
>> +                 struct drm_plane **cursor_planes)
>> +{
>> +    const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
>> +    struct drm_device *dev = dpu_kms->dev;
>> +    int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
>> +    struct drm_plane *plane;
>>       /* Create the planes, keeping track of one primary/cursor per 
>> crtc */
>>       for (i = 0; i < catalog->sspp_count; i++) {
>> @@ -784,8 +803,8 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms 
>> *dpu_kms)
>>                 type, catalog->sspp[i].features,
>>                 catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR));
>> -        plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
>> -                       (1UL << max_crtc_count) - 1);
>> +        plane = dpu_plane_init_sspp(dev, catalog->sspp[i].id, type,
>> +                        (1UL << max_crtc_count) - 1);
>>           if (IS_ERR(plane)) {
>>               DPU_ERROR("dpu_plane_init failed\n");
>>               ret = PTR_ERR(plane);
>> @@ -798,7 +817,50 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms 
>> *dpu_kms)
>>               primary_planes[primary_planes_idx++] = plane;
>>       }
>> -    max_crtc_count = min(max_crtc_count, primary_planes_idx);
>> +    return primary_planes_idx;
>> +}
>> +
>> +#define MAX_PLANES 20
>> +static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
>> +{
>> +    struct drm_device *dev;
>> +    struct drm_plane *primary_planes[MAX_PLANES];
>> +    struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
>> +    struct drm_crtc *crtc;
>> +    struct drm_encoder *encoder;
>> +    unsigned int num_encoders;
>> +
>> +    struct msm_drm_private *priv;
>> +    const struct dpu_mdss_cfg *catalog;
>> +    int i, ret;
>> +    int max_crtc_count;
>> +
>> +    dev = dpu_kms->dev;
>> +    priv = dev->dev_private;
>> +    catalog = dpu_kms->catalog;
>> +
>> +    /*
>> +     * Create encoder and query display drivers to create
>> +     * bridges and connectors
>> +     */
>> +    ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
>> +    if (ret)
>> +        return ret;
>> +
>> +    num_encoders = 0;
>> +    drm_for_each_encoder(encoder, dev)
>> +        num_encoders++;
>> +
>> +    max_crtc_count = min(catalog->mixer_count, num_encoders);
>> +
>> +    if (dpu_use_virtual_planes)
>> +        ret = dpu_kms_create_virtual_planes(dpu_kms, max_crtc_count, 
>> primary_planes, cursor_planes);
>> +    else
>> +        ret = dpu_kms_create_planes(dpu_kms, max_crtc_count, 
>> primary_planes, cursor_planes);
>> +    if (ret < 0)
>> +        return ret;
>> +
>> +    max_crtc_count = min(max_crtc_count, ret);
>>       /* Create one CRTC per encoder */
>>       for (i = 0; i < max_crtc_count; i++) {
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> index 934874eb2248..9f6478f0ced6 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> @@ -65,6 +65,8 @@
>>   #define DPU_NAME_SIZE  12
>> +extern bool dpu_use_virtual_planes;
>> +
>>   struct dpu_kms {
>>       struct msm_kms base;
>>       struct drm_device *dev;
>> @@ -134,6 +136,8 @@ struct dpu_global_state {
>>       uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
>>       uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>       uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>> +
>> +    uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE];
>>   };
>>   struct dpu_global_state
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>> index cf17075676d5..ee906c276aa5 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>> @@ -837,8 +837,77 @@ static int dpu_plane_atomic_check_pipe(struct 
>> dpu_plane *pdpu,
>>       return 0;
>>   }
>> -static int dpu_plane_atomic_check(struct drm_plane *plane,
>> -                  struct drm_atomic_state *state)
>> +static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
>> +                      struct drm_atomic_state *state)
>> +{
>> +    struct drm_plane_state *plane_state =
>> +        drm_atomic_get_plane_state(state, plane);
>> +    struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
>> +    const struct dpu_format *format;
>> +    struct drm_crtc_state *crtc_state;
>> +
>> +    /*
>> +     * Main part of checks, including 
>> drm_atomic_helper_check_plane_state()
>> +     * is called from dpu_crtc_atomic_check(). Do minimal processing 
>> here.
>> +     */
>> +
>> +    if (!plane_state->fb) {
>> +        plane_state->visible = false;
>> +
>> +        /* resources are freed by dpu_crtc_atomic_check(), but clean 
>> them here */
>> +        pstate->pipe.sspp = NULL;
>> +        pstate->r_pipe.sspp = NULL;
>> +
>> +        return 0;
>> +    }
>> +
>> +    format = to_dpu_format(msm_framebuffer_format(plane_state->fb));
>> +    crtc_state = drm_atomic_get_new_crtc_state(state, 
>> plane_state->crtc);
>> +
>> +    /* force resource reallocation if the format of FB has changed */
>> +    if (pstate->saved_fmt != format) {
>> +        crtc_state->planes_changed = true;
>> +        pstate->saved_fmt = format;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
>> +                       struct drm_crtc *crtc,
>> +                       struct dpu_global_state *global_state,
>> +                       struct drm_atomic_state *state)
>> +{
>> +    struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
>> +    struct dpu_plane_state *pstate;
>> +    struct drm_plane_state *plane_state;
>> +    struct dpu_hw_sspp *hw_sspp;
>> +    bool yuv, scale, rot90;
>> +
>> +    plane_state = drm_atomic_get_plane_state(state, plane);
>> +    if (IS_ERR(plane_state))
>> +        return PTR_ERR(plane_state);
>> +
>> +    yuv = plane_state->fb ?
>> +        
>> DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(plane_state->fb))) :
>> +        false;
>> +    scale = (plane_state->src_w >> 16 != plane_state->crtc_w) ||
>> +        (plane_state->src_h >> 16 != plane_state->crtc_h);
>> +
>> +    rot90 = drm_rotation_90_or_270(plane_state->rotation);
>> +
>> +    hw_sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, 
>> yuv, scale, rot90);
> 
> I think this parameter list is going to explode. Shall we introduce a 
> dpu_plane_sspp_requirements to store these?

SG.

> 
>> +    if (!hw_sspp)
>> +        return -ENODEV;
>> +
>> +    pstate = to_dpu_plane_state(plane_state);
>> +    pstate->pipe.sspp = hw_sspp;
>> +
>> +    return 0;
>> +}
>> +
>> +int dpu_plane_atomic_check(struct drm_plane *plane,
>> +               struct drm_atomic_state *state)
>>   {
>>       struct drm_plane_state *new_plane_state = 
>> drm_atomic_get_new_plane_state(state,
>>                                            plane);
>> @@ -863,8 +932,10 @@ static int dpu_plane_atomic_check(struct 
>> drm_plane *plane,
>>           crtc_state = drm_atomic_get_new_crtc_state(state,
>>                                  new_plane_state->crtc);
>> -    pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
>> -    r_pipe->sspp = NULL;
>> +    if (pdpu->pipe != SSPP_NONE) {
>> +        pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
>> +        r_pipe->sspp = NULL;
>> +    }
>>       pipe_hw_caps = pstate->pipe.sspp->cap;
>>       sblk = pstate->pipe.sspp->cap->sblk;
>> @@ -1358,12 +1429,14 @@ static void 
>> dpu_plane_atomic_print_state(struct drm_printer *p,
>>       drm_printf(p, "\tstage=%d\n", pstate->stage);
>> -    drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
>> -    drm_printf(p, "\tmultirect_mode[0]=%s\n", 
>> dpu_get_multirect_mode(pipe->multirect_mode));
>> -    drm_printf(p, "\tmultirect_index[0]=%s\n",
>> -           dpu_get_multirect_index(pipe->multirect_index));
>> -    drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&pipe_cfg->src_rect));
>> -    drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&pipe_cfg->dst_rect));
>> +    if (pipe->sspp) {
>> +        drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
>> +        drm_printf(p, "\tmultirect_mode[0]=%s\n", 
>> dpu_get_multirect_mode(pipe->multirect_mode));
>> +        drm_printf(p, "\tmultirect_index[0]=%s\n",
>> +               dpu_get_multirect_index(pipe->multirect_index));
>> +        drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&pipe_cfg->src_rect));
>> +        drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", 
>> DRM_RECT_ARG(&pipe_cfg->dst_rect));
>> +    }
>>       if (r_pipe->sspp) {
>>           drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
>> @@ -1453,18 +1526,30 @@ static const struct drm_plane_helper_funcs 
>> dpu_plane_helper_funcs = {
>>           .atomic_update = dpu_plane_atomic_update,
>>   };
>> +/*
>> + * For virtual planes atomic_check is called from 
>> dpu_crtc_atomic_check(),
>> + * after CRTC code assigning SSPP.
>> + */
>> +static const struct drm_plane_helper_funcs 
>> dpu_plane_virtual_helper_funcs = {
>> +    .prepare_fb = dpu_plane_prepare_fb,
>> +    .cleanup_fb = dpu_plane_cleanup_fb,
>> +    .atomic_check = dpu_plane_virtual_atomic_check,
>> +    .atomic_update = dpu_plane_atomic_update,
>> +};
>> +
>>   /* initialize plane */
>> -struct drm_plane *dpu_plane_init(struct drm_device *dev,
>> -        uint32_t pipe, enum drm_plane_type type,
>> -        unsigned long possible_crtcs)
>> +static struct drm_plane *dpu_plane_init(struct drm_device *dev,
>> +                    enum drm_plane_type type,
>> +                    unsigned long possible_crtcs,
>> +                    bool inline_rotation,
>> +                    const uint32_t *format_list,
>> +                    uint32_t num_formats,
>> +                    enum dpu_sspp pipe)
>>   {
>>       struct drm_plane *plane = NULL;
>> -    const uint32_t *format_list;
>>       struct dpu_plane *pdpu;
>>       struct msm_drm_private *priv = dev->dev_private;
>>       struct dpu_kms *kms = to_dpu_kms(priv->kms);
>> -    struct dpu_hw_sspp *pipe_hw;
>> -    uint32_t num_formats;
>>       uint32_t supported_rotations;
>>       int ret = -EINVAL;
>> @@ -1480,16 +1565,6 @@ struct drm_plane *dpu_plane_init(struct 
>> drm_device *dev,
>>       plane = &pdpu->base;
>>       pdpu->pipe = pipe;
>> -    /* initialize underlying h/w driver */
>> -    pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
>> -    if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
>> -        DPU_ERROR("[%u]SSPP is invalid\n", pipe);
>> -        goto clean_plane;
>> -    }
>> -
>> -    format_list = pipe_hw->cap->sblk->format_list;
>> -    num_formats = pipe_hw->cap->sblk->num_formats;
>> -
>>       ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
>>                   format_list, num_formats,
>>                   supported_format_modifiers, type, NULL);
>> @@ -1510,7 +1585,7 @@ struct drm_plane *dpu_plane_init(struct 
>> drm_device *dev,
>>       supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 
>> | DRM_MODE_ROTATE_180;
>> -    if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION))
>> +    if (inline_rotation)
>>           supported_rotations |= DRM_MODE_ROTATE_MASK;
>>       drm_plane_create_rotation_property(plane,
>> @@ -1519,8 +1594,6 @@ struct drm_plane *dpu_plane_init(struct 
>> drm_device *dev,
>>       drm_plane_enable_fb_damage_clips(plane);
>>       /* success! finalize initialization */
>> -    drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
>> -
>>       mutex_init(&pdpu->lock);
>>       DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
>> @@ -1531,3 +1604,59 @@ struct drm_plane *dpu_plane_init(struct 
>> drm_device *dev,
>>       kfree(pdpu);
>>       return ERR_PTR(ret);
>>   }
>> +
>> +struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
>> +                      uint32_t pipe, enum drm_plane_type type,
>> +                      unsigned long possible_crtcs)
>> +{
>> +    struct drm_plane *plane = NULL;
>> +    struct msm_drm_private *priv = dev->dev_private;
>> +    struct dpu_kms *kms = to_dpu_kms(priv->kms);
>> +    struct dpu_hw_sspp *pipe_hw;
>> +
>> +    /* initialize underlying h/w driver */
>> +    pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
>> +    if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
>> +        DPU_ERROR("[%u]SSPP is invalid\n", pipe);
>> +        return ERR_PTR(-EINVAL);
>> +    }
>> +
>> +
>> +    plane = dpu_plane_init(dev, type, possible_crtcs,
>> +                   pipe_hw->cap->features & 
>> BIT(DPU_SSPP_INLINE_ROTATION),
>> +                   pipe_hw->cap->sblk->format_list,
>> +                   pipe_hw->cap->sblk->num_formats,
>> +                   pipe);
>> +    if (IS_ERR(plane))
>> +        return plane;
>> +
>> +    drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
>> +
>> +    DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
>> +                    pipe, plane->base.id);
>> +
>> +    return plane;
>> +}
>> +
>> +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
>> +                     enum drm_plane_type type,
>> +                     unsigned long possible_crtcs)
>> +{
>> +    struct drm_plane *plane = NULL;
>> +    struct msm_drm_private *priv = dev->dev_private;
>> +    struct dpu_kms *kms = to_dpu_kms(priv->kms);
>> +
>> +    plane = dpu_plane_init(dev, type, possible_crtcs,
>> +                   kms->catalog->caps->has_inline_rot,
>> +                   kms->catalog->caps->format_list,
>> +                   kms->catalog->caps->num_formats,
>> +                   SSPP_NONE);
>> +    if (IS_ERR(plane))
>> +        return plane;
>> +
>> +    drm_plane_helper_add(plane, &dpu_plane_virtual_helper_funcs);
>> +
>> +    DPU_DEBUG("%s created virtual id:%u\n", plane->name, 
>> plane->base.id);
>> +
>> +    return plane;
>> +}
> 
> Overall I am satisfied with the split of the dpu_plane_init() function 
> into virtual vs non-virtual and happy its protected with a modparam.
> 
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>> index abd6b21a049b..cb1e31ef0d3f 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>> @@ -31,6 +31,7 @@
>>    * @plane_clk: calculated clk per plane
>>    * @needs_dirtyfb: whether attached CRTC needs pixel data explicitly 
>> flushed
>>    * @rotation: simplified drm rotation hint
>> + * @saved_fmt: format used by the plane's FB, saved for for virtual 
>> plane support
>>    */
>>   struct dpu_plane_state {
>>       struct drm_plane_state base;
>> @@ -48,6 +49,8 @@ struct dpu_plane_state {
>>       bool needs_dirtyfb;
>>       unsigned int rotation;
>> +
>> +    const struct dpu_format *saved_fmt;
>>   };
>>   #define to_dpu_plane_state(x) \
>> @@ -66,17 +69,27 @@ void dpu_plane_flush(struct drm_plane *plane);
>>   void dpu_plane_set_error(struct drm_plane *plane, bool error);
>>   /**
>> - * dpu_plane_init - create new dpu plane for the given pipe
>> + * dpu_plane_init_sspp - create new dpu plane for the given pipe
>>    * @dev:   Pointer to DRM device
>>    * @pipe:  dpu hardware pipe identifier
>>    * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
>>    * @possible_crtcs: bitmask of crtc that can be attached to the 
>> given pipe
>>    *
>>    */
>> -struct drm_plane *dpu_plane_init(struct drm_device *dev,
>> +struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
>>           uint32_t pipe, enum drm_plane_type type,
>>           unsigned long possible_crtcs);
>> +/**
>> + * dpu_plane_init_virtual - create new dpu virtualized plane
>> + * @dev:   Pointer to DRM device
>> + * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
>> + * @possible_crtcs: bitmask of crtc that can be attached to the given 
>> pipe
>> + */
>> +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
>> +                     enum drm_plane_type type,
>> +                     unsigned long possible_crtcs);
>> +
>>   /**
>>    * dpu_plane_color_fill - enables color fill on plane
>>    * @plane:  Pointer to DRM plane object
>> @@ -93,4 +106,11 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane 
>> *plane, bool enable);
>>   static inline void dpu_plane_danger_signal_ctrl(struct drm_plane 
>> *plane, bool enable) {}
>>   #endif
>> +int dpu_plane_atomic_check(struct drm_plane *plane, struct 
>> drm_atomic_state *state);
>> +
>> +int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
>> +                       struct drm_crtc *crtc,
>> +                       struct dpu_global_state *global_state,
>> +                       struct drm_atomic_state *state);
>> +
>>   #endif /* _DPU_PLANE_H_ */
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index f0a94008d17a..6130ac87d7e3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -607,6 +607,71 @@ int dpu_rm_reserve(
>>       return ret;
>>   }
>> +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
>> +                    struct dpu_global_state *global_state,
>> +                    struct drm_crtc *crtc,
>> +                    bool yuv, bool scale, bool rot90)
>> +{
> 
> as noted above, lets consider adding a dpu_plane_sspp_requirements 
> struct instead of just expanding the param list.
> 
>> +    uint32_t crtc_id = crtc->base.id;
>> +    struct dpu_hw_sspp *hw_sspp;
>> +    bool retry = false;
>> +    int i;
>> +
>> +retry_loop:
>> +    for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) {
>> +        if (!rm->hw_sspp[i])
>> +            continue;
>> +
>> +        if (global_state->sspp_to_crtc_id[i])
>> +            continue;
>> +
>> +        hw_sspp = rm->hw_sspp[i];
>> +
>> +        /* skip incompatible planes */
>> +        if (scale && !(hw_sspp->cap->features & DPU_SSPP_SCALER))
>> +            continue;
>> +
>> +        if (yuv && !(hw_sspp->cap->features & DPU_SSPP_CSC_ANY))
>> +            continue;
>> +
>> +        if (rot90 && !(hw_sspp->cap->features & 
>> DPU_SSPP_INLINE_ROTATION))
>> +            continue;
>> +
> 
> These are sufficient conditions to start with for the use-cases I can 
> think of.
> 
>> +        /*
>> +         * For non-yuv, non-scaled planes try to find simple (DMA)
>> +         * plane, fallback to VIG on a second try.
>> +         *
>> +         * This way we'd leave VIG sspps to be later used for YUV 
>> formats.
>> +         */
>> +
>> +        if (!scale && !yuv && !rot90 && !retry &&
>> +            (hw_sspp->cap->features &
>> +             (DPU_SSPP_SCALER | DPU_SSPP_CSC_ANY | 
>> DPU_SSPP_INLINE_ROTATION)))
>> +            continue;
>> +
>> +        global_state->sspp_to_crtc_id[hw_sspp->idx - SSPP_NONE] = 
>> crtc_id;
>> +
>> +        return hw_sspp;
>> +    }
>> +
>> +    /* If we were looking for DMA plane, retry looking for VIG plane */
>> +    if (!scale && !yuv && !retry) {
>> +        retry = true;
>> +        goto retry_loop;
>> +    }
>> +
>> +    return NULL;
>> +}
>> +
>> +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
>> +                 struct drm_crtc *crtc)
>> +{
>> +    uint32_t crtc_id = crtc->base.id;
>> +
>> +    _dpu_rm_clear_mapping(global_state->sspp_to_crtc_id,
>> +        ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id);
>> +}
>> +
>>   int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>       struct dpu_global_state *global_state, struct drm_crtc *crtc,
>>       enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> index f402bec8322b..5bf6740ecb45 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> @@ -82,6 +82,30 @@ int dpu_rm_reserve(
>>   void dpu_rm_release(struct dpu_global_state *global_state,
>>           struct drm_crtc *crtc);
>> +/**
>> + * dpu_rm_reserve_sspp - Reserve the required SSPP for the provided CRTC
>> + * @rm: DPU Resource Manager handle
>> + * @global_state: private global state
>> + * @crtc: DRM CRTC handle
>> + * @yuv: required SSPP supporting YUV formats
>> + * @scale: required SSPP supporting scaling
>> + * @rot90: required SSPP supporting inline 90 degree rotation
>> + */
>> +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
>> +                    struct dpu_global_state *global_state,
>> +                    struct drm_crtc *crtc,
>> +                    bool yuv, bool scale, bool rot90);
>> +
>> +/**
>> + * dpu_rm_release_all_sspp - Given the CRTC, release all SSPP
>> + *    blocks previously reserved for that use case.
>> + * @rm: DPU Resource Manager handle
>> + * @crtc: DRM CRTC handle
>> + * @Return: 0 on Success otherwise -ERROR
>> + */
>> +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
>> +                 struct drm_crtc *crtc);
>> +
>>   /**
>>    * Get hw resources of the given type that are assigned to this 
>> encoder.
>>    */

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes
  2023-06-07 21:56     ` Dmitry Baryshkov
@ 2023-06-08 19:51       ` Abhinav Kumar
  2023-06-10  0:00         ` Abhinav Kumar
  0 siblings, 1 reply; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-08 19:51 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: Stephen Boyd, David Airlie, Daniel Vetter, Bjorn Andersson,
	linux-arm-msm, dri-devel, freedreno



On 6/7/2023 2:56 PM, Dmitry Baryshkov wrote:
> On 08/06/2023 00:05, Abhinav Kumar wrote:
>>
>>
>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>> Only several SSPP blocks support such features as YUV output or scaling,
>>> thus different DRM planes have different features.  Properly utilizing
>>> all planes requires the attention of the compositor, who should
>>> prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
>>> to end up in a situation when all featureful planes are already
>>> allocated for simple windows, leaving no spare plane for YUV playback.
>>>
>>> To solve this problem make all planes virtual. Each plane is registered
>>> as if it supports all possible features, but then at the runtime during
>>> the atomic_check phase the driver selects backing SSPP block for each
>>> plane.
>>>
>>> Note, this does not provide support for using two different SSPP blocks
>>> for a single plane or using two rectangles of an SSPP to drive two
>>> planes. Each plane still gets its own SSPP and can utilize either a solo
>>> rectangle or both multirect rectangles depending on the resolution.
>>>
>>> Note #2: By default support for virtual planes is turned off and the
>>> driver still uses old code path with preallocated SSPP block for each
>>> plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
>>> kernel parameter.
>>>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> ---
>>
>> There will be some rebase needed to switch back to encoder based 
>> allocation so I am not going to comment on those parts and will let 
>> you handle that when you post v3.
>>
>> But my questions/comments below are for other things.
>>
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  59 +++++--
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 120 ++++++++++----
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 187 ++++++++++++++++++----
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  24 ++-
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c    |  65 ++++++++
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h    |  24 +++
>>>   7 files changed, 413 insertions(+), 70 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>> index 8ef191fd002d..cdece21b81c9 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>> @@ -1273,6 +1273,29 @@ static int dpu_crtc_assign_resources(struct 
>>> drm_crtc *crtc, struct drm_crtc_stat
>>>       return 0;
>>>   }
>>> +static int dpu_crtc_assign_plane_resources(struct drm_crtc *crtc, 
>>> struct drm_crtc_state *crtc_state)
>>> +{
>>> +    struct dpu_global_state *global_state;
>>> +    struct drm_plane *plane;
>>> +    int rc;
>>> +
>>> +    global_state = dpu_kms_get_global_state(crtc_state->state);
>>> +    if (IS_ERR(global_state))
>>> +        return PTR_ERR(global_state);
>>> +
>>> +    dpu_rm_release_all_sspp(global_state, crtc);
>>> +
>>> +    drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
>>> +        rc = dpu_plane_virtual_assign_resources(plane, crtc,
>>> +                            global_state,
>>> +                            crtc_state->state);
>>> +        if (rc)
>>> +            return rc;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>>   static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>>>           struct drm_atomic_state *state)
>>>   {
>>> @@ -1281,7 +1304,6 @@ static int dpu_crtc_atomic_check(struct 
>>> drm_crtc *crtc,
>>>       struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
>>>       struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
>>> -    const struct drm_plane_state *pstate;
>>>       struct drm_plane *plane;
>>>       int rc = 0;
>>> @@ -1294,6 +1316,13 @@ static int dpu_crtc_atomic_check(struct 
>>> drm_crtc *crtc,
>>>               return rc;
>>>       }
>>> +    if (dpu_use_virtual_planes &&
>>> +        crtc_state->planes_changed) {
>>> +        rc = dpu_crtc_assign_plane_resources(crtc, crtc_state);
>>> +        if (rc < 0)
>>> +            return rc;
>>> +    }
>>
>> Can you please explain a bit more about the planes_changed condition?
>>
>> 1) Are we doing this because the plane's atomic check happens before 
>> the CRTC atomic check?
> 
> Yes. Another alternative would be to stop using 
> drm_atomic_helper_check() and implement our own code instead, inverting 
> the plane / CRTC check order.
> 

I am fine with that too but as you noted in (3), if planes_changed will 
be set by those functions and you can drop explicit assignment of it in 
this patch, that will be the best option for me.

>>
>> 2) So the DRM core sets this to true already when plane is switching 
>> CRTCs or being connected to a CRTC for the first time, we need to 
>> handle the conditions additional to that right?
> 
> Nit: it is not possible to switch CRTCs. Plane first has to be 
> disconnected and then to be connected to another CRTC.
> 
>>
>> 3) If (2) is correct, arent there other conditions then to be handled 
>> for setting planes_changed to true?
>>
>> Some examples include, switching from a scaling to non-scaling 
>> scenario, needing rotation vs not needing etc.
> 
> Setting the plane_changed is not required. Both 
> drm_atomic_helper_disable_plane() and drm_atomic_helper_update_plane() 
> will add the plane to the state. Then drm_atomic_helper_check_planes() 
> will call drm_atomic_helper_plane_changed(), setting 
> {old_,new_}crtc_state->planes_changed.
> 
> I should check if the format check below is required or not. It looks 
> like I can drop that clause too.
> 

Yes, please do. From the above explanation, it seems like we dont need 
to explicity set it again ourselves for format change.

> 
>>
>> Basically it seems like all of this is handled within the 
>> reserve_sspp() function but if planes_changes is not set then that 
>> wont get invoked at all.
>>
>>
>>> +
>>>       if (!crtc_state->enable || !crtc_state->active) {
>>>           DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip 
>>> atomic_check\n",
>>>                   crtc->base.id, crtc_state->enable,
>>> @@ -1311,20 +1340,30 @@ static int dpu_crtc_atomic_check(struct 
>>> drm_crtc *crtc,
>>>       if (cstate->num_mixers)
>>>           _dpu_crtc_setup_lm_bounds(crtc, crtc_state);
>>> -    /* FIXME: move this to dpu_plane_atomic_check? */
>>> -    drm_atomic_crtc_state_for_each_plane_state(plane, pstate, 
>>> crtc_state) {
>>> -        struct dpu_plane_state *dpu_pstate = 
>>> to_dpu_plane_state(pstate);
>>> -
>>> -        if (IS_ERR_OR_NULL(pstate)) {
>>> -            rc = PTR_ERR(pstate);
>>> -            DPU_ERROR("%s: failed to get plane%d state, %d\n",
>>> -                    dpu_crtc->name, plane->base.id, rc);
>>> -            return rc;
>>> +    drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
>>> +        const struct drm_plane_state *pstate;
>>> +        struct dpu_plane_state *dpu_pstate;
>>> +
>>> +        pstate = drm_atomic_get_plane_state(crtc_state->state, plane);
>>> +        if (IS_ERR(pstate))
>>> +            return PTR_ERR(pstate);
>>> +
>>> +        if (dpu_use_virtual_planes) {
>>> +            /*
>>> +             * In case of virtual planes, the plane's atomic_check
>>> +             * is a shortcut. Perform actual check here, after
>>> +             * allocating SSPPs.
>>> +             */
>>> +            rc = dpu_plane_atomic_check(plane, crtc_state->state);
>>> +            if (rc)
>>> +                return rc;
>>>           }
>>>           if (!pstate->visible)
>>>               continue;
>>> +        /* FIXME: move this to dpu_plane_atomic_check? */
>>> +        dpu_pstate = to_dpu_plane_state(pstate);
>>
>> Anything prevents us from doing it even now instead of a FIXME?
> 
> The question mark at the end. I'm not sure that moving it to the 
> plane_atomic_check would actually help. And please note that it is the 
> old code (and old FIXME) being moved around.
> 

Ah sorry, this is old code, so never mind.

>>
>>>           dpu_pstate->needs_dirtyfb = needs_dirtyfb;
>>>       }
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>>> index 35194262e628..487bb19ee9d6 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
>>> @@ -50,6 +50,9 @@
>>>   #define DPU_DEBUGFS_DIR "msm_dpu"
>>>   #define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"
>>> +bool dpu_use_virtual_planes = false;
>>> +module_param(dpu_use_virtual_planes, bool, 0);
>>> +
>>>   static int dpu_kms_hw_init(struct msm_kms *kms);
>>>   static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
>>> @@ -735,38 +738,54 @@ static int _dpu_kms_setup_displays(struct 
>>> drm_device *dev,
>>>       return rc;
>>>   }
>>> -#define MAX_PLANES 20
>>> -static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
>>> +static int dpu_kms_create_virtual_planes(struct dpu_kms *dpu_kms,
>>> +                     int max_crtc_count,
>>> +                     struct drm_plane **primary_planes,
>>> +                     struct drm_plane **cursor_planes)
>>>   {
>>> -    struct drm_device *dev;
>>> -    struct drm_plane *primary_planes[MAX_PLANES], *plane;
>>> -    struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
>>> -    struct drm_crtc *crtc;
>>> -    struct drm_encoder *encoder;
>>> -    unsigned int num_encoders;
>>> +    const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
>>> +    struct drm_device *dev = dpu_kms->dev;
>>> +    int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
>>> +    struct drm_plane *plane;
>>> -    struct msm_drm_private *priv;
>>> -    const struct dpu_mdss_cfg *catalog;
>>> +    /* Create the planes, keeping track of one primary/cursor per 
>>> crtc */
>>> +    for (i = 0; i < catalog->sspp_count; i++) {
>>> +        enum drm_plane_type type;
>>> -    int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
>>> -    int max_crtc_count;
>>> -    dev = dpu_kms->dev;
>>> -    priv = dev->dev_private;
>>> -    catalog = dpu_kms->catalog;
>>> +        if (primary_planes_idx < max_crtc_count)
>>> +            type = DRM_PLANE_TYPE_PRIMARY;
>>> +        else if (cursor_planes_idx < max_crtc_count)
>>> +            type = DRM_PLANE_TYPE_CURSOR;
>>> +        else
>>> +            type = DRM_PLANE_TYPE_OVERLAY;
>>> -    /*
>>> -     * Create encoder and query display drivers to create
>>> -     * bridges and connectors
>>> -     */
>>> -    ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
>>> -    if (ret)
>>> -        return ret;
>>> +        DPU_DEBUG("Create plane type %d\n", type);
>>> -    num_encoders = 0;
>>> -    drm_for_each_encoder(encoder, dev)
>>> -        num_encoders++;
>>> +        plane = dpu_plane_init_virtual(dev, type, (1UL << 
>>> max_crtc_count) - 1);
>>> +        if (IS_ERR(plane)) {
>>> +            DPU_ERROR("dpu_plane_init failed\n");
>>> +            ret = PTR_ERR(plane);
>>> +            return ret;
>>> +        }
>>> -    max_crtc_count = min(catalog->mixer_count, num_encoders);
>>> +        if (type == DRM_PLANE_TYPE_CURSOR)
>>> +            cursor_planes[cursor_planes_idx++] = plane;
>>> +        else if (type == DRM_PLANE_TYPE_PRIMARY)
>>> +            primary_planes[primary_planes_idx++] = plane;
>>> +    }
>>> +
>>> +    return primary_planes_idx;
>>> +}
>>> +
>>> +static int dpu_kms_create_planes(struct dpu_kms *dpu_kms,
>>> +                 int max_crtc_count,
>>> +                 struct drm_plane **primary_planes,
>>> +                 struct drm_plane **cursor_planes)
>>> +{
>>> +    const struct dpu_mdss_cfg *catalog = dpu_kms->catalog;
>>> +    struct drm_device *dev = dpu_kms->dev;
>>> +    int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
>>> +    struct drm_plane *plane;
>>>       /* Create the planes, keeping track of one primary/cursor per 
>>> crtc */
>>>       for (i = 0; i < catalog->sspp_count; i++) {
>>> @@ -784,8 +803,8 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms 
>>> *dpu_kms)
>>>                 type, catalog->sspp[i].features,
>>>                 catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR));
>>> -        plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
>>> -                       (1UL << max_crtc_count) - 1);
>>> +        plane = dpu_plane_init_sspp(dev, catalog->sspp[i].id, type,
>>> +                        (1UL << max_crtc_count) - 1);
>>>           if (IS_ERR(plane)) {
>>>               DPU_ERROR("dpu_plane_init failed\n");
>>>               ret = PTR_ERR(plane);
>>> @@ -798,7 +817,50 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms 
>>> *dpu_kms)
>>>               primary_planes[primary_planes_idx++] = plane;
>>>       }
>>> -    max_crtc_count = min(max_crtc_count, primary_planes_idx);
>>> +    return primary_planes_idx;
>>> +}
>>> +
>>> +#define MAX_PLANES 20
>>> +static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
>>> +{
>>> +    struct drm_device *dev;
>>> +    struct drm_plane *primary_planes[MAX_PLANES];
>>> +    struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
>>> +    struct drm_crtc *crtc;
>>> +    struct drm_encoder *encoder;
>>> +    unsigned int num_encoders;
>>> +
>>> +    struct msm_drm_private *priv;
>>> +    const struct dpu_mdss_cfg *catalog;
>>> +    int i, ret;
>>> +    int max_crtc_count;
>>> +
>>> +    dev = dpu_kms->dev;
>>> +    priv = dev->dev_private;
>>> +    catalog = dpu_kms->catalog;
>>> +
>>> +    /*
>>> +     * Create encoder and query display drivers to create
>>> +     * bridges and connectors
>>> +     */
>>> +    ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    num_encoders = 0;
>>> +    drm_for_each_encoder(encoder, dev)
>>> +        num_encoders++;
>>> +
>>> +    max_crtc_count = min(catalog->mixer_count, num_encoders);
>>> +
>>> +    if (dpu_use_virtual_planes)
>>> +        ret = dpu_kms_create_virtual_planes(dpu_kms, max_crtc_count, 
>>> primary_planes, cursor_planes);
>>> +    else
>>> +        ret = dpu_kms_create_planes(dpu_kms, max_crtc_count, 
>>> primary_planes, cursor_planes);
>>> +    if (ret < 0)
>>> +        return ret;
>>> +
>>> +    max_crtc_count = min(max_crtc_count, ret);
>>>       /* Create one CRTC per encoder */
>>>       for (i = 0; i < max_crtc_count; i++) {
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>> index 934874eb2248..9f6478f0ced6 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>> @@ -65,6 +65,8 @@
>>>   #define DPU_NAME_SIZE  12
>>> +extern bool dpu_use_virtual_planes;
>>> +
>>>   struct dpu_kms {
>>>       struct msm_kms base;
>>>       struct drm_device *dev;
>>> @@ -134,6 +136,8 @@ struct dpu_global_state {
>>>       uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
>>>       uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>>       uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>>> +
>>> +    uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE];
>>>   };
>>>   struct dpu_global_state
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>> index cf17075676d5..ee906c276aa5 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
>>> @@ -837,8 +837,77 @@ static int dpu_plane_atomic_check_pipe(struct 
>>> dpu_plane *pdpu,
>>>       return 0;
>>>   }
>>> -static int dpu_plane_atomic_check(struct drm_plane *plane,
>>> -                  struct drm_atomic_state *state)
>>> +static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
>>> +                      struct drm_atomic_state *state)
>>> +{
>>> +    struct drm_plane_state *plane_state =
>>> +        drm_atomic_get_plane_state(state, plane);
>>> +    struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
>>> +    const struct dpu_format *format;
>>> +    struct drm_crtc_state *crtc_state;
>>> +
>>> +    /*
>>> +     * Main part of checks, including 
>>> drm_atomic_helper_check_plane_state()
>>> +     * is called from dpu_crtc_atomic_check(). Do minimal processing 
>>> here.
>>> +     */
>>> +
>>> +    if (!plane_state->fb) {
>>> +        plane_state->visible = false;
>>> +
>>> +        /* resources are freed by dpu_crtc_atomic_check(), but clean 
>>> them here */
>>> +        pstate->pipe.sspp = NULL;
>>> +        pstate->r_pipe.sspp = NULL;
>>> +
>>> +        return 0;
>>> +    }
>>> +
>>> +    format = to_dpu_format(msm_framebuffer_format(plane_state->fb));
>>> +    crtc_state = drm_atomic_get_new_crtc_state(state, 
>>> plane_state->crtc);
>>> +
>>> +    /* force resource reallocation if the format of FB has changed */
>>> +    if (pstate->saved_fmt != format) {
>>> +        crtc_state->planes_changed = true;
>>> +        pstate->saved_fmt = format;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
>>> +                       struct drm_crtc *crtc,
>>> +                       struct dpu_global_state *global_state,
>>> +                       struct drm_atomic_state *state)
>>> +{
>>> +    struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
>>> +    struct dpu_plane_state *pstate;
>>> +    struct drm_plane_state *plane_state;
>>> +    struct dpu_hw_sspp *hw_sspp;
>>> +    bool yuv, scale, rot90;
>>> +
>>> +    plane_state = drm_atomic_get_plane_state(state, plane);
>>> +    if (IS_ERR(plane_state))
>>> +        return PTR_ERR(plane_state);
>>> +
>>> +    yuv = plane_state->fb ?
>>> + 
>>> DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(plane_state->fb))) :
>>> +        false;
>>> +    scale = (plane_state->src_w >> 16 != plane_state->crtc_w) ||
>>> +        (plane_state->src_h >> 16 != plane_state->crtc_h);
>>> +
>>> +    rot90 = drm_rotation_90_or_270(plane_state->rotation);
>>> +
>>> +    hw_sspp = dpu_rm_reserve_sspp(&dpu_kms->rm, global_state, crtc, 
>>> yuv, scale, rot90);
>>
>> I think this parameter list is going to explode. Shall we introduce a 
>> dpu_plane_sspp_requirements to store these?
> 
> SG.
> 
>>
>>> +    if (!hw_sspp)
>>> +        return -ENODEV;
>>> +
>>> +    pstate = to_dpu_plane_state(plane_state);
>>> +    pstate->pipe.sspp = hw_sspp;
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +int dpu_plane_atomic_check(struct drm_plane *plane,
>>> +               struct drm_atomic_state *state)
>>>   {
>>>       struct drm_plane_state *new_plane_state = 
>>> drm_atomic_get_new_plane_state(state,
>>>                                            plane);
>>> @@ -863,8 +932,10 @@ static int dpu_plane_atomic_check(struct 
>>> drm_plane *plane,
>>>           crtc_state = drm_atomic_get_new_crtc_state(state,
>>>                                  new_plane_state->crtc);
>>> -    pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
>>> -    r_pipe->sspp = NULL;
>>> +    if (pdpu->pipe != SSPP_NONE) {
>>> +        pipe->sspp = dpu_rm_get_sspp(&dpu_kms->rm, pdpu->pipe);
>>> +        r_pipe->sspp = NULL;
>>> +    }
>>>       pipe_hw_caps = pstate->pipe.sspp->cap;
>>>       sblk = pstate->pipe.sspp->cap->sblk;
>>> @@ -1358,12 +1429,14 @@ static void 
>>> dpu_plane_atomic_print_state(struct drm_printer *p,
>>>       drm_printf(p, "\tstage=%d\n", pstate->stage);
>>> -    drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
>>> -    drm_printf(p, "\tmultirect_mode[0]=%s\n", 
>>> dpu_get_multirect_mode(pipe->multirect_mode));
>>> -    drm_printf(p, "\tmultirect_index[0]=%s\n",
>>> -           dpu_get_multirect_index(pipe->multirect_index));
>>> -    drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", 
>>> DRM_RECT_ARG(&pipe_cfg->src_rect));
>>> -    drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", 
>>> DRM_RECT_ARG(&pipe_cfg->dst_rect));
>>> +    if (pipe->sspp) {
>>> +        drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
>>> +        drm_printf(p, "\tmultirect_mode[0]=%s\n", 
>>> dpu_get_multirect_mode(pipe->multirect_mode));
>>> +        drm_printf(p, "\tmultirect_index[0]=%s\n",
>>> +               dpu_get_multirect_index(pipe->multirect_index));
>>> +        drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", 
>>> DRM_RECT_ARG(&pipe_cfg->src_rect));
>>> +        drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", 
>>> DRM_RECT_ARG(&pipe_cfg->dst_rect));
>>> +    }
>>>       if (r_pipe->sspp) {
>>>           drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
>>> @@ -1453,18 +1526,30 @@ static const struct drm_plane_helper_funcs 
>>> dpu_plane_helper_funcs = {
>>>           .atomic_update = dpu_plane_atomic_update,
>>>   };
>>> +/*
>>> + * For virtual planes atomic_check is called from 
>>> dpu_crtc_atomic_check(),
>>> + * after CRTC code assigning SSPP.
>>> + */
>>> +static const struct drm_plane_helper_funcs 
>>> dpu_plane_virtual_helper_funcs = {
>>> +    .prepare_fb = dpu_plane_prepare_fb,
>>> +    .cleanup_fb = dpu_plane_cleanup_fb,
>>> +    .atomic_check = dpu_plane_virtual_atomic_check,
>>> +    .atomic_update = dpu_plane_atomic_update,
>>> +};
>>> +
>>>   /* initialize plane */
>>> -struct drm_plane *dpu_plane_init(struct drm_device *dev,
>>> -        uint32_t pipe, enum drm_plane_type type,
>>> -        unsigned long possible_crtcs)
>>> +static struct drm_plane *dpu_plane_init(struct drm_device *dev,
>>> +                    enum drm_plane_type type,
>>> +                    unsigned long possible_crtcs,
>>> +                    bool inline_rotation,
>>> +                    const uint32_t *format_list,
>>> +                    uint32_t num_formats,
>>> +                    enum dpu_sspp pipe)
>>>   {
>>>       struct drm_plane *plane = NULL;
>>> -    const uint32_t *format_list;
>>>       struct dpu_plane *pdpu;
>>>       struct msm_drm_private *priv = dev->dev_private;
>>>       struct dpu_kms *kms = to_dpu_kms(priv->kms);
>>> -    struct dpu_hw_sspp *pipe_hw;
>>> -    uint32_t num_formats;
>>>       uint32_t supported_rotations;
>>>       int ret = -EINVAL;
>>> @@ -1480,16 +1565,6 @@ struct drm_plane *dpu_plane_init(struct 
>>> drm_device *dev,
>>>       plane = &pdpu->base;
>>>       pdpu->pipe = pipe;
>>> -    /* initialize underlying h/w driver */
>>> -    pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
>>> -    if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
>>> -        DPU_ERROR("[%u]SSPP is invalid\n", pipe);
>>> -        goto clean_plane;
>>> -    }
>>> -
>>> -    format_list = pipe_hw->cap->sblk->format_list;
>>> -    num_formats = pipe_hw->cap->sblk->num_formats;
>>> -
>>>       ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
>>>                   format_list, num_formats,
>>>                   supported_format_modifiers, type, NULL);
>>> @@ -1510,7 +1585,7 @@ struct drm_plane *dpu_plane_init(struct 
>>> drm_device *dev,
>>>       supported_rotations = DRM_MODE_REFLECT_MASK | DRM_MODE_ROTATE_0 
>>> | DRM_MODE_ROTATE_180;
>>> -    if (pipe_hw->cap->features & BIT(DPU_SSPP_INLINE_ROTATION))
>>> +    if (inline_rotation)
>>>           supported_rotations |= DRM_MODE_ROTATE_MASK;
>>>       drm_plane_create_rotation_property(plane,
>>> @@ -1519,8 +1594,6 @@ struct drm_plane *dpu_plane_init(struct 
>>> drm_device *dev,
>>>       drm_plane_enable_fb_damage_clips(plane);
>>>       /* success! finalize initialization */
>>> -    drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
>>> -
>>>       mutex_init(&pdpu->lock);
>>>       DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
>>> @@ -1531,3 +1604,59 @@ struct drm_plane *dpu_plane_init(struct 
>>> drm_device *dev,
>>>       kfree(pdpu);
>>>       return ERR_PTR(ret);
>>>   }
>>> +
>>> +struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
>>> +                      uint32_t pipe, enum drm_plane_type type,
>>> +                      unsigned long possible_crtcs)
>>> +{
>>> +    struct drm_plane *plane = NULL;
>>> +    struct msm_drm_private *priv = dev->dev_private;
>>> +    struct dpu_kms *kms = to_dpu_kms(priv->kms);
>>> +    struct dpu_hw_sspp *pipe_hw;
>>> +
>>> +    /* initialize underlying h/w driver */
>>> +    pipe_hw = dpu_rm_get_sspp(&kms->rm, pipe);
>>> +    if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
>>> +        DPU_ERROR("[%u]SSPP is invalid\n", pipe);
>>> +        return ERR_PTR(-EINVAL);
>>> +    }
>>> +
>>> +
>>> +    plane = dpu_plane_init(dev, type, possible_crtcs,
>>> +                   pipe_hw->cap->features & 
>>> BIT(DPU_SSPP_INLINE_ROTATION),
>>> +                   pipe_hw->cap->sblk->format_list,
>>> +                   pipe_hw->cap->sblk->num_formats,
>>> +                   pipe);
>>> +    if (IS_ERR(plane))
>>> +        return plane;
>>> +
>>> +    drm_plane_helper_add(plane, &dpu_plane_helper_funcs);
>>> +
>>> +    DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
>>> +                    pipe, plane->base.id);
>>> +
>>> +    return plane;
>>> +}
>>> +
>>> +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
>>> +                     enum drm_plane_type type,
>>> +                     unsigned long possible_crtcs)
>>> +{
>>> +    struct drm_plane *plane = NULL;
>>> +    struct msm_drm_private *priv = dev->dev_private;
>>> +    struct dpu_kms *kms = to_dpu_kms(priv->kms);
>>> +
>>> +    plane = dpu_plane_init(dev, type, possible_crtcs,
>>> +                   kms->catalog->caps->has_inline_rot,
>>> +                   kms->catalog->caps->format_list,
>>> +                   kms->catalog->caps->num_formats,
>>> +                   SSPP_NONE);
>>> +    if (IS_ERR(plane))
>>> +        return plane;
>>> +
>>> +    drm_plane_helper_add(plane, &dpu_plane_virtual_helper_funcs);
>>> +
>>> +    DPU_DEBUG("%s created virtual id:%u\n", plane->name, 
>>> plane->base.id);
>>> +
>>> +    return plane;
>>> +}
>>
>> Overall I am satisfied with the split of the dpu_plane_init() function 
>> into virtual vs non-virtual and happy its protected with a modparam.
>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>>> index abd6b21a049b..cb1e31ef0d3f 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
>>> @@ -31,6 +31,7 @@
>>>    * @plane_clk: calculated clk per plane
>>>    * @needs_dirtyfb: whether attached CRTC needs pixel data 
>>> explicitly flushed
>>>    * @rotation: simplified drm rotation hint
>>> + * @saved_fmt: format used by the plane's FB, saved for for virtual 
>>> plane support
>>>    */
>>>   struct dpu_plane_state {
>>>       struct drm_plane_state base;
>>> @@ -48,6 +49,8 @@ struct dpu_plane_state {
>>>       bool needs_dirtyfb;
>>>       unsigned int rotation;
>>> +
>>> +    const struct dpu_format *saved_fmt;
>>>   };
>>>   #define to_dpu_plane_state(x) \
>>> @@ -66,17 +69,27 @@ void dpu_plane_flush(struct drm_plane *plane);
>>>   void dpu_plane_set_error(struct drm_plane *plane, bool error);
>>>   /**
>>> - * dpu_plane_init - create new dpu plane for the given pipe
>>> + * dpu_plane_init_sspp - create new dpu plane for the given pipe
>>>    * @dev:   Pointer to DRM device
>>>    * @pipe:  dpu hardware pipe identifier
>>>    * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
>>>    * @possible_crtcs: bitmask of crtc that can be attached to the 
>>> given pipe
>>>    *
>>>    */
>>> -struct drm_plane *dpu_plane_init(struct drm_device *dev,
>>> +struct drm_plane *dpu_plane_init_sspp(struct drm_device *dev,
>>>           uint32_t pipe, enum drm_plane_type type,
>>>           unsigned long possible_crtcs);
>>> +/**
>>> + * dpu_plane_init_virtual - create new dpu virtualized plane
>>> + * @dev:   Pointer to DRM device
>>> + * @type:  Plane type - PRIMARY/OVERLAY/CURSOR
>>> + * @possible_crtcs: bitmask of crtc that can be attached to the 
>>> given pipe
>>> + */
>>> +struct drm_plane *dpu_plane_init_virtual(struct drm_device *dev,
>>> +                     enum drm_plane_type type,
>>> +                     unsigned long possible_crtcs);
>>> +
>>>   /**
>>>    * dpu_plane_color_fill - enables color fill on plane
>>>    * @plane:  Pointer to DRM plane object
>>> @@ -93,4 +106,11 @@ void dpu_plane_danger_signal_ctrl(struct 
>>> drm_plane *plane, bool enable);
>>>   static inline void dpu_plane_danger_signal_ctrl(struct drm_plane 
>>> *plane, bool enable) {}
>>>   #endif
>>> +int dpu_plane_atomic_check(struct drm_plane *plane, struct 
>>> drm_atomic_state *state);
>>> +
>>> +int dpu_plane_virtual_assign_resources(struct drm_plane *plane,
>>> +                       struct drm_crtc *crtc,
>>> +                       struct dpu_global_state *global_state,
>>> +                       struct drm_atomic_state *state);
>>> +
>>>   #endif /* _DPU_PLANE_H_ */
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> index f0a94008d17a..6130ac87d7e3 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> @@ -607,6 +607,71 @@ int dpu_rm_reserve(
>>>       return ret;
>>>   }
>>> +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
>>> +                    struct dpu_global_state *global_state,
>>> +                    struct drm_crtc *crtc,
>>> +                    bool yuv, bool scale, bool rot90)
>>> +{
>>
>> as noted above, lets consider adding a dpu_plane_sspp_requirements 
>> struct instead of just expanding the param list.
>>
>>> +    uint32_t crtc_id = crtc->base.id;
>>> +    struct dpu_hw_sspp *hw_sspp;
>>> +    bool retry = false;
>>> +    int i;
>>> +
>>> +retry_loop:
>>> +    for (i = 0; i < ARRAY_SIZE(rm->hw_sspp); i++) {
>>> +        if (!rm->hw_sspp[i])
>>> +            continue;
>>> +
>>> +        if (global_state->sspp_to_crtc_id[i])
>>> +            continue;
>>> +
>>> +        hw_sspp = rm->hw_sspp[i];
>>> +
>>> +        /* skip incompatible planes */
>>> +        if (scale && !(hw_sspp->cap->features & DPU_SSPP_SCALER))
>>> +            continue;
>>> +
>>> +        if (yuv && !(hw_sspp->cap->features & DPU_SSPP_CSC_ANY))
>>> +            continue;
>>> +
>>> +        if (rot90 && !(hw_sspp->cap->features & 
>>> DPU_SSPP_INLINE_ROTATION))
>>> +            continue;
>>> +
>>
>> These are sufficient conditions to start with for the use-cases I can 
>> think of.
>>
>>> +        /*
>>> +         * For non-yuv, non-scaled planes try to find simple (DMA)
>>> +         * plane, fallback to VIG on a second try.
>>> +         *
>>> +         * This way we'd leave VIG sspps to be later used for YUV 
>>> formats.
>>> +         */
>>> +
>>> +        if (!scale && !yuv && !rot90 && !retry &&
>>> +            (hw_sspp->cap->features &
>>> +             (DPU_SSPP_SCALER | DPU_SSPP_CSC_ANY | 
>>> DPU_SSPP_INLINE_ROTATION)))
>>> +            continue;
>>> +
>>> +        global_state->sspp_to_crtc_id[hw_sspp->idx - SSPP_NONE] = 
>>> crtc_id;
>>> +
>>> +        return hw_sspp;
>>> +    }
>>> +
>>> +    /* If we were looking for DMA plane, retry looking for VIG plane */
>>> +    if (!scale && !yuv && !retry) {
>>> +        retry = true;
>>> +        goto retry_loop;
>>> +    }
>>> +
>>> +    return NULL;
>>> +}
>>> +
>>> +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
>>> +                 struct drm_crtc *crtc)
>>> +{
>>> +    uint32_t crtc_id = crtc->base.id;
>>> +
>>> +    _dpu_rm_clear_mapping(global_state->sspp_to_crtc_id,
>>> +        ARRAY_SIZE(global_state->sspp_to_crtc_id), crtc_id);
>>> +}
>>> +
>>>   int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>       struct dpu_global_state *global_state, struct drm_crtc *crtc,
>>>       enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int 
>>> blks_size)
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> index f402bec8322b..5bf6740ecb45 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> @@ -82,6 +82,30 @@ int dpu_rm_reserve(
>>>   void dpu_rm_release(struct dpu_global_state *global_state,
>>>           struct drm_crtc *crtc);
>>> +/**
>>> + * dpu_rm_reserve_sspp - Reserve the required SSPP for the provided 
>>> CRTC
>>> + * @rm: DPU Resource Manager handle
>>> + * @global_state: private global state
>>> + * @crtc: DRM CRTC handle
>>> + * @yuv: required SSPP supporting YUV formats
>>> + * @scale: required SSPP supporting scaling
>>> + * @rot90: required SSPP supporting inline 90 degree rotation
>>> + */
>>> +struct dpu_hw_sspp *dpu_rm_reserve_sspp(struct dpu_rm *rm,
>>> +                    struct dpu_global_state *global_state,
>>> +                    struct drm_crtc *crtc,
>>> +                    bool yuv, bool scale, bool rot90);
>>> +
>>> +/**
>>> + * dpu_rm_release_all_sspp - Given the CRTC, release all SSPP
>>> + *    blocks previously reserved for that use case.
>>> + * @rm: DPU Resource Manager handle
>>> + * @crtc: DRM CRTC handle
>>> + * @Return: 0 on Success otherwise -ERROR
>>> + */
>>> +void dpu_rm_release_all_sspp(struct dpu_global_state *global_state,
>>> +                 struct drm_crtc *crtc);
>>> +
>>>   /**
>>>    * Get hw resources of the given type that are assigned to this 
>>> encoder.
>>>    */
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes
  2023-06-08 19:51       ` Abhinav Kumar
@ 2023-06-10  0:00         ` Abhinav Kumar
  0 siblings, 0 replies; 55+ messages in thread
From: Abhinav Kumar @ 2023-06-10  0:00 UTC (permalink / raw)
  To: Dmitry Baryshkov, Rob Clark, Sean Paul
  Cc: freedreno, linux-arm-msm, Bjorn Andersson, dri-devel, Stephen Boyd



On 6/8/2023 12:51 PM, Abhinav Kumar wrote:
> 
> 
> On 6/7/2023 2:56 PM, Dmitry Baryshkov wrote:
>> On 08/06/2023 00:05, Abhinav Kumar wrote:
>>>
>>>
>>> On 3/20/2023 6:18 PM, Dmitry Baryshkov wrote:
>>>> Only several SSPP blocks support such features as YUV output or 
>>>> scaling,
>>>> thus different DRM planes have different features.  Properly utilizing
>>>> all planes requires the attention of the compositor, who should
>>>> prefer simpler planes to YUV-supporting ones. Otherwise it is very easy
>>>> to end up in a situation when all featureful planes are already
>>>> allocated for simple windows, leaving no spare plane for YUV playback.
>>>>
>>>> To solve this problem make all planes virtual. Each plane is registered
>>>> as if it supports all possible features, but then at the runtime during
>>>> the atomic_check phase the driver selects backing SSPP block for each
>>>> plane.
>>>>
>>>> Note, this does not provide support for using two different SSPP blocks
>>>> for a single plane or using two rectangles of an SSPP to drive two
>>>> planes. Each plane still gets its own SSPP and can utilize either a 
>>>> solo
>>>> rectangle or both multirect rectangles depending on the resolution.
>>>>
>>>> Note #2: By default support for virtual planes is turned off and the
>>>> driver still uses old code path with preallocated SSPP block for each
>>>> plane. To enable virtual planes, pass 'msm.dpu_use_virtual_planes=1'
>>>> kernel parameter.
>>>>
>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>> ---
>>>
>>> There will be some rebase needed to switch back to encoder based 
>>> allocation so I am not going to comment on those parts and will let 
>>> you handle that when you post v3.
>>>
>>> But my questions/comments below are for other things.
>>>
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  59 +++++--
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 120 ++++++++++----
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   4 +
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 187 
>>>> ++++++++++++++++++----
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h |  24 ++-
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c    |  65 ++++++++
>>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h    |  24 +++
>>>>   7 files changed, 413 insertions(+), 70 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>> index 8ef191fd002d..cdece21b81c9 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>> @@ -1273,6 +1273,29 @@ static int dpu_crtc_assign_resources(struct 
>>>> drm_crtc *crtc, struct drm_crtc_stat
>>>>       return 0;
>>>>   }
>>>> +static int dpu_crtc_assign_plane_resources(struct drm_crtc *crtc, 
>>>> struct drm_crtc_state *crtc_state)
>>>> +{
>>>> +    struct dpu_global_state *global_state;
>>>> +    struct drm_plane *plane;
>>>> +    int rc;
>>>> +
>>>> +    global_state = dpu_kms_get_global_state(crtc_state->state);
>>>> +    if (IS_ERR(global_state))
>>>> +        return PTR_ERR(global_state);
>>>> +
>>>> +    dpu_rm_release_all_sspp(global_state, crtc);
>>>> +
>>>> +    drm_atomic_crtc_state_for_each_plane(plane, crtc_state) {
>>>> +        rc = dpu_plane_virtual_assign_resources(plane, crtc,
>>>> +                            global_state,
>>>> +                            crtc_state->state);
>>>> +        if (rc)
>>>> +            return rc;
>>>> +    }
>>>> +
>>>> +    return 0;
>>>> +}
>>>> +
>>>>   static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>>>>           struct drm_atomic_state *state)
>>>>   {
>>>> @@ -1281,7 +1304,6 @@ static int dpu_crtc_atomic_check(struct 
>>>> drm_crtc *crtc,
>>>>       struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
>>>>       struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
>>>> -    const struct drm_plane_state *pstate;
>>>>       struct drm_plane *plane;
>>>>       int rc = 0;
>>>> @@ -1294,6 +1316,13 @@ static int dpu_crtc_atomic_check(struct 
>>>> drm_crtc *crtc,
>>>>               return rc;
>>>>       }
>>>> +    if (dpu_use_virtual_planes &&
>>>> +        crtc_state->planes_changed) {
>>>> +        rc = dpu_crtc_assign_plane_resources(crtc, crtc_state);
>>>> +        if (rc < 0)
>>>> +            return rc;
>>>> +    }
>>>
>>> Can you please explain a bit more about the planes_changed condition?
>>>
>>> 1) Are we doing this because the plane's atomic check happens before 
>>> the CRTC atomic check?
>>
>> Yes. Another alternative would be to stop using 
>> drm_atomic_helper_check() and implement our own code instead, 
>> inverting the plane / CRTC check order.
>>
> 
> I am fine with that too but as you noted in (3), if planes_changed will 
> be set by those functions and you can drop explicit assignment of it in 
> this patch, that will be the best option for me.
> 
>>>
>>> 2) So the DRM core sets this to true already when plane is switching 
>>> CRTCs or being connected to a CRTC for the first time, we need to 
>>> handle the conditions additional to that right?
>>
>> Nit: it is not possible to switch CRTCs. Plane first has to be 
>> disconnected and then to be connected to another CRTC.
>>
>>>
>>> 3) If (2) is correct, arent there other conditions then to be handled 
>>> for setting planes_changed to true?
>>>
>>> Some examples include, switching from a scaling to non-scaling 
>>> scenario, needing rotation vs not needing etc.
>>
>> Setting the plane_changed is not required. Both 
>> drm_atomic_helper_disable_plane() and drm_atomic_helper_update_plane() 
>> will add the plane to the state. Then drm_atomic_helper_check_planes() 
>> will call drm_atomic_helper_plane_changed(), setting 
>> {old_,new_}crtc_state->planes_changed.
>>
>> I should check if the format check below is required or not. It looks 
>> like I can drop that clause too.
>>
> 
> Yes, please do. From the above explanation, it seems like we dont need 
> to explicity set it again ourselves for format change.
> 
>>

I have a basic doubt about the split between dpu_plane_atomic_check Vs 
dpu_crtc_atomic_check() because the next patch is also relying heavily 
on the fact that plane's atomic check comes first and then crtc.

Please help me understand this better.

-> dpu_plane_virtual_atomic_check() is called and today that doesnt seem 
to do much :

	- marks visible as false if there is no fb
	(wouldnt the DRM core already do this?)
	- caches the format
	(this part is used in the dpu_crtc_atomic_check())

-> dpu_crtc_atomic_check() gets called which calls 
dpu_crtc_assign_plane_resources() which finally reserves the SSPPs to 
back the planes

-> perform dpu_plane_atomic_check() on each of the planes on the CRTC by 
checking the planes attached to CRTC state

1) What would be wrong to continue using dpu_plane_atomic_check() 
instead of the newly created dpu_plane_virtual_atomic_check() to get the 
backing SSPPs because it seems we need to maintain lot of information in 
the dpu_plane_state to manage co-ordination between the two atomic 
checks? A big portion of even the next patch does that.

2) Even dpu_plane_atomic_check() /  dpu_plane_virtual_atomic_check() is 
called only for each plane in the CRTC state, so why all the movement to 
crtc's atomic_check()? I am missing the link here. Was it done only to 
move all resource allocation to CRTC ID?



^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2023-06-10  0:00 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-21  1:18 [RFC PATCH v2 00/13] drm/msm/dpu: support virtual wide planes Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 01/13] drm/atomic-helper: split not-scaling part of drm_atomic_helper_check_plane_state Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 02/13] drm/msm/dpu: take plane rotation into account for wide planes Dmitry Baryshkov
2023-05-12 22:12   ` Abhinav Kumar
2023-05-14 17:01     ` Dmitry Baryshkov
2023-05-15 18:45       ` Abhinav Kumar
2023-05-15 19:12         ` Dmitry Baryshkov
2023-05-15 19:32           ` Abhinav Kumar
2023-03-21  1:18 ` [RFC PATCH v2 03/13] drm/msm/dpu: encoder: simplify debugfs handling Dmitry Baryshkov
2023-05-12 22:18   ` Abhinav Kumar
2023-05-14 17:02     ` Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 04/13] drm/msm/dpu: remove unused fields from dpu_encoder_virt Dmitry Baryshkov
2023-06-06 20:25   ` [Freedreno] " Abhinav Kumar
2023-06-06 20:29     ` Dmitry Baryshkov
2023-06-06 20:36       ` Abhinav Kumar
2023-03-21  1:18 ` [RFC PATCH v2 05/13] drm/msm/dpu: get rid of struct dpu_rm_requirements Dmitry Baryshkov
2023-05-12 22:39   ` Abhinav Kumar
2023-05-14 17:06     ` Dmitry Baryshkov
2023-05-17 23:53       ` Abhinav Kumar
2023-05-18 23:19         ` Abhinav Kumar
2023-03-21  1:18 ` [RFC PATCH v2 06/13] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Dmitry Baryshkov
2023-05-18 23:46   ` Abhinav Kumar
2023-05-19  1:50     ` Dmitry Baryshkov
2023-05-22 22:22       ` [Freedreno] " Abhinav Kumar
2023-05-23  7:25         ` Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 07/13] drm/msm/dpu: move resource allocation to CRTC Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 08/13] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 09/13] drm/msm/dpu: move pstate->pipe initialization to dpu_plane_atomic_check Dmitry Baryshkov
2023-05-24 22:46   ` Abhinav Kumar
2023-05-24 23:04     ` [Freedreno] " Abhinav Kumar
2023-05-25  1:40       ` Dmitry Baryshkov
2023-06-06 20:27         ` Abhinav Kumar
2023-03-21  1:18 ` [RFC PATCH v2 10/13] drm/msm/dpu: add list of supported formats to the DPU caps Dmitry Baryshkov
2023-05-24 23:16   ` Abhinav Kumar
2023-05-25  1:47     ` Dmitry Baryshkov
2023-06-06 21:14       ` Abhinav Kumar
2023-06-06 21:29         ` Dmitry Baryshkov
2023-06-06 21:47           ` Abhinav Kumar
2023-06-06 21:52             ` Dmitry Baryshkov
2023-06-06 22:47               ` Abhinav Kumar
2023-06-06 22:50                 ` Dmitry Baryshkov
2023-06-06 22:57                   ` [Freedreno] " Abhinav Kumar
2023-06-06 22:59                     ` Dmitry Baryshkov
2023-06-06 23:14                       ` Abhinav Kumar
2023-06-06 23:21                         ` Dmitry Baryshkov
2023-06-07  1:12                           ` Abhinav Kumar
2023-03-21  1:18 ` [RFC PATCH v2 11/13] drm/msm/dpu: add a field describing inline rotation to dpu_caps Dmitry Baryshkov
2023-05-24 23:20   ` Abhinav Kumar
2023-05-25  1:47     ` Dmitry Baryshkov
2023-03-21  1:18 ` [RFC PATCH v2 12/13] drm/msm/dpu: add support for virtual planes Dmitry Baryshkov
2023-06-07 21:05   ` Abhinav Kumar
2023-06-07 21:56     ` Dmitry Baryshkov
2023-06-08 19:51       ` Abhinav Kumar
2023-06-10  0:00         ` Abhinav Kumar
2023-03-21  1:18 ` [RFC PATCH v2 13/13] drm/msm/dpu: allow using two SSPP blocks for a single plane Dmitry Baryshkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).