All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff
@ 2016-12-19 12:08 Archit Taneja
  2016-12-19 12:08 ` [PATCH 1/9] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
                   ` (10 more replies)
  0 siblings, 11 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

This series does some mdp5_plane related clean ups (use plane helpers
for clipping etc), adds MDP5 bits needed for cursor plane blocks, and
then add cursor planes.

On older MDP5 versions, we had cursor HW in Layer Mixer blocks, and
that's implemented in mdp5_crtc.c. With newer hardware, the cursor
blocks look exactly like MDP5 pipes (SSPPs).

The "faster than vblank cursor position update stuff" has been
copied from vc4 and the patches posted recently by Maarten for Intel:

https://patchwork.kernel.org/patch/9466417/

I've tried this with some X11 UI and modetest -C, and it seems to
work okay. Are there any tests that mix up atomic commits and legacy
cursor updates a lot to identify issues?

Archit Taneja (9):
  drm/msm/mdp5: cfg: Add pipe_cursor block
  drm/msm/mdp5: Update generated headers
  drm/msm/mdp5: Prepare CRTC/LM for empty stages
  drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
  drm/msm/mdp5: Configure COLOR3_OUT propagation
  drm/msm/mdp5: Misc cursor plane bits
  drm/msm/mdp5: Refactor mdp5_plane_atomic_check
  HACK: drm/msm/mdp5: Add support for legacy cursor updates
  drm/msm/mdp5: Add cursor planes

 drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h   |  30 +++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c   |  10 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h   |   1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  |  73 +++++++++++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   |  14 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h   |   4 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   |  38 +++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |   8 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c  |   8 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 181 ++++++++++++++++++++++++++----
 drivers/gpu/drm/msm/mdp/mdp_kms.h         |   1 +
 drivers/gpu/drm/msm/msm_atomic.c          |  26 +++--
 12 files changed, 334 insertions(+), 60 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 1/9] drm/msm/mdp5: cfg: Add pipe_cursor block
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [PATCH 2/9] drm/msm/mdp5: Update generated headers Archit Taneja
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

Define the block in advance so that the generated mdp5.xml.h doesn't
break build.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index bd4fe81..b1c7daa 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -85,6 +85,7 @@ struct mdp5_cfg_hw {
 	struct mdp5_pipe_block pipe_vig;
 	struct mdp5_pipe_block pipe_rgb;
 	struct mdp5_pipe_block pipe_dma;
+	struct mdp5_pipe_block pipe_cursor;
 	struct mdp5_lm_block  lm;
 	struct mdp5_sub_block dspp;
 	struct mdp5_sub_block ad;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH 2/9] drm/msm/mdp5: Update generated headers
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
  2016-12-19 12:08 ` [PATCH 1/9] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [PATCH 3/9] drm/msm/mdp5: Prepare CRTC/LM for empty stages Archit Taneja
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index 27d5371..6db1b8b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -65,16 +65,19 @@ enum mdp5_intfnum {
 };
 
 enum mdp5_pipe {
-	SSPP_VIG0 = 0,
-	SSPP_VIG1 = 1,
-	SSPP_VIG2 = 2,
-	SSPP_RGB0 = 3,
-	SSPP_RGB1 = 4,
-	SSPP_RGB2 = 5,
-	SSPP_DMA0 = 6,
-	SSPP_DMA1 = 7,
-	SSPP_VIG3 = 8,
-	SSPP_RGB3 = 9,
+	SSPP_NONE = 0,
+	SSPP_VIG0 = 1,
+	SSPP_VIG1 = 2,
+	SSPP_VIG2 = 3,
+	SSPP_RGB0 = 4,
+	SSPP_RGB1 = 5,
+	SSPP_RGB2 = 6,
+	SSPP_DMA0 = 7,
+	SSPP_DMA1 = 8,
+	SSPP_VIG3 = 9,
+	SSPP_RGB3 = 10,
+	SSPP_CURSOR0 = 11,
+	SSPP_CURSOR1 = 12,
 };
 
 enum mdp5_ctl_mode {
@@ -532,6 +535,7 @@ static inline uint32_t MDP5_CTL_LAYER_EXT_REG_CURSOR1(enum mdp_mixer_stage_id va
 static inline uint32_t __offset_PIPE(enum mdp5_pipe idx)
 {
 	switch (idx) {
+		case SSPP_NONE: return (INVALID_IDX(idx));
 		case SSPP_VIG0: return (mdp5_cfg->pipe_vig.base[0]);
 		case SSPP_VIG1: return (mdp5_cfg->pipe_vig.base[1]);
 		case SSPP_VIG2: return (mdp5_cfg->pipe_vig.base[2]);
@@ -542,6 +546,8 @@ static inline uint32_t __offset_PIPE(enum mdp5_pipe idx)
 		case SSPP_DMA1: return (mdp5_cfg->pipe_dma.base[1]);
 		case SSPP_VIG3: return (mdp5_cfg->pipe_vig.base[3]);
 		case SSPP_RGB3: return (mdp5_cfg->pipe_rgb.base[3]);
+		case SSPP_CURSOR0: return (mdp5_cfg->pipe_cursor.base[0]);
+		case SSPP_CURSOR1: return (mdp5_cfg->pipe_cursor.base[1]);
 		default: return INVALID_IDX(idx);
 	}
 }
@@ -1073,6 +1079,10 @@ static inline uint32_t __offset_LM(uint32_t idx)
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA			0x00000004
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA			0x00000008
 #define MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA			0x00000010
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA			0x00000020
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA			0x00000040
+#define MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA			0x00000080
+#define MDP5_LM_BLEND_COLOR_OUT_SPLIT_LEFT_RIGHT		0x80000000
 
 static inline uint32_t REG_MDP5_LM_OUT_SIZE(uint32_t i0) { return 0x00000004 + __offset_LM(i0); }
 #define MDP5_LM_OUT_SIZE_HEIGHT__MASK				0xffff0000
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH 3/9] drm/msm/mdp5: Prepare CRTC/LM for empty stages
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
  2016-12-19 12:08 ` [PATCH 1/9] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
  2016-12-19 12:08 ` [PATCH 2/9] drm/msm/mdp5: Update generated headers Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [PATCH 4/9] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles Archit Taneja
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

Use SSPP_NONE in mdp5_plane_pipe() if there is now hwpipe allocated for
the drm_plane. Returning '0' means we are returning VIG0 pipe.

Also, use the mdp5_pipe enum to pass around the stage array. Initialize
the stage to SSPP_NONE by default.

We do the above because 1) Cursor plane has to be staged at the topmost
blender of the LM, which can result in empty stages in between 2) In
the future, when we support multiple LMs per CRTC. We could have stages
which don't have any pipe assigned to them.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  | 2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   | 4 ++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h   | 4 ++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 1ce8a01..7a47209 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -195,7 +195,7 @@ static void blend_setup(struct drm_crtc *crtc)
 	uint32_t lm = mdp5_crtc->lm;
 	uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0;
 	unsigned long flags;
-	uint8_t stage[STAGE_MAX + 1];
+	enum mdp5_pipe stage[STAGE_MAX + 1] = { SSPP_NONE };
 	int i, plane_cnt = 0;
 #define blender(stage)	((stage) - STAGE0)
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index d021edc..ab339ce 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -351,8 +351,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
 	}
 }
 
-int mdp5_ctl_blend(struct mdp5_ctl *ctl, u8 *stage, u32 stage_cnt,
-	u32 ctl_blend_op_flags)
+int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
+		   u32 ctl_blend_op_flags)
 {
 	unsigned long flags;
 	u32 blend_cfg = 0, blend_ext_cfg = 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index 96148c6..fda00d3 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -56,8 +56,8 @@ int mdp5_ctl_set_pipeline(struct mdp5_ctl *ctl, struct mdp5_interface *intf,
  * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask)
  */
 #define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT	BIT(0)
-int mdp5_ctl_blend(struct mdp5_ctl *ctl, u8 *stage, u32 stage_cnt,
-	u32 ctl_blend_op_flags);
+int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
+		   u32 ctl_blend_op_flags);
 
 /**
  * mdp_ctl_flush_mask...() - Register FLUSH masks
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 75247ea..72a9f98 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -836,7 +836,7 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
 	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
 
 	if (WARN_ON(!pstate->hwpipe))
-		return 0;
+		return SSPP_NONE;
 
 	return pstate->hwpipe->pipe;
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH 4/9] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (2 preceding siblings ...)
  2016-12-19 12:08 ` [PATCH 3/9] drm/msm/mdp5: Prepare CRTC/LM for empty stages Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [PATCH 5/9] drm/msm/mdp5: Configure COLOR3_OUT propagation Archit Taneja
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

The MDP5 plane's atomic_check ops doesn't perform clipping tests.
This didn't hurt us much in the past, but clipping becomes important
with cursor planes.

Use drm_plane_helper_check_state, the way rockchip/intel/mtk drivers
already do. Clipping requires knowledge of the crtc width and height.
This requires us to call drm_atomic_helper_check_modeset before
drm_atomic_helper_check_planes in the driver's atomic_check op,
because check_modetest will populate the mode for the crtc, needed
to populate the clip rectangle.

We also replace the plane_enabled(state) local helper with
state->visible, since they both represent the same thing (i.e, whether
state->fb and state->crtc are non-NULL or not).

One issue with the existing code is that we don't have a way to disable
the plane when it's completely clipped out. Until there isn't an update
on the crtc (which would de-stage the plane), we would still see the
plane in its last 'visible' configuration.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 59 +++++++++++++++++++++++--------
 drivers/gpu/drm/msm/msm_atomic.c          | 21 +++++++----
 2 files changed, 60 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 72a9f98..929e58c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -29,10 +29,7 @@ struct mdp5_plane {
 
 static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
-		int crtc_x, int crtc_y,
-		unsigned int crtc_w, unsigned int crtc_h,
-		uint32_t src_x, uint32_t src_y,
-		uint32_t src_w, uint32_t src_h);
+		struct drm_rect *src, struct drm_rect *dest);
 
 static void set_scanout_locked(struct drm_plane *plane,
 		struct drm_framebuffer *fb);
@@ -275,6 +272,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
 	msm_framebuffer_cleanup(fb, mdp5_kms->id);
 }
 
+#define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
 static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		struct drm_plane_state *state)
 {
@@ -283,11 +281,20 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 	struct mdp5_cfg *config = mdp5_cfg_get_config(get_kms(plane)->cfg);
 	bool new_hwpipe = false;
 	uint32_t max_width, max_height;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip;
+	int min_scale, max_scale;
 	uint32_t caps = 0;
+	int ret;
 
 	DBG("%s: check (%d -> %d)", plane->name,
 			plane_enabled(old_state), plane_enabled(state));
 
+	crtc = state->crtc ? state->crtc : plane->state->crtc;
+	if (!crtc)
+		return 0;
+
 	/* We don't allow faster-than-vblank updates.. if we did add this
 	 * some day, we would need to disallow in cases where hwpipe
 	 * changes
@@ -306,7 +313,23 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		return -ERANGE;
 	}
 
-	if (plane_enabled(state)) {
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->adjusted_mode.hdisplay;
+	clip.y2 = crtc_state->adjusted_mode.vdisplay;
+	min_scale = FRAC_16_16(1, 8);
+	max_scale = FRAC_16_16(8, 1);
+
+	ret = drm_plane_helper_check_state(state, &clip, min_scale,
+					   max_scale, true, true);
+	if (ret)
+		return ret;
+
+	if (state->visible) {
 		unsigned int rotation;
 		const struct mdp_format *format;
 		struct mdp5_kms *mdp5_kms = get_kms(plane);
@@ -376,15 +399,12 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
 
 	mdp5_state->pending = true;
 
-	if (plane_enabled(state)) {
+	if (state->visible) {
 		int ret;
 
 		ret = mdp5_plane_mode_set(plane,
 				state->crtc, state->fb,
-				state->crtc_x, state->crtc_y,
-				state->crtc_w, state->crtc_h,
-				state->src_x,  state->src_y,
-				state->src_w, state->src_h);
+				&state->src, &state->dst);
 		/* atomic_check should have ensured that this doesn't fail */
 		WARN_ON(ret < 0);
 	}
@@ -677,10 +697,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
 
 static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
-		int crtc_x, int crtc_y,
-		unsigned int crtc_w, unsigned int crtc_h,
-		uint32_t src_x, uint32_t src_y,
-		uint32_t src_w, uint32_t src_h)
+		struct drm_rect *src, struct drm_rect *dest)
 {
 	struct drm_plane_state *pstate = plane->state;
 	struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(pstate)->hwpipe;
@@ -696,6 +713,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	uint32_t pix_format;
 	unsigned int rotation;
 	bool vflip, hflip;
+	int crtc_x, crtc_y;
+	unsigned int crtc_w, crtc_h;
+	uint32_t src_x, src_y;
+	uint32_t src_w, src_h;
 	unsigned long flags;
 	int ret;
 
@@ -708,6 +729,16 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	format = to_mdp_format(msm_framebuffer_format(fb));
 	pix_format = format->base.pixel_format;
 
+	src_x = src->x1;
+	src_y = src->y1;
+	src_w = drm_rect_width(src);
+	src_h = drm_rect_height(src);
+
+	crtc_x = dest->x1;
+	crtc_y = dest->y1;
+	crtc_w = drm_rect_width(dest);
+	crtc_h = drm_rect_height(dest);
+
 	/* src values are in Q16 fixed point, convert to integer: */
 	src_x = src_x >> 16;
 	src_y = src_y >> 16;
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 30b5d23..6924fa2 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -151,20 +151,29 @@ static void commit_worker(struct work_struct *work)
 	complete_commit(container_of(work, struct msm_commit, work), true);
 }
 
+/*
+ * this func is identical to the drm_atomic_helper_check, but we keep this
+ * because we might eventually need to have a more finegrained check
+ * sequence without using the atomic helpers.
+ *
+ * In the past, we first called drm_atomic_helper_check_planes, and then
+ * drm_atomic_helper_check_modeset. We needed this because the MDP5 plane's
+ * ->atomic_check could update ->mode_changed for pixel format changes.
+ * This, however isn't needed now because if there is a pixel format change,
+ * we just assign a new hwpipe for it with a new SMP allocation. We might
+ * eventually hit a condition where we would need to do a full modeset if
+ * we run out of planes. There, we'd probably need to set mode_changed.
+ */
 int msm_atomic_check(struct drm_device *dev,
 		     struct drm_atomic_state *state)
 {
 	int ret;
 
-	/*
-	 * msm ->atomic_check can update ->mode_changed for pixel format
-	 * changes, hence must be run before we check the modeset changes.
-	 */
-	ret = drm_atomic_helper_check_planes(dev, state);
+	ret = drm_atomic_helper_check_modeset(dev, state);
 	if (ret)
 		return ret;
 
-	ret = drm_atomic_helper_check_modeset(dev, state);
+	ret = drm_atomic_helper_check_planes(dev, state);
 	if (ret)
 		return ret;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH 5/9] drm/msm/mdp5: Configure COLOR3_OUT propagation
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (3 preceding siblings ...)
  2016-12-19 12:08 ` [PATCH 4/9] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [PATCH 6/9] drm/msm/mdp5: Misc cursor plane bits Archit Taneja
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

In MDP5 Layer Mixer HW, the blender output is only the blended color
components (i.e R, G and B, or COLOR0/1/2 in MDP5 HW terminology). This
is fed to the BG input of the next blender. We also need to provide an
alpha (COLOR3) value for the BG input at the next stage.

This is configured via using the REG_MDP5_LM_BLEND_COLOR_OUT register.
For each stage, we can propagate either the BG or FG alpha to the next
stage.

The approach taken by the driver is to propagate FG alpha, if the plane
staged on that blender has an alpha. If it doesn't, we try to propagate
the base layer's alpha.

This is borrowed from downstream MDP5 kernel driver. Without this, we
don't see any cursor plane content.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 7a47209..fec9662 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -177,6 +177,21 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc)
 	kfree(mdp5_crtc);
 }
 
+static inline u32 mdp5_lm_use_fg_alpha_mask(enum mdp_mixer_stage_id stage)
+{
+	switch (stage) {
+	case STAGE0: return MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA;
+	case STAGE1: return MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA;
+	case STAGE2: return MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA;
+	case STAGE3: return MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA;
+	case STAGE4: return MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA;
+	case STAGE5: return MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA;
+	case STAGE6: return MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA;
+	default:
+		return 0;
+	}
+}
+
 /*
  * blend_setup() - blend all the planes of a CRTC
  *
@@ -197,6 +212,8 @@ static void blend_setup(struct drm_crtc *crtc)
 	unsigned long flags;
 	enum mdp5_pipe stage[STAGE_MAX + 1] = { SSPP_NONE };
 	int i, plane_cnt = 0;
+	bool bg_alpha_enabled = false;
+	u32 mixer_op_mode = 0;
 #define blender(stage)	((stage) - STAGE0)
 
 	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
@@ -218,6 +235,11 @@ static void blend_setup(struct drm_crtc *crtc)
 	if (!pstates[STAGE_BASE]) {
 		ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT;
 		DBG("Border Color is enabled");
+	} else if (plane_cnt) {
+		format = to_mdp_format(msm_framebuffer_format(pstates[STAGE_BASE]->base.fb));
+
+		if (format->alpha_enable)
+			bg_alpha_enabled = true;
 	}
 
 	/* The reset for blending */
@@ -232,6 +254,12 @@ static void blend_setup(struct drm_crtc *crtc)
 			MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST);
 		fg_alpha = pstates[i]->alpha;
 		bg_alpha = 0xFF - pstates[i]->alpha;
+
+		if (!format->alpha_enable && bg_alpha_enabled)
+			mixer_op_mode = 0;
+		else
+			mixer_op_mode |= mdp5_lm_use_fg_alpha_mask(i);
+
 		DBG("Stage %d fg_alpha %x bg_alpha %x", i, fg_alpha, bg_alpha);
 
 		if (format->alpha_enable && pstates[i]->premultiplied) {
@@ -268,6 +296,8 @@ static void blend_setup(struct drm_crtc *crtc)
 				blender(i)), bg_alpha);
 	}
 
+	mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm), mixer_op_mode);
+
 	mdp5_ctl_blend(mdp5_crtc->ctl, stage, plane_cnt, ctl_blend_flags);
 
 out:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH 6/9] drm/msm/mdp5: Misc cursor plane bits
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (4 preceding siblings ...)
  2016-12-19 12:08 ` [PATCH 5/9] drm/msm/mdp5: Configure COLOR3_OUT propagation Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [PATCH 7/9] drm/msm/mdp5: Refactor mdp5_plane_atomic_check Archit Taneja
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

These are various changes in preparation for cursor planes:

- Add a pipe_cursor block for 8x96 in mdp5_cfg.
- Add a new pipe CAP called MDP_PIPE_CAP_CURSOR. Use this to ensure we
  assign a cursor SSPP for a drm_plane with type DRM_PLANE_TYPE_CURSOR.
- Update mdp5_ctl_blend/ext_blend masks to incorporate cursor SSPPs.
- In mdp5_crtc_atomic_check, make sure that the cursor plane has the
  highest zorder, and stage the cursor plane to the maximum stage #
  present on the HW.
- Create drm_crtc_funcs that doesn't try to implement cursors using the
  older LM cursor HW.
- Pass drm_plane_type in mdp5_plane_init instead of a bool telling
  whether plane is primary or not.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c   | 10 +++++++++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  | 34 +++++++++++++++++++++++++++----
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   | 10 +++++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   | 10 +++++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |  7 +++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c  |  8 ++++++++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c |  7 ++++---
 drivers/gpu/drm/msm/mdp/mdp_kms.h         |  1 +
 8 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 618b2ff..34ab553 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -421,6 +421,16 @@ struct mdp5_cfg_handler {
 			MDP_PIPE_CAP_SW_PIX_EXT	|
 			0,
 	},
+	.pipe_cursor = {
+		.count = 2,
+		.base = { 0x34000, 0x36000 },
+		.caps = MDP_PIPE_CAP_HFLIP	|
+			MDP_PIPE_CAP_VFLIP	|
+			MDP_PIPE_CAP_SW_PIX_EXT	|
+			MDP_PIPE_CAP_CURSOR	|
+			0,
+	},
+
 	.lm = {
 		.count = 6,
 		.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index fec9662..84fcb6e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 	struct plane_state pstates[STAGE_MAX + 1];
 	const struct mdp5_cfg_hw *hw_cfg;
 	const struct drm_plane_state *pstate;
+	bool cursor_plane = false;
 	int cnt = 0, base = 0, i;
 
 	DBG("%s: check", crtc->name);
@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 		pstates[cnt].state = to_mdp5_plane_state(pstate);
 
 		cnt++;
+
+		if (plane->type == DRM_PLANE_TYPE_CURSOR)
+			cursor_plane = true;
 	}
 
 	/* assign a stage based on sorted zpos property */
@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 	if ((cnt > 0) && !is_fullscreen(state, &pstates[0].state->base))
 		base++;
 
+	/* trigger a warning if cursor isn't the highest zorder */
+	WARN_ON(cursor_plane &&
+		(pstates[cnt - 1].plane->type != DRM_PLANE_TYPE_CURSOR));
+
 	/* verify that there are not too many planes attached to crtc
 	 * and that we don't have conflicting mixer stages:
 	 */
@@ -431,7 +439,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 	}
 
 	for (i = 0; i < cnt; i++) {
-		pstates[i].state->stage = STAGE_BASE + i + base;
+		if (cursor_plane && (i == (cnt - 1)))
+			pstates[i].state->stage = hw_cfg->lm.nb_stages;
+		else
+			pstates[i].state->stage = STAGE_BASE + i + base;
 		DBG("%s: assign pipe %s on stage=%d", crtc->name,
 				pstates[i].plane->name,
 				pstates[i].state->stage);
@@ -642,6 +653,16 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
 	.cursor_move = mdp5_crtc_cursor_move,
 };
 
+static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
+	.set_config = drm_atomic_helper_set_config,
+	.destroy = mdp5_crtc_destroy,
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_property = drm_atomic_helper_crtc_set_property,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
 static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
 	.mode_set_nofb = mdp5_crtc_mode_set_nofb,
 	.disable = mdp5_crtc_disable,
@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
 
 /* initialize crtc */
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
-		struct drm_plane *plane, int id)
+				struct drm_plane *plane,
+				struct drm_plane *cursor_plane, int id)
 {
 	struct drm_crtc *crtc = NULL;
 	struct mdp5_crtc *mdp5_crtc;
@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 	mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
 	mdp5_crtc->err.irq = mdp5_crtc_err_irq;
 
-	drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs,
-				  NULL);
+	if (cursor_plane)
+		drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
+					  &mdp5_crtc_no_lm_cursor_funcs, NULL);
+	else
+		drm_crtc_init_with_planes(dev, crtc, plane, NULL,
+					  &mdp5_crtc_funcs, NULL);
 
 	drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
 			"unref cursor", unref_cursor_worker);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index ab339ce..8b93f7e 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -326,6 +326,8 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
 	case SSPP_DMA1: return MDP5_CTL_LAYER_REG_DMA1(stage);
 	case SSPP_VIG3: return MDP5_CTL_LAYER_REG_VIG3(stage);
 	case SSPP_RGB3: return MDP5_CTL_LAYER_REG_RGB3(stage);
+	case SSPP_CURSOR0:
+	case SSPP_CURSOR1:
 	default:	return 0;
 	}
 }
@@ -333,7 +335,7 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
 static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
 		enum mdp_mixer_stage_id stage)
 {
-	if (stage < STAGE6)
+	if (stage < STAGE6 && (pipe != SSPP_CURSOR0 && pipe != SSPP_CURSOR1))
 		return 0;
 
 	switch (pipe) {
@@ -347,6 +349,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
 	case SSPP_DMA1: return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3;
 	case SSPP_VIG3: return MDP5_CTL_LAYER_EXT_REG_VIG3_BIT3;
 	case SSPP_RGB3: return MDP5_CTL_LAYER_EXT_REG_RGB3_BIT3;
+	case SSPP_CURSOR0: return MDP5_CTL_LAYER_EXT_REG_CURSOR0(stage);
+	case SSPP_CURSOR1: return MDP5_CTL_LAYER_EXT_REG_CURSOR1(stage);
 	default:	return 0;
 	}
 }
@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
 		start_stage = STAGE_BASE;
 	}
 
-	for (i = start_stage; i < start_stage + stage_cnt; i++) {
+	for (i = start_stage; stage_cnt && i <= STAGE_MAX; i++) {
 		blend_cfg |= mdp_ctl_blend_mask(stage[i], i);
 		blend_ext_cfg |= mdp_ctl_blend_ext_mask(stage[i], i);
 	}
@@ -422,6 +426,8 @@ u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)
 	case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
 	case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
 	case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3;
+	case SSPP_CURSOR0: return MDP5_CTL_FLUSH_CURSOR_0;
+	case SSPP_CURSOR1: return MDP5_CTL_FLUSH_CURSOR_1;
 	default:        return 0;
 	}
 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 84ec89d..2bebbc2 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -447,8 +447,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		bool primary = i < num_crtcs;
 		struct drm_plane *plane;
 		struct drm_crtc *crtc;
+		enum drm_plane_type type;
 
-		plane = mdp5_plane_init(dev, primary);
+		if (primary)
+			type = DRM_PLANE_TYPE_PRIMARY;
+		else
+			type = DRM_PLANE_TYPE_OVERLAY;
+
+		plane = mdp5_plane_init(dev, type);
 		if (IS_ERR(plane)) {
 			ret = PTR_ERR(plane);
 			dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret);
@@ -459,7 +465,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		if (!primary)
 			continue;
 
-		crtc  = mdp5_crtc_init(dev, plane, i);
+		crtc  = mdp5_crtc_init(dev, plane, NULL, i);
 		if (IS_ERR(crtc)) {
 			ret = PTR_ERR(crtc);
 			dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 9d22ff4..5be50c7 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -169,6 +169,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)
 		NAME(RGB0), NAME(RGB1), NAME(RGB2),
 		NAME(DMA0), NAME(DMA1),
 		NAME(VIG3), NAME(RGB3),
+		NAME(CURSOR0), NAME(CURSOR1),
 #undef NAME
 	};
 	return names[pipe];
@@ -246,7 +247,8 @@ void mdp5_set_irqmask(struct mdp_kms *mdp_kms, uint32_t irqmask,
 void mdp5_plane_complete_commit(struct drm_plane *plane,
 	struct drm_plane_state *state);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
-struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+				  enum drm_plane_type type);
 
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
@@ -255,7 +257,8 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
 		struct mdp5_interface *intf, struct mdp5_ctl *ctl);
 void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
-		struct drm_plane *plane, int id);
+				struct drm_plane *plane,
+				struct drm_plane *cursor_plane, int id);
 
 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
 		struct mdp5_interface *intf, struct mdp5_ctl *ctl);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
index 1ae9dc8..35c4dab 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
 		if (caps & ~cur->caps)
 			continue;
 
+		/*
+		 * don't assign a cursor pipe to a plane that isn't going to
+		 * be used as a cursor
+		 */
+		if (cur->caps & MDP_PIPE_CAP_CURSOR &&
+				plane->type != DRM_PLANE_TYPE_CURSOR)
+			continue;
+
 		/* possible candidate, take the one with the
 		 * fewest unneeded caps bits set:
 		 */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 929e58c..c813ea7 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -354,6 +354,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		if (rotation & DRM_REFLECT_Y)
 			caps |= MDP_PIPE_CAP_VFLIP;
 
+		if (plane->type == DRM_PLANE_TYPE_CURSOR)
+			caps |= MDP_PIPE_CAP_CURSOR;
+
 		/* (re)allocate hw pipe if we don't have one or caps-mismatch: */
 		if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps))
 			new_hwpipe = true;
@@ -892,12 +895,11 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
 }
 
 /* initialize plane */
-struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
+struct drm_plane *mdp5_plane_init(struct drm_device *dev, enum drm_plane_type type)
 {
 	struct drm_plane *plane = NULL;
 	struct mdp5_plane *mdp5_plane;
 	int ret;
-	enum drm_plane_type type;
 
 	mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
 	if (!mdp5_plane) {
@@ -910,7 +912,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 	mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
 		ARRAY_SIZE(mdp5_plane->formats), false);
 
-	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
 				 mdp5_plane->formats, mdp5_plane->nformats,
 				 type, NULL);
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 3031303..7574cdf 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -112,6 +112,7 @@ struct mdp_format {
 #define MDP_PIPE_CAP_CSC			BIT(3)
 #define MDP_PIPE_CAP_DECIMATION			BIT(4)
 #define MDP_PIPE_CAP_SW_PIX_EXT			BIT(5)
+#define MDP_PIPE_CAP_CURSOR			BIT(6)
 
 static inline bool pipe_supports_yuv(uint32_t pipe_caps)
 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH 7/9] drm/msm/mdp5: Refactor mdp5_plane_atomic_check
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (5 preceding siblings ...)
  2016-12-19 12:08 ` [PATCH 6/9] drm/msm/mdp5: Misc cursor plane bits Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:08 ` [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

In mdp5_plane_atomic_check, we get crtc_state from
drm_plane_state.

Later, for cursor planes, we'll populate the update_plane()
func that takes a fast asynchronous path to implement cursor
movements. There, we would need to call a similar atomic_check
func to validate the plane state, but crtc_state would need to
be derived differently.

Refactor mdp5_plane_atomic_check to mdp5_plane_atomic_check_with_state
such that the latter takes crtc_state as an argument.

This is similar to what the intel driver has done for async cursor
updates.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 32 +++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index c813ea7..107bb3a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -273,16 +273,15 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
 }
 
 #define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
-static int mdp5_plane_atomic_check(struct drm_plane *plane,
-		struct drm_plane_state *state)
+static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
+					      struct drm_plane_state *state)
 {
 	struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
+	struct drm_plane *plane = state->plane;
 	struct drm_plane_state *old_state = plane->state;
 	struct mdp5_cfg *config = mdp5_cfg_get_config(get_kms(plane)->cfg);
 	bool new_hwpipe = false;
 	uint32_t max_width, max_height;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
 	struct drm_rect clip;
 	int min_scale, max_scale;
 	uint32_t caps = 0;
@@ -291,10 +290,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 	DBG("%s: check (%d -> %d)", plane->name,
 			plane_enabled(old_state), plane_enabled(state));
 
-	crtc = state->crtc ? state->crtc : plane->state->crtc;
-	if (!crtc)
-		return 0;
-
 	/* We don't allow faster-than-vblank updates.. if we did add this
 	 * some day, we would need to disallow in cases where hwpipe
 	 * changes
@@ -313,10 +308,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		return -ERANGE;
 	}
 
-	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
-	if (WARN_ON(!crtc_state))
-		return -EINVAL;
-
 	clip.x1 = 0;
 	clip.y1 = 0;
 	clip.x2 = crtc_state->adjusted_mode.hdisplay;
@@ -392,6 +383,23 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 	return 0;
 }
 
+static int mdp5_plane_atomic_check(struct drm_plane *plane,
+				   struct drm_plane_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+
+	crtc = state->crtc ? state->crtc : plane->state->crtc;
+	if (!crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	return mdp5_plane_atomic_check_with_state(crtc_state, state);
+}
+
 static void mdp5_plane_atomic_update(struct drm_plane *plane,
 				     struct drm_plane_state *old_state)
 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (6 preceding siblings ...)
  2016-12-19 12:08 ` [PATCH 7/9] drm/msm/mdp5: Refactor mdp5_plane_atomic_check Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 12:50   ` Maarten Lankhorst
  2016-12-19 16:00   ` Daniel Vetter
  2016-12-19 12:08 ` [PATCH 9/9] drm/msm/mdp5: Add cursor planes Archit Taneja
                   ` (2 subsequent siblings)
  10 siblings, 2 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

This code has been more or less picked up from the vc4 and intel
implementations of update_plane() funcs for cursor planes.

The update_plane() func is usually the drm_atomic_helper_update_plane
func that will issue an atomic commit with the plane updates. Such
commits are not intended to be done faster than the vsync rate.

The legacy cursor userspace API, on the other hand, expects the kernel
to handle cursor updates immediately.

Create a fast path in update_plane, which updates the cursor registers
and flushes the configuration. The fast path is taken when there is only
a change in the cursor's position in the crtc, or a change in the
cursor's crop co-ordinates. For anything else, we go via the slow path.

We take the slow path even whenever the fb changes, and even when there
is currently no fb tied to the plane. This should hopefully ensure that
we always take a slow path for every new fb. The slow path will ensure
that the fb is prepared/pinned etc.

Cc: 
Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
- Don't know what to do for locking here :/

 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  |   7 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |   1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 109 +++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 84fcb6e..d0c8b38 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -778,6 +778,13 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
 	mdp5_ctl_set_pipeline(ctl, intf, lm);
 }
 
+struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
+{
+	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+	return mdp5_crtc->ctl;
+}
+
 int mdp5_crtc_get_lm(struct drm_crtc *crtc)
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 5be50c7..d3b728b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -250,6 +250,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 				  enum drm_plane_type type);
 
+struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
 int mdp5_crtc_get_lm(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 107bb3a..728dad7 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -31,6 +31,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		struct drm_rect *src, struct drm_rect *dest);
 
+static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
+		struct drm_crtc *crtc,
+		struct drm_framebuffer *fb,
+		int crtc_x, int crtc_y,
+		unsigned int crtc_w, unsigned int crtc_h,
+		uint32_t src_x, uint32_t src_y,
+		uint32_t src_w, uint32_t src_h);
+
 static void set_scanout_locked(struct drm_plane *plane,
 		struct drm_framebuffer *fb);
 
@@ -246,6 +254,19 @@ static void mdp5_plane_destroy_state(struct drm_plane *plane,
 		.atomic_print_state = mdp5_plane_atomic_print_state,
 };
 
+static const struct drm_plane_funcs mdp5_cursor_plane_funcs = {
+		.update_plane = mdp5_update_cursor_plane_legacy,
+		.disable_plane = drm_atomic_helper_disable_plane,
+		.destroy = mdp5_plane_destroy,
+		.set_property = drm_atomic_helper_plane_set_property,
+		.atomic_set_property = mdp5_plane_atomic_set_property,
+		.atomic_get_property = mdp5_plane_atomic_get_property,
+		.reset = mdp5_plane_reset,
+		.atomic_duplicate_state = mdp5_plane_duplicate_state,
+		.atomic_destroy_state = mdp5_plane_destroy_state,
+		.atomic_print_state = mdp5_plane_atomic_print_state,
+};
+
 static int mdp5_plane_prepare_fb(struct drm_plane *plane,
 				 struct drm_plane_state *new_state)
 {
@@ -873,6 +894,81 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	return ret;
 }
 
+static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
+			struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			int crtc_x, int crtc_y,
+			unsigned int crtc_w, unsigned int crtc_h,
+			uint32_t src_x, uint32_t src_y,
+			uint32_t src_w, uint32_t src_h)
+{
+	struct drm_plane_state *plane_state, *new_plane_state;
+	struct mdp5_plane_state *mdp5_pstate;
+	struct drm_crtc_state *crtc_state = crtc->state;
+	int ret;
+
+	if (!crtc_state->active || drm_atomic_crtc_needs_modeset(crtc_state))
+		goto slow;
+
+	plane_state = plane->state;
+	mdp5_pstate = to_mdp5_plane_state(plane_state);
+
+	/* don't use fast path if we don't have a hwpipe allocated yet */
+	if (!mdp5_pstate->hwpipe)
+		goto slow;
+
+	/* only allow changing of position(crtc x/y or src x/y) in fast path */
+	if (plane_state->crtc != crtc ||
+	    plane_state->src_w != src_w ||
+	    plane_state->src_h != src_h ||
+	    plane_state->crtc_w != crtc_w ||
+	    plane_state->crtc_h != crtc_h ||
+	    !plane_state->fb ||
+	    plane_state->fb != fb)
+		goto slow;
+
+	new_plane_state = mdp5_plane_duplicate_state(plane);
+	if (!new_plane_state)
+		return -ENOMEM;
+
+	new_plane_state->src_x = src_x;
+	new_plane_state->src_y = src_y;
+	new_plane_state->src_w = src_w;
+	new_plane_state->src_h = src_h;
+	new_plane_state->crtc_x = crtc_x;
+	new_plane_state->crtc_y = crtc_y;
+	new_plane_state->crtc_w = crtc_w;
+	new_plane_state->crtc_h = crtc_h;
+
+	ret = mdp5_plane_atomic_check_with_state(crtc_state, new_plane_state);
+	if (ret)
+		goto slow_free;
+
+	if (new_plane_state->visible) {
+		struct mdp5_ctl *ctl;
+
+		ret = mdp5_plane_mode_set(plane, crtc, fb,
+					  &new_plane_state->src,
+					  &new_plane_state->dst);
+		WARN_ON(ret < 0);
+
+		ctl = mdp5_crtc_get_ctl(crtc);
+
+		mdp5_ctl_commit(ctl, mdp5_plane_get_flush(plane));
+	}
+
+	*to_mdp5_plane_state(plane_state) = *to_mdp5_plane_state(new_plane_state);
+
+	mdp5_plane_destroy_state(plane, new_plane_state);
+
+	return 0;
+slow_free:
+	mdp5_plane_destroy_state(plane, new_plane_state);
+slow:
+	return drm_atomic_helper_update_plane(plane, crtc, fb,
+					      crtc_x, crtc_y, crtc_w, crtc_h,
+					      src_x, src_y, src_w, src_h);
+}
+
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
 {
 	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
@@ -920,9 +1016,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, enum drm_plane_type ty
 	mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
 		ARRAY_SIZE(mdp5_plane->formats), false);
 
-	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
-				 mdp5_plane->formats, mdp5_plane->nformats,
-				 type, NULL);
+	if (type == DRM_PLANE_TYPE_CURSOR)
+		ret = drm_universal_plane_init(dev, plane, 0xff,
+				&mdp5_cursor_plane_funcs,
+				mdp5_plane->formats, mdp5_plane->nformats,
+				type, NULL);
+	else
+		ret = drm_universal_plane_init(dev, plane, 0xff,
+				&mdp5_plane_funcs,
+				mdp5_plane->formats, mdp5_plane->nformats,
+				type, NULL);
 	if (ret)
 		goto fail;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH 9/9] drm/msm/mdp5: Add cursor planes
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (7 preceding siblings ...)
  2016-12-19 12:08 ` [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
@ 2016-12-19 12:08 ` Archit Taneja
  2016-12-19 15:50 ` [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Daniel Vetter
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
  10 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-19 12:08 UTC (permalink / raw)
  To: robdclark
  Cc: linux-arm-msm, dri-devel, daniel, maarten.lankhorst, Archit Taneja

Register cursor drm_planes. The loop in modeset_init that inits the
planes and crtcs has to be refactored a bit. We first iterate all the
hwpipes to find the cursor planes. Then, we loop again to create
crtcs.

In msm_atomic_wait_for_commit_done, remove the check which bypasses
waiting for vsyncs if state->legacy_cursor_updates is true. We've created
a fast path for cursor position changes in the cursor plane's update_plane
func that doesn't go via the regular atomic commit path. For rest of
cursor related updates, we have to wait for the vsyncs, so ignore the
legacy_cursor_updates flag.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 32 +++++++++++++++++++++++++-------
 drivers/gpu/drm/msm/msm_atomic.c        |  5 -----
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 2bebbc2..dce9c23 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -417,7 +417,9 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	struct msm_drm_private *priv = dev->dev_private;
 	const struct mdp5_cfg_hw *hw_cfg;
 	unsigned int num_crtcs;
-	int i, ret;
+	int i, ret, pi = 0, ci = 0;
+	struct drm_plane *primary[6] = { NULL };
+	struct drm_plane *cursor[6] = { NULL };
 
 	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
 
@@ -444,13 +446,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	 * planes for the CRTCs, with the remainder as overlay planes:
 	 */
 	for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
-		bool primary = i < num_crtcs;
+		struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
 		struct drm_plane *plane;
-		struct drm_crtc *crtc;
 		enum drm_plane_type type;
 
-		if (primary)
+		if (i < num_crtcs)
 			type = DRM_PLANE_TYPE_PRIMARY;
+		else if (hwpipe->caps & MDP_PIPE_CAP_CURSOR)
+			type = DRM_PLANE_TYPE_CURSOR;
 		else
 			type = DRM_PLANE_TYPE_OVERLAY;
 
@@ -462,10 +465,16 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		}
 		priv->planes[priv->num_planes++] = plane;
 
-		if (!primary)
-			continue;
+		if (type == DRM_PLANE_TYPE_PRIMARY)
+			primary[pi++] = plane;
+		if (type == DRM_PLANE_TYPE_CURSOR)
+			cursor[ci++] = plane;
+	}
+
+	for (i = 0; i < num_crtcs; i++) {
+		struct drm_crtc *crtc;
 
-		crtc  = mdp5_crtc_init(dev, plane, NULL, i);
+		crtc  = mdp5_crtc_init(dev, primary[i], cursor[i], i);
 		if (IS_ERR(crtc)) {
 			ret = PTR_ERR(crtc);
 			dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
@@ -797,6 +806,9 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)
 	static const enum mdp5_pipe dma_planes[] = {
 			SSPP_DMA0, SSPP_DMA1,
 	};
+	static const enum mdp5_pipe cursor_planes[] = {
+			SSPP_CURSOR0, SSPP_CURSOR1,
+	};
 	const struct mdp5_cfg_hw *hw_cfg;
 	int ret;
 
@@ -820,6 +832,12 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)
 	if (ret)
 		return ret;
 
+	/* Construct cursor pipes: */
+	ret = construct_pipes(mdp5_kms, hw_cfg->pipe_cursor.count, cursor_planes,
+			hw_cfg->pipe_cursor.base, hw_cfg->pipe_cursor.caps);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 6924fa2..9633a68b 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -93,11 +93,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
 		if (!crtc->state->enable)
 			continue;
 
-		/* Legacy cursor ioctls are completely unsynced, and userspace
-		 * relies on that (by doing tons of cursor updates). */
-		if (old_state->legacy_cursor_update)
-			continue;
-
 		kms->funcs->wait_for_crtc_commit_done(kms, crtc);
 	}
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-19 12:08 ` [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
@ 2016-12-19 12:50   ` Maarten Lankhorst
  2016-12-20  6:23     ` Archit Taneja
  2016-12-19 16:00   ` Daniel Vetter
  1 sibling, 1 reply; 26+ messages in thread
From: Maarten Lankhorst @ 2016-12-19 12:50 UTC (permalink / raw)
  To: Archit Taneja, robdclark; +Cc: linux-arm-msm, dri-devel, daniel

Op 19-12-16 om 13:08 schreef Archit Taneja:
> This code has been more or less picked up from the vc4 and intel
> implementations of update_plane() funcs for cursor planes.
>
> The update_plane() func is usually the drm_atomic_helper_update_plane
> func that will issue an atomic commit with the plane updates. Such
> commits are not intended to be done faster than the vsync rate.
>
> The legacy cursor userspace API, on the other hand, expects the kernel
> to handle cursor updates immediately.
>
> Create a fast path in update_plane, which updates the cursor registers
> and flushes the configuration. The fast path is taken when there is only
> a change in the cursor's position in the crtc, or a change in the
> cursor's crop co-ordinates. For anything else, we go via the slow path.
>
> We take the slow path even whenever the fb changes, and even when there
> is currently no fb tied to the plane. This should hopefully ensure that
> we always take a slow path for every new fb. The slow path will ensure
> that the fb is prepared/pinned etc.
>
> Cc: 
> Signed-off-by: Archit Taneja <architt@codeaurora.org>
> ---
> - Don't know what to do for locking here :/
Shouldn't patch 9 be done first before 8?

~Maarten

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

* Re: [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (8 preceding siblings ...)
  2016-12-19 12:08 ` [PATCH 9/9] drm/msm/mdp5: Add cursor planes Archit Taneja
@ 2016-12-19 15:50 ` Daniel Vetter
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
  10 siblings, 0 replies; 26+ messages in thread
From: Daniel Vetter @ 2016-12-19 15:50 UTC (permalink / raw)
  To: Archit Taneja
  Cc: robdclark, linux-arm-msm, dri-devel, daniel, maarten.lankhorst

On Mon, Dec 19, 2016 at 05:38:49PM +0530, Archit Taneja wrote:
> This series does some mdp5_plane related clean ups (use plane helpers
> for clipping etc), adds MDP5 bits needed for cursor plane blocks, and
> then add cursor planes.
> 
> On older MDP5 versions, we had cursor HW in Layer Mixer blocks, and
> that's implemented in mdp5_crtc.c. With newer hardware, the cursor
> blocks look exactly like MDP5 pipes (SSPPs).
> 
> The "faster than vblank cursor position update stuff" has been
> copied from vc4 and the patches posted recently by Maarten for Intel:
> 
> https://patchwork.kernel.org/patch/9466417/
> 
> I've tried this with some X11 UI and modetest -C, and it seems to
> work okay. Are there any tests that mix up atomic commits and legacy
> cursor updates a lot to identify issues?

kms_legacy_cursor mixes cursor updates with page_flips (and if you use
atomic for those, atomic flips ofcourse). But the test is a bit too
oveager and even expects cursor updates vs. modesets to not block. Not
sure Maarten fixed that already.
-Daniel

> 
> Archit Taneja (9):
>   drm/msm/mdp5: cfg: Add pipe_cursor block
>   drm/msm/mdp5: Update generated headers
>   drm/msm/mdp5: Prepare CRTC/LM for empty stages
>   drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
>   drm/msm/mdp5: Configure COLOR3_OUT propagation
>   drm/msm/mdp5: Misc cursor plane bits
>   drm/msm/mdp5: Refactor mdp5_plane_atomic_check
>   HACK: drm/msm/mdp5: Add support for legacy cursor updates
>   drm/msm/mdp5: Add cursor planes
> 
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h   |  30 +++--
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c   |  10 ++
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h   |   1 +
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  |  73 +++++++++++-
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   |  14 ++-
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h   |   4 +-
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   |  38 +++++--
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |   8 +-
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c  |   8 ++
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 181 ++++++++++++++++++++++++++----
>  drivers/gpu/drm/msm/mdp/mdp_kms.h         |   1 +
>  drivers/gpu/drm/msm/msm_atomic.c          |  26 +++--
>  12 files changed, 334 insertions(+), 60 deletions(-)
> 
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-19 12:08 ` [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
  2016-12-19 12:50   ` Maarten Lankhorst
@ 2016-12-19 16:00   ` Daniel Vetter
  2016-12-19 16:51     ` Daniel Vetter
  1 sibling, 1 reply; 26+ messages in thread
From: Daniel Vetter @ 2016-12-19 16:00 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-arm-msm, dri-devel

On Mon, Dec 19, 2016 at 05:38:57PM +0530, Archit Taneja wrote:
> This code has been more or less picked up from the vc4 and intel
> implementations of update_plane() funcs for cursor planes.
> 
> The update_plane() func is usually the drm_atomic_helper_update_plane
> func that will issue an atomic commit with the plane updates. Such
> commits are not intended to be done faster than the vsync rate.
> 
> The legacy cursor userspace API, on the other hand, expects the kernel
> to handle cursor updates immediately.
> 
> Create a fast path in update_plane, which updates the cursor registers
> and flushes the configuration. The fast path is taken when there is only
> a change in the cursor's position in the crtc, or a change in the
> cursor's crop co-ordinates. For anything else, we go via the slow path.
> 
> We take the slow path even whenever the fb changes, and even when there
> is currently no fb tied to the plane. This should hopefully ensure that
> we always take a slow path for every new fb. The slow path will ensure
> that the fb is prepared/pinned etc.
> 
> Cc: 
> Signed-off-by: Archit Taneja <architt@codeaurora.org>

I wonder whether it's time to extract this pattern into some helpers. I
think a combo of async_check and async_flip callbacks on planes should do
the trick and integrate somewhat into atomic overall. amdgpu also needs
this for async flips on the primary plane.

Both async_check and async_flip would take only (struct drm_plane *plane,
struct drm_plane_state *state) as arguments. Maybe we should even wrap
that up into an struct drm_async_flip so that we can add more stuff in the
future.

But all still a bit unclear to me.

> ---
> - Don't know what to do for locking here :/
> 
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  |   7 ++
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |   1 +
>  drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 109 +++++++++++++++++++++++++++++-
>  3 files changed, 114 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> index 84fcb6e..d0c8b38 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
> @@ -778,6 +778,13 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
>  	mdp5_ctl_set_pipeline(ctl, intf, lm);
>  }
>  
> +struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
> +{
> +	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
> +
> +	return mdp5_crtc->ctl;
> +}
> +
>  int mdp5_crtc_get_lm(struct drm_crtc *crtc)
>  {
>  	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
> index 5be50c7..d3b728b 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
> @@ -250,6 +250,7 @@ void mdp5_plane_complete_commit(struct drm_plane *plane,
>  struct drm_plane *mdp5_plane_init(struct drm_device *dev,
>  				  enum drm_plane_type type);
>  
> +struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
>  uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
>  
>  int mdp5_crtc_get_lm(struct drm_crtc *crtc);
> diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> index 107bb3a..728dad7 100644
> --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
> @@ -31,6 +31,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
>  		struct drm_crtc *crtc, struct drm_framebuffer *fb,
>  		struct drm_rect *src, struct drm_rect *dest);
>  
> +static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
> +		struct drm_crtc *crtc,
> +		struct drm_framebuffer *fb,
> +		int crtc_x, int crtc_y,
> +		unsigned int crtc_w, unsigned int crtc_h,
> +		uint32_t src_x, uint32_t src_y,
> +		uint32_t src_w, uint32_t src_h);
> +
>  static void set_scanout_locked(struct drm_plane *plane,
>  		struct drm_framebuffer *fb);
>  
> @@ -246,6 +254,19 @@ static void mdp5_plane_destroy_state(struct drm_plane *plane,
>  		.atomic_print_state = mdp5_plane_atomic_print_state,
>  };
>  
> +static const struct drm_plane_funcs mdp5_cursor_plane_funcs = {
> +		.update_plane = mdp5_update_cursor_plane_legacy,
> +		.disable_plane = drm_atomic_helper_disable_plane,
> +		.destroy = mdp5_plane_destroy,
> +		.set_property = drm_atomic_helper_plane_set_property,
> +		.atomic_set_property = mdp5_plane_atomic_set_property,
> +		.atomic_get_property = mdp5_plane_atomic_get_property,
> +		.reset = mdp5_plane_reset,
> +		.atomic_duplicate_state = mdp5_plane_duplicate_state,
> +		.atomic_destroy_state = mdp5_plane_destroy_state,
> +		.atomic_print_state = mdp5_plane_atomic_print_state,
> +};
> +
>  static int mdp5_plane_prepare_fb(struct drm_plane *plane,
>  				 struct drm_plane_state *new_state)
>  {
> @@ -873,6 +894,81 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
>  	return ret;
>  }
>  
> +static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
> +			struct drm_crtc *crtc, struct drm_framebuffer *fb,
> +			int crtc_x, int crtc_y,
> +			unsigned int crtc_w, unsigned int crtc_h,
> +			uint32_t src_x, uint32_t src_y,
> +			uint32_t src_w, uint32_t src_h)
> +{
> +	struct drm_plane_state *plane_state, *new_plane_state;
> +	struct mdp5_plane_state *mdp5_pstate;
> +	struct drm_crtc_state *crtc_state = crtc->state;
> +	int ret;
> +
> +	if (!crtc_state->active || drm_atomic_crtc_needs_modeset(crtc_state))

Until you do some kind of normal flip on the primary after a modeset no
one will ever change the needs_modeset(crtc_state) if you only ever do
async flips. Sounds like a bug, and vc4 doesn't check for it. Why do you
need this?

> +		goto slow;
> +
> +	plane_state = plane->state;
> +	mdp5_pstate = to_mdp5_plane_state(plane_state);
> +
> +	/* don't use fast path if we don't have a hwpipe allocated yet */
> +	if (!mdp5_pstate->hwpipe)
> +		goto slow;
> +
> +	/* only allow changing of position(crtc x/y or src x/y) in fast path */
> +	if (plane_state->crtc != crtc ||
> +	    plane_state->src_w != src_w ||
> +	    plane_state->src_h != src_h ||
> +	    plane_state->crtc_w != crtc_w ||
> +	    plane_state->crtc_h != crtc_h ||
> +	    !plane_state->fb ||
> +	    plane_state->fb != fb)
> +		goto slow;
> +
> +	new_plane_state = mdp5_plane_duplicate_state(plane);
> +	if (!new_plane_state)
> +		return -ENOMEM;
> +
> +	new_plane_state->src_x = src_x;
> +	new_plane_state->src_y = src_y;
> +	new_plane_state->src_w = src_w;
> +	new_plane_state->src_h = src_h;
> +	new_plane_state->crtc_x = crtc_x;
> +	new_plane_state->crtc_y = crtc_y;
> +	new_plane_state->crtc_w = crtc_w;
> +	new_plane_state->crtc_h = crtc_h;
> +
> +	ret = mdp5_plane_atomic_check_with_state(crtc_state, new_plane_state);
> +	if (ret)
> +		goto slow_free;
> +
> +	if (new_plane_state->visible) {
> +		struct mdp5_ctl *ctl;
> +
> +		ret = mdp5_plane_mode_set(plane, crtc, fb,
> +					  &new_plane_state->src,
> +					  &new_plane_state->dst);
> +		WARN_ON(ret < 0);
> +
> +		ctl = mdp5_crtc_get_ctl(crtc);
> +
> +		mdp5_ctl_commit(ctl, mdp5_plane_get_flush(plane));
> +	}
> +
> +	*to_mdp5_plane_state(plane_state) = *to_mdp5_plane_state(new_plane_state);
> +
> +	mdp5_plane_destroy_state(plane, new_plane_state);

Even if the don't go the full monty, at least a
drm_legacy_cursor_helper_update_plane which encodes the above would be
good. I think it should be possible to code it up using the ->atomic_check
and ->atomic_update callbacks ...

But just ideas really, might be better to wait for yet another driver to
explore this space before we consolidate ;-)
-Daniel

> +
> +	return 0;
> +slow_free:
> +	mdp5_plane_destroy_state(plane, new_plane_state);
> +slow:
> +	return drm_atomic_helper_update_plane(plane, crtc, fb,
> +					      crtc_x, crtc_y, crtc_w, crtc_h,
> +					      src_x, src_y, src_w, src_h);
> +}
> +
>  enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
>  {
>  	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
> @@ -920,9 +1016,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, enum drm_plane_type ty
>  	mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
>  		ARRAY_SIZE(mdp5_plane->formats), false);
>  
> -	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
> -				 mdp5_plane->formats, mdp5_plane->nformats,
> -				 type, NULL);
> +	if (type == DRM_PLANE_TYPE_CURSOR)
> +		ret = drm_universal_plane_init(dev, plane, 0xff,
> +				&mdp5_cursor_plane_funcs,
> +				mdp5_plane->formats, mdp5_plane->nformats,
> +				type, NULL);
> +	else
> +		ret = drm_universal_plane_init(dev, plane, 0xff,
> +				&mdp5_plane_funcs,
> +				mdp5_plane->formats, mdp5_plane->nformats,
> +				type, NULL);
>  	if (ret)
>  		goto fail;
>  
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-19 16:00   ` Daniel Vetter
@ 2016-12-19 16:51     ` Daniel Vetter
  0 siblings, 0 replies; 26+ messages in thread
From: Daniel Vetter @ 2016-12-19 16:51 UTC (permalink / raw)
  To: Archit Taneja; +Cc: linux-arm-msm, dri-devel

On Mon, Dec 19, 2016 at 05:00:49PM +0100, Daniel Vetter wrote:
> On Mon, Dec 19, 2016 at 05:38:57PM +0530, Archit Taneja wrote:
> > @@ -873,6 +894,81 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
> >  	return ret;
> >  }
> >  
> > +static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
> > +			struct drm_crtc *crtc, struct drm_framebuffer *fb,
> > +			int crtc_x, int crtc_y,
> > +			unsigned int crtc_w, unsigned int crtc_h,
> > +			uint32_t src_x, uint32_t src_y,
> > +			uint32_t src_w, uint32_t src_h)
> > +{
> > +	struct drm_plane_state *plane_state, *new_plane_state;
> > +	struct mdp5_plane_state *mdp5_pstate;
> > +	struct drm_crtc_state *crtc_state = crtc->state;
> > +	int ret;
> > +
> > +	if (!crtc_state->active || drm_atomic_crtc_needs_modeset(crtc_state))
> 
> Until you do some kind of normal flip on the primary after a modeset no
> one will ever change the needs_modeset(crtc_state) if you only ever do
> async flips. Sounds like a bug, and vc4 doesn't check for it. Why do you
> need this?

Self-correct: The slow-path will duplicate the crtc state also and clear
needs_modeset, which means only the very first cursor move after a modeset
will be slow. I think that's ok.

But this kind of trickery is a good reason to try to extract this logic a
bit better I think.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-19 12:50   ` Maarten Lankhorst
@ 2016-12-20  6:23     ` Archit Taneja
  2016-12-20 13:40       ` Maarten Lankhorst
  0 siblings, 1 reply; 26+ messages in thread
From: Archit Taneja @ 2016-12-20  6:23 UTC (permalink / raw)
  To: Maarten Lankhorst, robdclark; +Cc: linux-arm-msm, dri-devel, daniel



On 12/19/2016 06:20 PM, Maarten Lankhorst wrote:
> Op 19-12-16 om 13:08 schreef Archit Taneja:
>> This code has been more or less picked up from the vc4 and intel
>> implementations of update_plane() funcs for cursor planes.
>>
>> The update_plane() func is usually the drm_atomic_helper_update_plane
>> func that will issue an atomic commit with the plane updates. Such
>> commits are not intended to be done faster than the vsync rate.
>>
>> The legacy cursor userspace API, on the other hand, expects the kernel
>> to handle cursor updates immediately.
>>
>> Create a fast path in update_plane, which updates the cursor registers
>> and flushes the configuration. The fast path is taken when there is only
>> a change in the cursor's position in the crtc, or a change in the
>> cursor's crop co-ordinates. For anything else, we go via the slow path.
>>
>> We take the slow path even whenever the fb changes, and even when there
>> is currently no fb tied to the plane. This should hopefully ensure that
>> we always take a slow path for every new fb. The slow path will ensure
>> that the fb is prepared/pinned etc.
>>
>> Cc:
>> Signed-off-by: Archit Taneja <architt@codeaurora.org>
>> ---
>> - Don't know what to do for locking here :/
> Shouldn't patch 9 be done first before 8?

Patch 9 introduces cursor drm_planes for the first time, so
anything done in 8 doesn't really take effect until we add
the planes in patch 9. So it's safe to have this order.

Archit


>
> ~Maarten
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-20  6:23     ` Archit Taneja
@ 2016-12-20 13:40       ` Maarten Lankhorst
  2016-12-21  5:23         ` Archit Taneja
  0 siblings, 1 reply; 26+ messages in thread
From: Maarten Lankhorst @ 2016-12-20 13:40 UTC (permalink / raw)
  To: Archit Taneja, robdclark; +Cc: linux-arm-msm, dri-devel

Op 20-12-16 om 07:23 schreef Archit Taneja:
>
>
> On 12/19/2016 06:20 PM, Maarten Lankhorst wrote:
>> Op 19-12-16 om 13:08 schreef Archit Taneja:
>>> This code has been more or less picked up from the vc4 and intel
>>> implementations of update_plane() funcs for cursor planes.
>>>
>>> The update_plane() func is usually the drm_atomic_helper_update_plane
>>> func that will issue an atomic commit with the plane updates. Such
>>> commits are not intended to be done faster than the vsync rate.
>>>
>>> The legacy cursor userspace API, on the other hand, expects the kernel
>>> to handle cursor updates immediately.
>>>
>>> Create a fast path in update_plane, which updates the cursor registers
>>> and flushes the configuration. The fast path is taken when there is only
>>> a change in the cursor's position in the crtc, or a change in the
>>> cursor's crop co-ordinates. For anything else, we go via the slow path.
>>>
>>> We take the slow path even whenever the fb changes, and even when there
>>> is currently no fb tied to the plane. This should hopefully ensure that
>>> we always take a slow path for every new fb. The slow path will ensure
>>> that the fb is prepared/pinned etc.
>>>
>>> Cc:
>>> Signed-off-by: Archit Taneja <architt@codeaurora.org>
>>> ---
>>> - Don't know what to do for locking here :/
>> Shouldn't patch 9 be done first before 8?
>
> Patch 9 introduces cursor drm_planes for the first time, so
> anything done in 8 doesn't really take effect until we add
> the planes in patch 9. So it's safe to have this order. 
The other way around will allow you to test with the normal atomic helpers first, and then if the hack breaks you're able to bisect it correctly and revert it, that's why I think it should be the other way around. :)

~Maarten
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* Re: [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2016-12-20 13:40       ` Maarten Lankhorst
@ 2016-12-21  5:23         ` Archit Taneja
  0 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2016-12-21  5:23 UTC (permalink / raw)
  To: Maarten Lankhorst, robdclark; +Cc: linux-arm-msm, dri-devel



On 12/20/2016 07:10 PM, Maarten Lankhorst wrote:
> Op 20-12-16 om 07:23 schreef Archit Taneja:
>>
>>
>> On 12/19/2016 06:20 PM, Maarten Lankhorst wrote:
>>> Op 19-12-16 om 13:08 schreef Archit Taneja:
>>>> This code has been more or less picked up from the vc4 and intel
>>>> implementations of update_plane() funcs for cursor planes.
>>>>
>>>> The update_plane() func is usually the drm_atomic_helper_update_plane
>>>> func that will issue an atomic commit with the plane updates. Such
>>>> commits are not intended to be done faster than the vsync rate.
>>>>
>>>> The legacy cursor userspace API, on the other hand, expects the kernel
>>>> to handle cursor updates immediately.
>>>>
>>>> Create a fast path in update_plane, which updates the cursor registers
>>>> and flushes the configuration. The fast path is taken when there is only
>>>> a change in the cursor's position in the crtc, or a change in the
>>>> cursor's crop co-ordinates. For anything else, we go via the slow path.
>>>>
>>>> We take the slow path even whenever the fb changes, and even when there
>>>> is currently no fb tied to the plane. This should hopefully ensure that
>>>> we always take a slow path for every new fb. The slow path will ensure
>>>> that the fb is prepared/pinned etc.
>>>>
>>>> Cc:
>>>> Signed-off-by: Archit Taneja <architt@codeaurora.org>
>>>> ---
>>>> - Don't know what to do for locking here :/
>>> Shouldn't patch 9 be done first before 8?
>>
>> Patch 9 introduces cursor drm_planes for the first time, so
>> anything done in 8 doesn't really take effect until we add
>> the planes in patch 9. So it's safe to have this order.
> The other way around will allow you to test with the normal atomic helpers first, and then if the hack breaks you're able to bisect it correctly and revert it, that's why I think it should be the other way around. :)

Yeah, makes sense when you put it that way :). Will make sure the hack commit comes after
the cursor planes are supported the regular atomic way.

Archit

>
> ~Maarten
>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 0/8] drm/msm/mdp5: Cursor plane stuff
  2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
                   ` (9 preceding siblings ...)
  2016-12-19 15:50 ` [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Daniel Vetter
@ 2017-01-17  4:45 ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 1/8] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
                     ` (7 more replies)
  10 siblings, 8 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

This series does some mdp5_plane related clean ups (use plane helpers
for clipping etc), adds MDP5 bits needed for cursor plane blocks, and
then add cursor planes.

On older MDP5 versions, we had cursor HW in Layer Mixer blocks, and
that's implemented in mdp5_crtc.c. With newer hardware, the cursor
blocks look exactly like MDP5 pipes (SSPPs).

The "faster than vblank cursor position update stuff" has been
copied from vc4 and the patches posted recently by Maarten for Intel:

https://patchwork.kernel.org/patch/9466417/

Changes in v2:
- Dropped generated headers patch.
- Add the fast path patch in the end as suggested by Maarten.
- Minor cleanups.

Archit Taneja (8):
  drm/msm/mdp5: cfg: Add pipe_cursor block
  drm/msm/mdp5: Prepare CRTC/LM for empty stages
  drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
  drm/msm/mdp5: Configure COLOR3_OUT propagation
  drm/msm/mdp5: Misc cursor plane bits
  drm/msm/mdp5: Add cursor planes
  drm/msm/mdp5: Refactor mdp5_plane_atomic_check
  HACK: drm/msm/mdp5: Add support for legacy cursor updates

 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c   |  10 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h   |   1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  |  73 +++++++++++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   |  14 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h   |   4 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   |  39 +++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |   8 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c  |   8 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 181 +++++++++++++++++++++++++++---
 drivers/gpu/drm/msm/mdp/mdp_kms.h         |   1 +
 drivers/gpu/drm/msm/msm_atomic.c          |  26 +++--
 11 files changed, 316 insertions(+), 49 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 1/8] drm/msm/mdp5: cfg: Add pipe_cursor block
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 2/8] drm/msm/mdp5: Prepare CRTC/LM for empty stages Archit Taneja
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

Define the block in advance so that the generated mdp5.xml.h doesn't
break build.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
index bd4fe81d6160..b1c7daaede86 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.h
@@ -85,6 +85,7 @@ struct mdp5_cfg_hw {
 	struct mdp5_pipe_block pipe_vig;
 	struct mdp5_pipe_block pipe_rgb;
 	struct mdp5_pipe_block pipe_dma;
+	struct mdp5_pipe_block pipe_cursor;
 	struct mdp5_lm_block  lm;
 	struct mdp5_sub_block dspp;
 	struct mdp5_sub_block ad;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 2/8] drm/msm/mdp5: Prepare CRTC/LM for empty stages
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 1/8] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 3/8] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles Archit Taneja
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

Use SSPP_NONE in mdp5_plane_pipe() if there is now hwpipe allocated for
the drm_plane. Returning '0' means we are returning VIG0 pipe.

Also, use the mdp5_pipe enum to pass around the stage array. Initialize
the stage to SSPP_NONE by default.

We do the above because 1) Cursor plane has to be staged at the topmost
blender of the LM, which can result in empty stages in between 2) In
the future, when we support multiple LMs per CRTC. We could have stages
which don't have any pipe assigned to them.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  | 2 +-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   | 4 ++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h   | 4 ++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 1ce8a01a5a28..7a47209b0c6f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -195,7 +195,7 @@ static void blend_setup(struct drm_crtc *crtc)
 	uint32_t lm = mdp5_crtc->lm;
 	uint32_t blend_op, fg_alpha, bg_alpha, ctl_blend_flags = 0;
 	unsigned long flags;
-	uint8_t stage[STAGE_MAX + 1];
+	enum mdp5_pipe stage[STAGE_MAX + 1] = { SSPP_NONE };
 	int i, plane_cnt = 0;
 #define blender(stage)	((stage) - STAGE0)
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index d021edc3b307..ab339ce7425a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -351,8 +351,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
 	}
 }
 
-int mdp5_ctl_blend(struct mdp5_ctl *ctl, u8 *stage, u32 stage_cnt,
-	u32 ctl_blend_op_flags)
+int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
+		   u32 ctl_blend_op_flags)
 {
 	unsigned long flags;
 	u32 blend_cfg = 0, blend_ext_cfg = 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index 96148c6f863c..fda00d33e4db 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -56,8 +56,8 @@ int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable);
  * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask)
  */
 #define MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT	BIT(0)
-int mdp5_ctl_blend(struct mdp5_ctl *ctl, u8 *stage, u32 stage_cnt,
-	u32 ctl_blend_op_flags);
+int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
+		   u32 ctl_blend_op_flags);
 
 /**
  * mdp_ctl_flush_mask...() - Register FLUSH masks
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index b9fb111d3428..eb8dc7c36419 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -823,7 +823,7 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
 	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
 
 	if (WARN_ON(!pstate->hwpipe))
-		return 0;
+		return SSPP_NONE;
 
 	return pstate->hwpipe->pipe;
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 3/8] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 1/8] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 2/8] drm/msm/mdp5: Prepare CRTC/LM for empty stages Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 4/8] drm/msm/mdp5: Configure COLOR3_OUT propagation Archit Taneja
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

The MDP5 plane's atomic_check ops doesn't perform clipping tests.
This didn't hurt us much in the past, but clipping becomes important
with cursor planes.

Use drm_plane_helper_check_state, the way rockchip/intel/mtk drivers
already do. Use these drivers as reference.

Clipping requires knowledge of the crtc width and height. This requires
us to call drm_atomic_helper_check_modeset before
drm_atomic_helper_check_planes in the driver's atomic_check op, because
check_modetest will populate the mode for the crtc, needed to populate
the clip rectangle.

We update the plane_enabled(state) local helper to use state->visible,
since state->visible and 'state->fb && state->crtc' represent the same
thing.

One issue with the existing code is that we don't have a way to disable
the plane when it's completely clipped out. Until there isn't an update
on the crtc (which would de-stage the plane), we would still see the
plane in its last 'visible' configuration.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 57 ++++++++++++++++++++++++-------
 drivers/gpu/drm/msm/msm_atomic.c          | 21 ++++++++----
 2 files changed, 59 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index eb8dc7c36419..939991d5f346 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -29,10 +29,7 @@ struct mdp5_plane {
 
 static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
-		int crtc_x, int crtc_y,
-		unsigned int crtc_w, unsigned int crtc_h,
-		uint32_t src_x, uint32_t src_y,
-		uint32_t src_w, uint32_t src_h);
+		struct drm_rect *src, struct drm_rect *dest);
 
 static void set_scanout_locked(struct drm_plane *plane,
 		struct drm_framebuffer *fb);
@@ -45,7 +42,7 @@ static struct mdp5_kms *get_kms(struct drm_plane *plane)
 
 static bool plane_enabled(struct drm_plane_state *state)
 {
-	return state->fb && state->crtc;
+	return state->visible;
 }
 
 static void mdp5_plane_destroy(struct drm_plane *plane)
@@ -272,6 +269,7 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
 	msm_framebuffer_cleanup(fb, mdp5_kms->id);
 }
 
+#define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
 static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		struct drm_plane_state *state)
 {
@@ -281,10 +279,19 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 	bool new_hwpipe = false;
 	uint32_t max_width, max_height;
 	uint32_t caps = 0;
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+	struct drm_rect clip;
+	int min_scale, max_scale;
+	int ret;
 
 	DBG("%s: check (%d -> %d)", plane->name,
 			plane_enabled(old_state), plane_enabled(state));
 
+	crtc = state->crtc ? state->crtc : plane->state->crtc;
+	if (!crtc)
+		return 0;
+
 	max_width = config->hw->lm.max_width << 16;
 	max_height = config->hw->lm.max_height << 16;
 
@@ -296,6 +303,22 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		return -ERANGE;
 	}
 
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	clip.x1 = 0;
+	clip.y1 = 0;
+	clip.x2 = crtc_state->adjusted_mode.hdisplay;
+	clip.y2 = crtc_state->adjusted_mode.vdisplay;
+	min_scale = FRAC_16_16(1, 8);
+	max_scale = FRAC_16_16(8, 1);
+
+	ret = drm_plane_helper_check_state(state, &clip, min_scale,
+					   max_scale, true, true);
+	if (ret)
+		return ret;
+
 	if (plane_enabled(state)) {
 		unsigned int rotation;
 		const struct mdp_format *format;
@@ -368,10 +391,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
 
 		ret = mdp5_plane_mode_set(plane,
 				state->crtc, state->fb,
-				state->crtc_x, state->crtc_y,
-				state->crtc_w, state->crtc_h,
-				state->src_x,  state->src_y,
-				state->src_w, state->src_h);
+				&state->src, &state->dst);
 		/* atomic_check should have ensured that this doesn't fail */
 		WARN_ON(ret < 0);
 	}
@@ -664,10 +684,7 @@ static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
 
 static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
-		int crtc_x, int crtc_y,
-		unsigned int crtc_w, unsigned int crtc_h,
-		uint32_t src_x, uint32_t src_y,
-		uint32_t src_w, uint32_t src_h)
+		struct drm_rect *src, struct drm_rect *dest)
 {
 	struct drm_plane_state *pstate = plane->state;
 	struct mdp5_hw_pipe *hwpipe = to_mdp5_plane_state(pstate)->hwpipe;
@@ -683,6 +700,10 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	uint32_t pix_format;
 	unsigned int rotation;
 	bool vflip, hflip;
+	int crtc_x, crtc_y;
+	unsigned int crtc_w, crtc_h;
+	uint32_t src_x, src_y;
+	uint32_t src_w, src_h;
 	unsigned long flags;
 	int ret;
 
@@ -695,6 +716,16 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	format = to_mdp_format(msm_framebuffer_format(fb));
 	pix_format = format->base.pixel_format;
 
+	src_x = src->x1;
+	src_y = src->y1;
+	src_w = drm_rect_width(src);
+	src_h = drm_rect_height(src);
+
+	crtc_x = dest->x1;
+	crtc_y = dest->y1;
+	crtc_w = drm_rect_width(dest);
+	crtc_h = drm_rect_height(dest);
+
 	/* src values are in Q16 fixed point, convert to integer: */
 	src_x = src_x >> 16;
 	src_y = src_y >> 16;
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 30b5d23e53b4..6924fa28f04f 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -151,20 +151,29 @@ static void commit_worker(struct work_struct *work)
 	complete_commit(container_of(work, struct msm_commit, work), true);
 }
 
+/*
+ * this func is identical to the drm_atomic_helper_check, but we keep this
+ * because we might eventually need to have a more finegrained check
+ * sequence without using the atomic helpers.
+ *
+ * In the past, we first called drm_atomic_helper_check_planes, and then
+ * drm_atomic_helper_check_modeset. We needed this because the MDP5 plane's
+ * ->atomic_check could update ->mode_changed for pixel format changes.
+ * This, however isn't needed now because if there is a pixel format change,
+ * we just assign a new hwpipe for it with a new SMP allocation. We might
+ * eventually hit a condition where we would need to do a full modeset if
+ * we run out of planes. There, we'd probably need to set mode_changed.
+ */
 int msm_atomic_check(struct drm_device *dev,
 		     struct drm_atomic_state *state)
 {
 	int ret;
 
-	/*
-	 * msm ->atomic_check can update ->mode_changed for pixel format
-	 * changes, hence must be run before we check the modeset changes.
-	 */
-	ret = drm_atomic_helper_check_planes(dev, state);
+	ret = drm_atomic_helper_check_modeset(dev, state);
 	if (ret)
 		return ret;
 
-	ret = drm_atomic_helper_check_modeset(dev, state);
+	ret = drm_atomic_helper_check_planes(dev, state);
 	if (ret)
 		return ret;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 4/8] drm/msm/mdp5: Configure COLOR3_OUT propagation
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
                     ` (2 preceding siblings ...)
  2017-01-17  4:45   ` [PATCH v2 3/8] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 5/8] drm/msm/mdp5: Misc cursor plane bits Archit Taneja
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

In MDP5 Layer Mixer HW, the blender output is only the blended color
components (i.e R, G and B, or COLOR0/1/2 in MDP5 HW terminology). This
is fed to the BG input of the next blender. We also need to provide an
alpha (COLOR3) value for the BG input at the next stage.

This is configured via using the REG_MDP5_LM_BLEND_COLOR_OUT register.
For each stage, we can propagate either the BG or FG alpha to the next
stage.

The approach taken by the driver is to propagate FG alpha, if the plane
staged on that blender has an alpha. If it doesn't, we try to propagate
the base layer's alpha.

This is borrowed from downstream MDP5 kernel driver. Without this, we
don't see any cursor plane content.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 7a47209b0c6f..fec966293f9a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -177,6 +177,21 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc)
 	kfree(mdp5_crtc);
 }
 
+static inline u32 mdp5_lm_use_fg_alpha_mask(enum mdp_mixer_stage_id stage)
+{
+	switch (stage) {
+	case STAGE0: return MDP5_LM_BLEND_COLOR_OUT_STAGE0_FG_ALPHA;
+	case STAGE1: return MDP5_LM_BLEND_COLOR_OUT_STAGE1_FG_ALPHA;
+	case STAGE2: return MDP5_LM_BLEND_COLOR_OUT_STAGE2_FG_ALPHA;
+	case STAGE3: return MDP5_LM_BLEND_COLOR_OUT_STAGE3_FG_ALPHA;
+	case STAGE4: return MDP5_LM_BLEND_COLOR_OUT_STAGE4_FG_ALPHA;
+	case STAGE5: return MDP5_LM_BLEND_COLOR_OUT_STAGE5_FG_ALPHA;
+	case STAGE6: return MDP5_LM_BLEND_COLOR_OUT_STAGE6_FG_ALPHA;
+	default:
+		return 0;
+	}
+}
+
 /*
  * blend_setup() - blend all the planes of a CRTC
  *
@@ -197,6 +212,8 @@ static void blend_setup(struct drm_crtc *crtc)
 	unsigned long flags;
 	enum mdp5_pipe stage[STAGE_MAX + 1] = { SSPP_NONE };
 	int i, plane_cnt = 0;
+	bool bg_alpha_enabled = false;
+	u32 mixer_op_mode = 0;
 #define blender(stage)	((stage) - STAGE0)
 
 	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
@@ -218,6 +235,11 @@ static void blend_setup(struct drm_crtc *crtc)
 	if (!pstates[STAGE_BASE]) {
 		ctl_blend_flags |= MDP5_CTL_BLEND_OP_FLAG_BORDER_OUT;
 		DBG("Border Color is enabled");
+	} else if (plane_cnt) {
+		format = to_mdp_format(msm_framebuffer_format(pstates[STAGE_BASE]->base.fb));
+
+		if (format->alpha_enable)
+			bg_alpha_enabled = true;
 	}
 
 	/* The reset for blending */
@@ -232,6 +254,12 @@ static void blend_setup(struct drm_crtc *crtc)
 			MDP5_LM_BLEND_OP_MODE_BG_ALPHA(BG_CONST);
 		fg_alpha = pstates[i]->alpha;
 		bg_alpha = 0xFF - pstates[i]->alpha;
+
+		if (!format->alpha_enable && bg_alpha_enabled)
+			mixer_op_mode = 0;
+		else
+			mixer_op_mode |= mdp5_lm_use_fg_alpha_mask(i);
+
 		DBG("Stage %d fg_alpha %x bg_alpha %x", i, fg_alpha, bg_alpha);
 
 		if (format->alpha_enable && pstates[i]->premultiplied) {
@@ -268,6 +296,8 @@ static void blend_setup(struct drm_crtc *crtc)
 				blender(i)), bg_alpha);
 	}
 
+	mdp5_write(mdp5_kms, REG_MDP5_LM_BLEND_COLOR_OUT(lm), mixer_op_mode);
+
 	mdp5_ctl_blend(mdp5_crtc->ctl, stage, plane_cnt, ctl_blend_flags);
 
 out:
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 5/8] drm/msm/mdp5: Misc cursor plane bits
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
                     ` (3 preceding siblings ...)
  2017-01-17  4:45   ` [PATCH v2 4/8] drm/msm/mdp5: Configure COLOR3_OUT propagation Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 6/8] drm/msm/mdp5: Add cursor planes Archit Taneja
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

These are various changes added in preparation for cursor planes:

- Add a pipe_cursor block for 8x96 in mdp5_cfg.
- Add a new pipe CAP called MDP_PIPE_CAP_CURSOR. Use this to ensure we
  assign a cursor SSPP for a drm_plane with type DRM_PLANE_TYPE_CURSOR.
- Update mdp5_ctl_blend_mask/ext_blend_mask funcs to incorporate cursor
  SSPPs.
- In mdp5_ctl_blend, iterate through MAX_STAGES instead of stage_cnt,
  we need to do this because we can now have empty stages in between.
- In mdp5_crtc_atomic_check, make sure that the cursor plane has the
  highest zorder, and stage the cursor plane to the maximum stage #
  present on the HW.
- Create drm_crtc_funcs that doesn't try to implement cursors using the
  older LM cursor HW.
- Pass drm_plane_type in mdp5_plane_init instead of a bool telling
  whether plane is primary or not.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c   | 10 +++++++++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  | 34 +++++++++++++++++++++++++++----
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c   | 10 +++++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c   | 10 +++++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |  7 +++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c  |  8 ++++++++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c |  8 +++++---
 drivers/gpu/drm/msm/mdp/mdp_kms.h         |  1 +
 8 files changed, 75 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
index 618b2ffed9b4..34ab553f6897 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c
@@ -421,6 +421,16 @@ const struct mdp5_cfg_hw msm8x96_config = {
 			MDP_PIPE_CAP_SW_PIX_EXT	|
 			0,
 	},
+	.pipe_cursor = {
+		.count = 2,
+		.base = { 0x34000, 0x36000 },
+		.caps = MDP_PIPE_CAP_HFLIP	|
+			MDP_PIPE_CAP_VFLIP	|
+			MDP_PIPE_CAP_SW_PIX_EXT	|
+			MDP_PIPE_CAP_CURSOR	|
+			0,
+	},
+
 	.lm = {
 		.count = 6,
 		.base = { 0x44000, 0x45000, 0x46000, 0x47000, 0x48000, 0x49000 },
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index fec966293f9a..84fcb6e3a176 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -400,6 +400,7 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 	struct plane_state pstates[STAGE_MAX + 1];
 	const struct mdp5_cfg_hw *hw_cfg;
 	const struct drm_plane_state *pstate;
+	bool cursor_plane = false;
 	int cnt = 0, base = 0, i;
 
 	DBG("%s: check", crtc->name);
@@ -409,6 +410,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 		pstates[cnt].state = to_mdp5_plane_state(pstate);
 
 		cnt++;
+
+		if (plane->type == DRM_PLANE_TYPE_CURSOR)
+			cursor_plane = true;
 	}
 
 	/* assign a stage based on sorted zpos property */
@@ -420,6 +424,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 	if ((cnt > 0) && !is_fullscreen(state, &pstates[0].state->base))
 		base++;
 
+	/* trigger a warning if cursor isn't the highest zorder */
+	WARN_ON(cursor_plane &&
+		(pstates[cnt - 1].plane->type != DRM_PLANE_TYPE_CURSOR));
+
 	/* verify that there are not too many planes attached to crtc
 	 * and that we don't have conflicting mixer stages:
 	 */
@@ -431,7 +439,10 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc,
 	}
 
 	for (i = 0; i < cnt; i++) {
-		pstates[i].state->stage = STAGE_BASE + i + base;
+		if (cursor_plane && (i == (cnt - 1)))
+			pstates[i].state->stage = hw_cfg->lm.nb_stages;
+		else
+			pstates[i].state->stage = STAGE_BASE + i + base;
 		DBG("%s: assign pipe %s on stage=%d", crtc->name,
 				pstates[i].plane->name,
 				pstates[i].state->stage);
@@ -642,6 +653,16 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
 	.cursor_move = mdp5_crtc_cursor_move,
 };
 
+static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
+	.set_config = drm_atomic_helper_set_config,
+	.destroy = mdp5_crtc_destroy,
+	.page_flip = drm_atomic_helper_page_flip,
+	.set_property = drm_atomic_helper_crtc_set_property,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+};
+
 static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
 	.mode_set_nofb = mdp5_crtc_mode_set_nofb,
 	.disable = mdp5_crtc_disable,
@@ -775,7 +796,8 @@ void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
 
 /* initialize crtc */
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
-		struct drm_plane *plane, int id)
+				struct drm_plane *plane,
+				struct drm_plane *cursor_plane, int id)
 {
 	struct drm_crtc *crtc = NULL;
 	struct mdp5_crtc *mdp5_crtc;
@@ -796,8 +818,12 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 	mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
 	mdp5_crtc->err.irq = mdp5_crtc_err_irq;
 
-	drm_crtc_init_with_planes(dev, crtc, plane, NULL, &mdp5_crtc_funcs,
-				  NULL);
+	if (cursor_plane)
+		drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
+					  &mdp5_crtc_no_lm_cursor_funcs, NULL);
+	else
+		drm_crtc_init_with_planes(dev, crtc, plane, NULL,
+					  &mdp5_crtc_funcs, NULL);
 
 	drm_flip_work_init(&mdp5_crtc->unref_cursor_work,
 			"unref cursor", unref_cursor_worker);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index ab339ce7425a..8b93f7e13200 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -326,6 +326,8 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
 	case SSPP_DMA1: return MDP5_CTL_LAYER_REG_DMA1(stage);
 	case SSPP_VIG3: return MDP5_CTL_LAYER_REG_VIG3(stage);
 	case SSPP_RGB3: return MDP5_CTL_LAYER_REG_RGB3(stage);
+	case SSPP_CURSOR0:
+	case SSPP_CURSOR1:
 	default:	return 0;
 	}
 }
@@ -333,7 +335,7 @@ static u32 mdp_ctl_blend_mask(enum mdp5_pipe pipe,
 static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
 		enum mdp_mixer_stage_id stage)
 {
-	if (stage < STAGE6)
+	if (stage < STAGE6 && (pipe != SSPP_CURSOR0 && pipe != SSPP_CURSOR1))
 		return 0;
 
 	switch (pipe) {
@@ -347,6 +349,8 @@ static u32 mdp_ctl_blend_ext_mask(enum mdp5_pipe pipe,
 	case SSPP_DMA1: return MDP5_CTL_LAYER_EXT_REG_DMA1_BIT3;
 	case SSPP_VIG3: return MDP5_CTL_LAYER_EXT_REG_VIG3_BIT3;
 	case SSPP_RGB3: return MDP5_CTL_LAYER_EXT_REG_RGB3_BIT3;
+	case SSPP_CURSOR0: return MDP5_CTL_LAYER_EXT_REG_CURSOR0(stage);
+	case SSPP_CURSOR1: return MDP5_CTL_LAYER_EXT_REG_CURSOR1(stage);
 	default:	return 0;
 	}
 }
@@ -365,7 +369,7 @@ int mdp5_ctl_blend(struct mdp5_ctl *ctl, enum mdp5_pipe *stage, u32 stage_cnt,
 		start_stage = STAGE_BASE;
 	}
 
-	for (i = start_stage; i < start_stage + stage_cnt; i++) {
+	for (i = start_stage; stage_cnt && i <= STAGE_MAX; i++) {
 		blend_cfg |= mdp_ctl_blend_mask(stage[i], i);
 		blend_ext_cfg |= mdp_ctl_blend_ext_mask(stage[i], i);
 	}
@@ -422,6 +426,8 @@ u32 mdp_ctl_flush_mask_pipe(enum mdp5_pipe pipe)
 	case SSPP_DMA1: return MDP5_CTL_FLUSH_DMA1;
 	case SSPP_VIG3: return MDP5_CTL_FLUSH_VIG3;
 	case SSPP_RGB3: return MDP5_CTL_FLUSH_RGB3;
+	case SSPP_CURSOR0: return MDP5_CTL_FLUSH_CURSOR_0;
+	case SSPP_CURSOR1: return MDP5_CTL_FLUSH_CURSOR_1;
 	default:        return 0;
 	}
 }
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index ecfa38949aea..70a1950de8ae 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -441,8 +441,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		bool primary = i < num_crtcs;
 		struct drm_plane *plane;
 		struct drm_crtc *crtc;
+		enum drm_plane_type type;
 
-		plane = mdp5_plane_init(dev, primary);
+		if (primary)
+			type = DRM_PLANE_TYPE_PRIMARY;
+		else
+			type = DRM_PLANE_TYPE_OVERLAY;
+
+		plane = mdp5_plane_init(dev, type);
 		if (IS_ERR(plane)) {
 			ret = PTR_ERR(plane);
 			dev_err(dev->dev, "failed to construct plane %d (%d)\n", i, ret);
@@ -453,7 +459,7 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		if (!primary)
 			continue;
 
-		crtc  = mdp5_crtc_init(dev, plane, i);
+		crtc  = mdp5_crtc_init(dev, plane, NULL, i);
 		if (IS_ERR(crtc)) {
 			ret = PTR_ERR(crtc);
 			dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 40ebc5c50875..0396e8adb693 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -167,6 +167,7 @@ static inline const char *pipe2name(enum mdp5_pipe pipe)
 		NAME(RGB0), NAME(RGB1), NAME(RGB2),
 		NAME(DMA0), NAME(DMA1),
 		NAME(VIG3), NAME(RGB3),
+		NAME(CURSOR0), NAME(CURSOR1),
 #undef NAME
 	};
 	return names[pipe];
@@ -242,7 +243,8 @@ void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
 
 uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
-struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary);
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+				  enum drm_plane_type type);
 
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
@@ -251,7 +253,8 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
 		struct mdp5_interface *intf, struct mdp5_ctl *ctl);
 void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
 struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
-		struct drm_plane *plane, int id);
+				struct drm_plane *plane,
+				struct drm_plane *cursor_plane, int id);
 
 struct drm_encoder *mdp5_encoder_init(struct drm_device *dev,
 		struct mdp5_interface *intf, struct mdp5_ctl *ctl);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
index 1ae9dc8d260d..35c4dabb0c0c 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c
@@ -53,6 +53,14 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s,
 		if (caps & ~cur->caps)
 			continue;
 
+		/*
+		 * don't assign a cursor pipe to a plane that isn't going to
+		 * be used as a cursor
+		 */
+		if (cur->caps & MDP_PIPE_CAP_CURSOR &&
+				plane->type != DRM_PLANE_TYPE_CURSOR)
+			continue;
+
 		/* possible candidate, take the one with the
 		 * fewest unneeded caps bits set:
 		 */
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 939991d5f346..7409e959d810 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -344,6 +344,9 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		if (rotation & DRM_REFLECT_Y)
 			caps |= MDP_PIPE_CAP_VFLIP;
 
+		if (plane->type == DRM_PLANE_TYPE_CURSOR)
+			caps |= MDP_PIPE_CAP_CURSOR;
+
 		/* (re)allocate hw pipe if we don't have one or caps-mismatch: */
 		if (!mdp5_state->hwpipe || (caps & ~mdp5_state->hwpipe->caps))
 			new_hwpipe = true;
@@ -870,12 +873,12 @@ uint32_t mdp5_plane_get_flush(struct drm_plane *plane)
 }
 
 /* initialize plane */
-struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
+struct drm_plane *mdp5_plane_init(struct drm_device *dev,
+				  enum drm_plane_type type)
 {
 	struct drm_plane *plane = NULL;
 	struct mdp5_plane *mdp5_plane;
 	int ret;
-	enum drm_plane_type type;
 
 	mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
 	if (!mdp5_plane) {
@@ -888,7 +891,6 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, bool primary)
 	mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
 		ARRAY_SIZE(mdp5_plane->formats), false);
 
-	type = primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
 				 mdp5_plane->formats, mdp5_plane->nformats,
 				 type, NULL);
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 303130320748..7574cdfef418 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -112,6 +112,7 @@ const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
 #define MDP_PIPE_CAP_CSC			BIT(3)
 #define MDP_PIPE_CAP_DECIMATION			BIT(4)
 #define MDP_PIPE_CAP_SW_PIX_EXT			BIT(5)
+#define MDP_PIPE_CAP_CURSOR			BIT(6)
 
 static inline bool pipe_supports_yuv(uint32_t pipe_caps)
 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 6/8] drm/msm/mdp5: Add cursor planes
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
                     ` (4 preceding siblings ...)
  2017-01-17  4:45   ` [PATCH v2 5/8] drm/msm/mdp5: Misc cursor plane bits Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 7/8] drm/msm/mdp5: Refactor mdp5_plane_atomic_check Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 8/8] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

Register cursor drm_planes. The loop in modeset_init that inits the
planes and crtcs has to be refactored a bit. We first iterate all the
hwpipes to find the cursor planes. Then, we loop again to create
crtcs.

In msm_atomic_wait_for_commit_done, remove the check which bypasses
waiting for vsyncs if state->legacy_cursor_updates is true.

We will later create a fast path for cursor position changes in the
cursor plane's update_plane func that doesn't go via the regular
atomic commit path. For rest of cursor related updates, we will have
to wait for vsyncs, so ignore the legacy_cursor_updates flag.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | 33 ++++++++++++++++++++++++++-------
 drivers/gpu/drm/msm/msm_atomic.c        |  5 -----
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 70a1950de8ae..3eb0749223d9 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -411,7 +411,9 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	struct msm_drm_private *priv = dev->dev_private;
 	const struct mdp5_cfg_hw *hw_cfg;
 	unsigned int num_crtcs;
-	int i, ret;
+	int i, ret, pi = 0, ci = 0;
+	struct drm_plane *primary[MAX_BASES] = { NULL };
+	struct drm_plane *cursor[MAX_BASES] = { NULL };
 
 	hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg);
 
@@ -438,13 +440,14 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 	 * planes for the CRTCs, with the remainder as overlay planes:
 	 */
 	for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
-		bool primary = i < num_crtcs;
+		struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
 		struct drm_plane *plane;
-		struct drm_crtc *crtc;
 		enum drm_plane_type type;
 
-		if (primary)
+		if (i < num_crtcs)
 			type = DRM_PLANE_TYPE_PRIMARY;
+		else if (hwpipe->caps & MDP_PIPE_CAP_CURSOR)
+			type = DRM_PLANE_TYPE_CURSOR;
 		else
 			type = DRM_PLANE_TYPE_OVERLAY;
 
@@ -456,10 +459,16 @@ static int modeset_init(struct mdp5_kms *mdp5_kms)
 		}
 		priv->planes[priv->num_planes++] = plane;
 
-		if (!primary)
-			continue;
+		if (type == DRM_PLANE_TYPE_PRIMARY)
+			primary[pi++] = plane;
+		if (type == DRM_PLANE_TYPE_CURSOR)
+			cursor[ci++] = plane;
+	}
+
+	for (i = 0; i < num_crtcs; i++) {
+		struct drm_crtc *crtc;
 
-		crtc  = mdp5_crtc_init(dev, plane, NULL, i);
+		crtc  = mdp5_crtc_init(dev, primary[i], cursor[i], i);
 		if (IS_ERR(crtc)) {
 			ret = PTR_ERR(crtc);
 			dev_err(dev->dev, "failed to construct crtc %d (%d)\n", i, ret);
@@ -791,6 +800,9 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)
 	static const enum mdp5_pipe dma_planes[] = {
 			SSPP_DMA0, SSPP_DMA1,
 	};
+	static const enum mdp5_pipe cursor_planes[] = {
+			SSPP_CURSOR0, SSPP_CURSOR1,
+	};
 	const struct mdp5_cfg_hw *hw_cfg;
 	int ret;
 
@@ -814,6 +826,13 @@ static int hwpipe_init(struct mdp5_kms *mdp5_kms)
 	if (ret)
 		return ret;
 
+	/* Construct cursor pipes: */
+	ret = construct_pipes(mdp5_kms, hw_cfg->pipe_cursor.count,
+			cursor_planes, hw_cfg->pipe_cursor.base,
+			hw_cfg->pipe_cursor.caps);
+	if (ret)
+		return ret;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 6924fa28f04f..9633a68b14d7 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -93,11 +93,6 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
 		if (!crtc->state->enable)
 			continue;
 
-		/* Legacy cursor ioctls are completely unsynced, and userspace
-		 * relies on that (by doing tons of cursor updates). */
-		if (old_state->legacy_cursor_update)
-			continue;
-
 		kms->funcs->wait_for_crtc_commit_done(kms, crtc);
 	}
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 7/8] drm/msm/mdp5: Refactor mdp5_plane_atomic_check
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
                     ` (5 preceding siblings ...)
  2017-01-17  4:45   ` [PATCH v2 6/8] drm/msm/mdp5: Add cursor planes Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  2017-01-17  4:45   ` [PATCH v2 8/8] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

In mdp5_plane_atomic_check, we get crtc_state from drm_plane_state.

Later, for cursor planes, we'll populate the update_plane() func that
takes a fast asynchronous path to implement cursor movements. There, we
would need to call a similar atomic_check func to validate the plane
state, but crtc_state would need to be derived differently.

Refactor mdp5_plane_atomic_check to mdp5_plane_atomic_check_with_state
such that the latter takes crtc_state as an argument.

This is similar to what the intel driver has done for async cursor
updates.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 32 +++++++++++++++++++------------
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 7409e959d810..504201b710d9 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -270,17 +270,16 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
 }
 
 #define FRAC_16_16(mult, div)    (((mult) << 16) / (div))
-static int mdp5_plane_atomic_check(struct drm_plane *plane,
-		struct drm_plane_state *state)
+static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
+					      struct drm_plane_state *state)
 {
 	struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state);
+	struct drm_plane *plane = state->plane;
 	struct drm_plane_state *old_state = plane->state;
 	struct mdp5_cfg *config = mdp5_cfg_get_config(get_kms(plane)->cfg);
 	bool new_hwpipe = false;
 	uint32_t max_width, max_height;
 	uint32_t caps = 0;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
 	struct drm_rect clip;
 	int min_scale, max_scale;
 	int ret;
@@ -288,10 +287,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 	DBG("%s: check (%d -> %d)", plane->name,
 			plane_enabled(old_state), plane_enabled(state));
 
-	crtc = state->crtc ? state->crtc : plane->state->crtc;
-	if (!crtc)
-		return 0;
-
 	max_width = config->hw->lm.max_width << 16;
 	max_height = config->hw->lm.max_height << 16;
 
@@ -303,10 +298,6 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 		return -ERANGE;
 	}
 
-	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
-	if (WARN_ON(!crtc_state))
-		return -EINVAL;
-
 	clip.x1 = 0;
 	clip.y1 = 0;
 	clip.x2 = crtc_state->adjusted_mode.hdisplay;
@@ -382,6 +373,23 @@ static int mdp5_plane_atomic_check(struct drm_plane *plane,
 	return 0;
 }
 
+static int mdp5_plane_atomic_check(struct drm_plane *plane,
+				   struct drm_plane_state *state)
+{
+	struct drm_crtc *crtc;
+	struct drm_crtc_state *crtc_state;
+
+	crtc = state->crtc ? state->crtc : plane->state->crtc;
+	if (!crtc)
+		return 0;
+
+	crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc);
+	if (WARN_ON(!crtc_state))
+		return -EINVAL;
+
+	return mdp5_plane_atomic_check_with_state(crtc_state, state);
+}
+
 static void mdp5_plane_atomic_update(struct drm_plane *plane,
 				     struct drm_plane_state *old_state)
 {
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

* [PATCH v2 8/8] HACK: drm/msm/mdp5: Add support for legacy cursor updates
  2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
                     ` (6 preceding siblings ...)
  2017-01-17  4:45   ` [PATCH v2 7/8] drm/msm/mdp5: Refactor mdp5_plane_atomic_check Archit Taneja
@ 2017-01-17  4:45   ` Archit Taneja
  7 siblings, 0 replies; 26+ messages in thread
From: Archit Taneja @ 2017-01-17  4:45 UTC (permalink / raw)
  To: robdclark; +Cc: linux-arm-msm, dri-devel

This code has been more or less picked up from the vc4 and intel
implementations of update_plane() funcs for cursor planes.

The update_plane() func is usually the drm_atomic_helper_update_plane
func that will issue an atomic commit with the plane updates. Such
commits are not intended to be done faster than the vsync rate.

The legacy cursor userspace API, on the other hand, expects the kernel
to handle cursor updates immediately.

Create a fast path in update_plane, which updates the cursor registers
and flushes the configuration. The fast path is taken when there is only
a change in the cursor's position in the crtc, or a change in the
cursor's crop co-ordinates. For anything else, we go via the slow path.

We take the slow path even when the fb changes, and when there is
currently no fb tied to the plane. This should hopefully ensure that we
always take a slow path for every new fb. This in turn should ensure that
the fb is pinned/prepared.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c  |   7 ++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |   1 +
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 110 +++++++++++++++++++++++++++++-
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index 84fcb6e3a176..d0c8b38b96ce 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -778,6 +778,13 @@ void mdp5_crtc_set_pipeline(struct drm_crtc *crtc,
 	mdp5_ctl_set_pipeline(ctl, intf, lm);
 }
 
+struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
+{
+	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+	return mdp5_crtc->ctl;
+}
+
 int mdp5_crtc_get_lm(struct drm_crtc *crtc)
 {
 	struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 0396e8adb693..9de471191eba 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -246,6 +246,7 @@ enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
 struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 				  enum drm_plane_type type);
 
+struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
 uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc);
 
 int mdp5_crtc_get_lm(struct drm_crtc *crtc);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 504201b710d9..0ffb8affef35 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -31,6 +31,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		struct drm_rect *src, struct drm_rect *dest);
 
+static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
+		struct drm_crtc *crtc,
+		struct drm_framebuffer *fb,
+		int crtc_x, int crtc_y,
+		unsigned int crtc_w, unsigned int crtc_h,
+		uint32_t src_x, uint32_t src_y,
+		uint32_t src_w, uint32_t src_h);
+
 static void set_scanout_locked(struct drm_plane *plane,
 		struct drm_framebuffer *fb);
 
@@ -243,6 +251,19 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
 		.atomic_print_state = mdp5_plane_atomic_print_state,
 };
 
+static const struct drm_plane_funcs mdp5_cursor_plane_funcs = {
+		.update_plane = mdp5_update_cursor_plane_legacy,
+		.disable_plane = drm_atomic_helper_disable_plane,
+		.destroy = mdp5_plane_destroy,
+		.set_property = drm_atomic_helper_plane_set_property,
+		.atomic_set_property = mdp5_plane_atomic_set_property,
+		.atomic_get_property = mdp5_plane_atomic_get_property,
+		.reset = mdp5_plane_reset,
+		.atomic_duplicate_state = mdp5_plane_duplicate_state,
+		.atomic_destroy_state = mdp5_plane_destroy_state,
+		.atomic_print_state = mdp5_plane_atomic_print_state,
+};
+
 static int mdp5_plane_prepare_fb(struct drm_plane *plane,
 				 struct drm_plane_state *new_state)
 {
@@ -860,6 +881,82 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	return ret;
 }
 
+static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
+			struct drm_crtc *crtc, struct drm_framebuffer *fb,
+			int crtc_x, int crtc_y,
+			unsigned int crtc_w, unsigned int crtc_h,
+			uint32_t src_x, uint32_t src_y,
+			uint32_t src_w, uint32_t src_h)
+{
+	struct drm_plane_state *plane_state, *new_plane_state;
+	struct mdp5_plane_state *mdp5_pstate;
+	struct drm_crtc_state *crtc_state = crtc->state;
+	int ret;
+
+	if (!crtc_state->active || drm_atomic_crtc_needs_modeset(crtc_state))
+		goto slow;
+
+	plane_state = plane->state;
+	mdp5_pstate = to_mdp5_plane_state(plane_state);
+
+	/* don't use fast path if we don't have a hwpipe allocated yet */
+	if (!mdp5_pstate->hwpipe)
+		goto slow;
+
+	/* only allow changing of position(crtc x/y or src x/y) in fast path */
+	if (plane_state->crtc != crtc ||
+	    plane_state->src_w != src_w ||
+	    plane_state->src_h != src_h ||
+	    plane_state->crtc_w != crtc_w ||
+	    plane_state->crtc_h != crtc_h ||
+	    !plane_state->fb ||
+	    plane_state->fb != fb)
+		goto slow;
+
+	new_plane_state = mdp5_plane_duplicate_state(plane);
+	if (!new_plane_state)
+		return -ENOMEM;
+
+	new_plane_state->src_x = src_x;
+	new_plane_state->src_y = src_y;
+	new_plane_state->src_w = src_w;
+	new_plane_state->src_h = src_h;
+	new_plane_state->crtc_x = crtc_x;
+	new_plane_state->crtc_y = crtc_y;
+	new_plane_state->crtc_w = crtc_w;
+	new_plane_state->crtc_h = crtc_h;
+
+	ret = mdp5_plane_atomic_check_with_state(crtc_state, new_plane_state);
+	if (ret)
+		goto slow_free;
+
+	if (new_plane_state->visible) {
+		struct mdp5_ctl *ctl;
+
+		ret = mdp5_plane_mode_set(plane, crtc, fb,
+					  &new_plane_state->src,
+					  &new_plane_state->dst);
+		WARN_ON(ret < 0);
+
+		ctl = mdp5_crtc_get_ctl(crtc);
+
+		mdp5_ctl_commit(ctl, mdp5_plane_get_flush(plane));
+	}
+
+	*to_mdp5_plane_state(plane_state) =
+		*to_mdp5_plane_state(new_plane_state);
+
+	mdp5_plane_destroy_state(plane, new_plane_state);
+
+	return 0;
+slow_free:
+	mdp5_plane_destroy_state(plane, new_plane_state);
+slow:
+	return drm_atomic_helper_update_plane(plane, crtc, fb,
+					      crtc_x, crtc_y, crtc_w, crtc_h,
+					      src_x, src_y, src_w, src_h);
+}
+
 enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
 {
 	struct mdp5_plane_state *pstate = to_mdp5_plane_state(plane->state);
@@ -899,9 +996,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
 	mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
 		ARRAY_SIZE(mdp5_plane->formats), false);
 
-	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs,
-				 mdp5_plane->formats, mdp5_plane->nformats,
-				 type, NULL);
+	if (type == DRM_PLANE_TYPE_CURSOR)
+		ret = drm_universal_plane_init(dev, plane, 0xff,
+				&mdp5_cursor_plane_funcs,
+				mdp5_plane->formats, mdp5_plane->nformats,
+				type, NULL);
+	else
+		ret = drm_universal_plane_init(dev, plane, 0xff,
+				&mdp5_plane_funcs,
+				mdp5_plane->formats, mdp5_plane->nformats,
+				type, NULL);
 	if (ret)
 		goto fail;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

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

end of thread, other threads:[~2017-01-17  4:45 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-19 12:08 [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Archit Taneja
2016-12-19 12:08 ` [PATCH 1/9] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
2016-12-19 12:08 ` [PATCH 2/9] drm/msm/mdp5: Update generated headers Archit Taneja
2016-12-19 12:08 ` [PATCH 3/9] drm/msm/mdp5: Prepare CRTC/LM for empty stages Archit Taneja
2016-12-19 12:08 ` [PATCH 4/9] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles Archit Taneja
2016-12-19 12:08 ` [PATCH 5/9] drm/msm/mdp5: Configure COLOR3_OUT propagation Archit Taneja
2016-12-19 12:08 ` [PATCH 6/9] drm/msm/mdp5: Misc cursor plane bits Archit Taneja
2016-12-19 12:08 ` [PATCH 7/9] drm/msm/mdp5: Refactor mdp5_plane_atomic_check Archit Taneja
2016-12-19 12:08 ` [RFC 8/9] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja
2016-12-19 12:50   ` Maarten Lankhorst
2016-12-20  6:23     ` Archit Taneja
2016-12-20 13:40       ` Maarten Lankhorst
2016-12-21  5:23         ` Archit Taneja
2016-12-19 16:00   ` Daniel Vetter
2016-12-19 16:51     ` Daniel Vetter
2016-12-19 12:08 ` [PATCH 9/9] drm/msm/mdp5: Add cursor planes Archit Taneja
2016-12-19 15:50 ` [PATCH 0/9] drm/msm/mdp5: Cursor plane stuff Daniel Vetter
2017-01-17  4:45 ` [PATCH v2 0/8] " Archit Taneja
2017-01-17  4:45   ` [PATCH v2 1/8] drm/msm/mdp5: cfg: Add pipe_cursor block Archit Taneja
2017-01-17  4:45   ` [PATCH v2 2/8] drm/msm/mdp5: Prepare CRTC/LM for empty stages Archit Taneja
2017-01-17  4:45   ` [PATCH v2 3/8] drm/msm/mdp5: Use plane helpers to configure src/dst rectangles Archit Taneja
2017-01-17  4:45   ` [PATCH v2 4/8] drm/msm/mdp5: Configure COLOR3_OUT propagation Archit Taneja
2017-01-17  4:45   ` [PATCH v2 5/8] drm/msm/mdp5: Misc cursor plane bits Archit Taneja
2017-01-17  4:45   ` [PATCH v2 6/8] drm/msm/mdp5: Add cursor planes Archit Taneja
2017-01-17  4:45   ` [PATCH v2 7/8] drm/msm/mdp5: Refactor mdp5_plane_atomic_check Archit Taneja
2017-01-17  4:45   ` [PATCH v2 8/8] HACK: drm/msm/mdp5: Add support for legacy cursor updates Archit Taneja

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.