All of lore.kernel.org
 help / color / mirror / Atom feed
From: Russell King <rmk+kernel@armlinux.org.uk>
To: David Airlie <airlied@linux.ie>
Cc: dri-devel@lists.freedesktop.org
Subject: [PATCH 20/25] drm/armada: move overlay plane register update generation
Date: Fri, 08 Dec 2017 12:30:42 +0000	[thread overview]
Message-ID: <E1eNHne-00076m-2D@rmk-PC.armlinux.org.uk> (raw)
In-Reply-To: <20171208122754.GA20895@n2100.armlinux.org.uk>

Move the overlay plane register update generation to a separate function
as this is independent of the legacy or atomic update.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.h    |   2 +
 drivers/gpu/drm/armada/armada_overlay.c | 203 +++++++++++++++++---------------
 2 files changed, 112 insertions(+), 93 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index 0c7b519c09e8..445829b8877a 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -52,6 +52,8 @@ struct armada_plane_state {
 	u32 dst_hw;
 	u32 dst_yx;
 	u32 ctrl0;
+	bool changed;
+	bool vsync_update;
 };
 
 struct armada_plane {
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 00da2c58701c..e5fa346f572b 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -75,153 +75,172 @@ static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
 	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
 }
 
-static int
-armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
-	struct drm_framebuffer *fb,
-	int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
-	uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
-	struct drm_modeset_acquire_ctx *ctx)
+static void armada_ovl_plane_update_state(struct drm_plane_state *state,
+	struct armada_regs *regs)
 {
-	struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
-	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
-	struct armada_plane_work *work;
+	struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(state->plane);
+	struct armada_framebuffer *dfb = drm_fb_to_armada_fb(state->fb);
 	const struct drm_format_info *format;
-	struct drm_plane_state state = {
-		.plane = plane,
-		.crtc = crtc,
-		.fb = fb,
-		.src_x = src_x,
-		.src_y = src_y,
-		.src_w = src_w,
-		.src_h = src_h,
-		.crtc_x = crtc_x,
-		.crtc_y = crtc_y,
-		.crtc_w = crtc_w,
-		.crtc_h = crtc_h,
-		.rotation = DRM_MODE_ROTATE_0,
-	};
-	const struct drm_rect clip = {
-		.x2 = crtc->mode.hdisplay,
-		.y2 = crtc->mode.vdisplay,
-	};
-	uint32_t val, ctrl0;
-	unsigned idx = 0;
+	unsigned int idx = 0;
 	bool fb_changed;
-	int ret;
+	u32 val, ctrl0;
+	u16 src_x, src_y;
 
-	trace_armada_ovl_plane_update(plane, crtc, fb,
-				 crtc_x, crtc_y, crtc_w, crtc_h,
-				 src_x, src_y, src_w, src_h);
-
-	ret = drm_plane_helper_check_state(&state, &clip, 0, INT_MAX, true,
-					    false);
-	if (ret)
-		return ret;
-
-	work = &dplane->base.works[dplane->base.next_work];
-
-	ctrl0 = CFG_DMA_FMT(drm_fb_to_armada_fb(fb)->fmt) |
-		CFG_DMA_MOD(drm_fb_to_armada_fb(fb)->mod) |
-		CFG_CBSH_ENA;
-	if (state.visible)
+	ctrl0 = CFG_DMA_FMT(dfb->fmt) | CFG_DMA_MOD(dfb->mod) | CFG_CBSH_ENA;
+	if (state->visible)
 		ctrl0 |= CFG_DMA_ENA;
-	if (drm_rect_width(&state.src) >> 16 != drm_rect_width(&state.dst))
+	if (drm_rect_width(&state->src) >> 16 != drm_rect_width(&state->dst))
 		ctrl0 |= CFG_DMA_HSMOOTH;
 
 	/*
 	 * Shifting a YUV packed format image by one pixel causes the U/V
 	 * planes to swap.  Compensate for it by also toggling the UV swap.
 	 */
-	format = fb->format;
-	if (format->num_planes == 1 && state.src.x1 >> 16 & (format->hsub - 1))
+	format = dfb->fb.format;
+	if (format->num_planes == 1 && state->src.x1 >> 16 & (format->hsub - 1))
 		ctrl0 ^= CFG_DMA_MOD(CFG_SWAPUV);
 
 	if (~dplane->base.state.ctrl0 & ctrl0 & CFG_DMA_ENA) {
 		/* Power up the Y/U/V FIFOs on ENA 0->1 transitions */
-		armada_reg_queue_mod(work->regs, idx,
+		armada_reg_queue_mod(regs, idx,
 				     0, CFG_PDWN16x66 | CFG_PDWN32x66,
 				     LCD_SPU_SRAM_PARA1);
 	}
 
-	fb_changed = plane->fb != fb ||
-		     dplane->base.state.src_x != state.src.x1 >> 16 ||
-	             dplane->base.state.src_y != state.src.y1 >> 16;
+	fb_changed = dplane->base.base.fb != &dfb->fb ||
+		     dplane->base.state.src_x != state->src.x1 >> 16 ||
+	             dplane->base.state.src_y != state->src.y1 >> 16;
+
+	dplane->base.state.vsync_update = fb_changed;
 
 	/* FIXME: overlay on an interlaced display */
 	if (fb_changed) {
 		u32 addrs[3];
 
-		/*
-		 * Take a reference on the new framebuffer - we want to
-		 * hold on to it while the hardware is displaying it.
-		 */
-		drm_framebuffer_get(fb);
-
-		work->old_fb = plane->fb;
+		dplane->base.state.src_y = src_y = state->src.y1 >> 16;
+		dplane->base.state.src_x = src_x = state->src.x1 >> 16;
 
-		dplane->base.state.src_y = src_y = state.src.y1 >> 16;
-		dplane->base.state.src_x = src_x = state.src.x1 >> 16;
+		armada_drm_plane_calc_addrs(addrs, &dfb->fb, src_x, src_y);
 
-		armada_drm_plane_calc_addrs(addrs, fb, src_x, src_y);
-
-		armada_reg_queue_set(work->regs, idx, addrs[0],
+		armada_reg_queue_set(regs, idx, addrs[0],
 				     LCD_SPU_DMA_START_ADDR_Y0);
-		armada_reg_queue_set(work->regs, idx, addrs[1],
+		armada_reg_queue_set(regs, idx, addrs[1],
 				     LCD_SPU_DMA_START_ADDR_U0);
-		armada_reg_queue_set(work->regs, idx, addrs[2],
+		armada_reg_queue_set(regs, idx, addrs[2],
 				     LCD_SPU_DMA_START_ADDR_V0);
-		armada_reg_queue_set(work->regs, idx, addrs[0],
+		armada_reg_queue_set(regs, idx, addrs[0],
 				     LCD_SPU_DMA_START_ADDR_Y1);
-		armada_reg_queue_set(work->regs, idx, addrs[1],
+		armada_reg_queue_set(regs, idx, addrs[1],
 				     LCD_SPU_DMA_START_ADDR_U1);
-		armada_reg_queue_set(work->regs, idx, addrs[2],
+		armada_reg_queue_set(regs, idx, addrs[2],
 				     LCD_SPU_DMA_START_ADDR_V1);
 
-		val = fb->pitches[0] << 16 | fb->pitches[0];
-		armada_reg_queue_set(work->regs, idx, val,
+		val = dfb->fb.pitches[0] << 16 | dfb->fb.pitches[0];
+		armada_reg_queue_set(regs, idx, val,
 				     LCD_SPU_DMA_PITCH_YC);
-		val = fb->pitches[1] << 16 | fb->pitches[2];
-		armada_reg_queue_set(work->regs, idx, val,
+		val = dfb->fb.pitches[1] << 16 | dfb->fb.pitches[2];
+		armada_reg_queue_set(regs, idx, val,
 				     LCD_SPU_DMA_PITCH_UV);
-	} else {
-		work->old_fb = NULL;
 	}
 
-	val = (drm_rect_height(&state.src) & 0xffff0000) |
-	       drm_rect_width(&state.src) >> 16;
+	val = (drm_rect_height(&state->src) & 0xffff0000) |
+	       drm_rect_width(&state->src) >> 16;
 	if (dplane->base.state.src_hw != val) {
 		dplane->base.state.src_hw = val;
-		armada_reg_queue_set(work->regs, idx, val,
+		armada_reg_queue_set(regs, idx, val,
 				     LCD_SPU_DMA_HPXL_VLN);
 	}
 
-	val = drm_rect_height(&state.dst) << 16 | drm_rect_width(&state.dst);
+	val = drm_rect_height(&state->dst) << 16 | drm_rect_width(&state->dst);
 	if (dplane->base.state.dst_hw != val) {
 		dplane->base.state.dst_hw = val;
-		armada_reg_queue_set(work->regs, idx, val,
+		armada_reg_queue_set(regs, idx, val,
 				     LCD_SPU_DZM_HPXL_VLN);
 	}
 
-	val = state.dst.y1 << 16 | state.dst.x1;
+	val = state->dst.y1 << 16 | state->dst.x1;
 	if (dplane->base.state.dst_yx != val) {
 		dplane->base.state.dst_yx = val;
-		armada_reg_queue_set(work->regs, idx, val,
+		armada_reg_queue_set(regs, idx, val,
 				     LCD_SPU_DMA_OVSA_HPXL_VLN);
 	}
 
 	if (dplane->base.state.ctrl0 != ctrl0) {
 		dplane->base.state.ctrl0 = ctrl0;
-		armada_reg_queue_mod(work->regs, idx, ctrl0,
+		armada_reg_queue_mod(regs, idx, ctrl0,
 			CFG_CBSH_ENA | CFG_DMAFORMAT | CFG_DMA_FTOGGLE |
 			CFG_DMA_HSMOOTH | CFG_DMA_TSTMODE |
 			CFG_DMA_MOD(CFG_SWAPRB | CFG_SWAPUV | CFG_SWAPYU |
 			CFG_YUV2RGB) | CFG_DMA_ENA,
 			LCD_SPU_DMA_CTRL0);
+		dplane->base.state.vsync_update = true;
 	}
 
+	dplane->base.state.changed = idx != 0;
+
+	armada_reg_queue_end(regs, idx);
+}
+
+static int
+armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+	struct drm_framebuffer *fb,
+	int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
+	uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
+	struct drm_modeset_acquire_ctx *ctx)
+{
+	struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
+	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
+	struct armada_plane_work *work;
+	struct drm_plane_state state = {
+		.plane = plane,
+		.crtc = crtc,
+		.fb = fb,
+		.src_x = src_x,
+		.src_y = src_y,
+		.src_w = src_w,
+		.src_h = src_h,
+		.crtc_x = crtc_x,
+		.crtc_y = crtc_y,
+		.crtc_w = crtc_w,
+		.crtc_h = crtc_h,
+		.rotation = DRM_MODE_ROTATE_0,
+	};
+	const struct drm_rect clip = {
+		.x2 = crtc->mode.hdisplay,
+		.y2 = crtc->mode.vdisplay,
+	};
+	int ret;
+
+	trace_armada_ovl_plane_update(plane, crtc, fb,
+				 crtc_x, crtc_y, crtc_w, crtc_h,
+				 src_x, src_y, src_w, src_h);
+
+	ret = drm_plane_helper_check_state(&state, &clip, 0, INT_MAX, true,
+					    false);
+	if (ret)
+		return ret;
+
+	work = &dplane->base.works[dplane->base.next_work];
+
+	if (plane->fb != fb) {
+		/*
+		 * Take a reference on the new framebuffer - we want to
+		 * hold on to it while the hardware is displaying it.
+		 */
+		drm_framebuffer_reference(fb);
+
+		work->old_fb = plane->fb;
+	} else {
+		work->old_fb = NULL;
+	}
+
+	armada_ovl_plane_update_state(&state, work->regs);
+
+	if (!dplane->base.state.changed)
+		return 0;
+
 	/* Just updating the position/size? */
-	if (!fb_changed && dplane->base.state.ctrl0 == ctrl0) {
-		armada_reg_queue_end(work->regs, idx);
+	if (!dplane->base.state.vsync_update) {
 		armada_ovl_plane_work(dcrtc, work);
 		return 0;
 	}
@@ -235,15 +254,13 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 		armada_ovl_update_attr(&dplane->prop, dcrtc);
 	}
 
-	if (idx) {
-		armada_reg_queue_end(work->regs, idx);
-		/* Queue it for update on the next interrupt if we are enabled */
-		ret = armada_drm_plane_work_queue(dcrtc, work);
-		if (ret)
-			DRM_ERROR("failed to queue plane work: %d\n", ret);
+	/* Queue it for update on the next interrupt if we are enabled */
+	ret = armada_drm_plane_work_queue(dcrtc, work);
+	if (ret)
+		DRM_ERROR("failed to queue plane work: %d\n", ret);
+
+	dplane->base.next_work = !dplane->base.next_work;
 
-		dplane->base.next_work = !dplane->base.next_work;
-	}
 	return 0;
 }
 
-- 
2.7.4

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

  parent reply	other threads:[~2017-12-08 12:30 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-08 12:13 [PATCH v2 0/5] Armada DRM fixes Russell King - ARM Linux
2017-12-08 12:14 ` [PATCH 1/5] drm/armada: fix leak of crtc structure Russell King
2017-12-08 12:14 ` [PATCH 2/5] drm/armada: fix SRAM powerdown Russell King
2017-12-08 12:14 ` [PATCH 3/5] drm/armada: fix UV swap code Russell King
2017-12-08 12:14 ` [PATCH 4/5] drm/armada: improve efficiency of armada_drm_plane_calc_addrs() Russell King
2017-12-08 12:14 ` [PATCH 5/5] drm/armada: fix YUV planar format framebuffer offsets Russell King
2017-12-08 12:27 ` [PATCH 00/25] Armada DRM development for 4.16 Russell King - ARM Linux
2017-12-08 12:29   ` [PATCH 01/25] drm/armada: remove armada_drm_plane_work_cancel() return value Russell King
2017-12-08 12:29   ` [PATCH 02/25] drm/armada: add a common frame work allocator Russell King
2017-12-08 12:29   ` [PATCH 03/25] drm/armada: store plane in armada_plane_work Russell King
2017-12-08 12:29   ` [PATCH 04/25] drm/armada: add work cancel callback Russell King
2017-12-08 12:29   ` [PATCH 05/25] drm/armada: wait and cancel any pending frame work at disable Russell King
2017-12-08 12:29   ` [PATCH 06/25] drm/armada: allow the primary plane to be disabled Russell King
2017-12-08 12:29   ` [PATCH 07/25] drm/armada: clean up armada_drm_crtc_plane_disable() Russell King
2017-12-08 12:29   ` [PATCH 08/25] drm/armada: clear plane enable bit when disabling Russell King
2017-12-08 12:29   ` [PATCH 09/25] drm/armada: move overlay plane work out from under spinlock Russell King
2017-12-08 12:29   ` [PATCH 10/25] drm/armada: move fb retirement into armada_plane_work Russell King
2017-12-08 12:29   ` [PATCH 11/25] drm/armada: move event sending " Russell King
2017-12-08 12:29   ` [PATCH 12/25] drm/armada: move regs " Russell King
2017-12-08 12:30   ` [PATCH 13/25] drm/armada: move writes of LCD_SPU_SRAM_PARA1 under lock Russell King
2017-12-08 12:30   ` [PATCH 14/25] drm/armada: only enable HSMOOTH if scaling horizontally Russell King
2017-12-08 12:30   ` [PATCH 15/25] drm/armada: use drm_plane_helper_check_state() Russell King
2017-12-08 12:30   ` [PATCH 16/25] drm/armada: allow armada_drm_plane_work_queue() to silently fail Russell King
2017-12-08 12:30   ` [PATCH 17/25] drm/armada: avoid work allocation Russell King
2017-12-08 12:30   ` [PATCH 18/25] drm/armada: disable planes at next blanking period Russell King
2017-12-08 12:30   ` [PATCH 19/25] drm/armada: re-organise overlay register update generation Russell King
2017-12-08 12:30   ` Russell King [this message]
2017-12-08 12:30   ` [PATCH 21/25] drm/armada: wait for previous work when moving overlay window Russell King
2017-12-08 12:30   ` [PATCH 22/25] drm/armada: extract register generation from armada_drm_primary_set() Russell King
2017-12-08 12:30   ` [PATCH 23/25] drm/armada: implement primary plane update Russell King
2017-12-08 12:31   ` [PATCH 24/25] drm/armada: expand overlay trace entry Russell King
2017-12-08 12:31   ` [PATCH 25/25] drm/armada: add iturbt_709 plane property to control YUV colorspace Russell King
2017-12-11 20:54     ` Daniel Vetter
2017-12-11 22:17       ` Russell King - ARM Linux
2017-12-13 15:02     ` Ville Syrjälä
2017-12-13 15:41     ` Daniel Stone
2017-12-13 16:07       ` Russell King - ARM Linux
2017-12-13 16:12       ` Ilia Mirkin
2017-12-13 16:22         ` Ville Syrjälä
2018-01-01 12:17           ` Russell King - ARM Linux
2018-07-20 11:39             ` Russell King - ARM Linux
2018-07-20 12:26               ` Ville Syrjälä

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=E1eNHne-00076m-2D@rmk-PC.armlinux.org.uk \
    --to=rmk+kernel@armlinux.org.uk \
    --cc=airlied@linux.ie \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

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

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