[PATCH 15/20] drm/armada: switch overlay plane to atomic modeset

Russell King rmk+kernel at armlinux.org.uk
Tue Jul 10 10:42:29 UTC 2018


Switch the overlay plane away from the transitional helpers and legacy
methods, and use atomic helpers instead to implement the legacy
set_plane ioctl methods.

Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
---
 drivers/gpu/drm/armada/armada_crtc.c    |  89 -----------------
 drivers/gpu/drm/armada/armada_crtc.h    |  19 ----
 drivers/gpu/drm/armada/armada_overlay.c | 172 ++++++--------------------------
 3 files changed, 32 insertions(+), 248 deletions(-)

diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index a25094bbeb2c..ebcb99316c94 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -117,80 +117,6 @@ static void armada_drm_crtc_update(struct armada_crtc *dcrtc, bool enable)
 		       dcrtc->base + LCD_SPU_DUMB_CTRL);
 }
 
-static void armada_drm_plane_work_call(struct armada_crtc *dcrtc,
-	struct armada_plane_work *work,
-	void (*fn)(struct armada_crtc *, struct armada_plane_work *))
-{
-	struct armada_plane *dplane = drm_to_armada_plane(work->plane);
-	struct drm_pending_vblank_event *event;
-	struct drm_framebuffer *fb;
-
-	if (fn)
-		fn(dcrtc, work);
-	drm_crtc_vblank_put(&dcrtc->crtc);
-
-	event = work->event;
-	fb = work->old_fb;
-	if (event || fb) {
-		struct drm_device *dev = dcrtc->crtc.dev;
-		unsigned long flags;
-
-		spin_lock_irqsave(&dev->event_lock, flags);
-		if (event)
-			drm_crtc_send_vblank_event(&dcrtc->crtc, event);
-		if (fb)
-			__armada_drm_queue_unref_work(dev, fb);
-		spin_unlock_irqrestore(&dev->event_lock, flags);
-	}
-
-	if (work->need_kfree)
-		kfree(work);
-
-	wake_up(&dplane->frame_wait);
-}
-
-static void armada_drm_plane_work_run(struct armada_crtc *dcrtc,
-	struct drm_plane *plane)
-{
-	struct armada_plane *dplane = drm_to_armada_plane(plane);
-	struct armada_plane_work *work = xchg(&dplane->work, NULL);
-
-	/* Handle any pending frame work. */
-	if (work)
-		armada_drm_plane_work_call(dcrtc, work, work->fn);
-}
-
-int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
-	struct armada_plane_work *work)
-{
-	struct armada_plane *plane = drm_to_armada_plane(work->plane);
-	int ret;
-
-	ret = drm_crtc_vblank_get(&dcrtc->crtc);
-	if (ret)
-		return ret;
-
-	ret = cmpxchg(&plane->work, NULL, work) ? -EBUSY : 0;
-	if (ret)
-		drm_crtc_vblank_put(&dcrtc->crtc);
-
-	return ret;
-}
-
-int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout)
-{
-	return wait_event_timeout(plane->frame_wait, !plane->work, timeout);
-}
-
-void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc,
-	struct armada_plane *dplane)
-{
-	struct armada_plane_work *work = xchg(&dplane->work, NULL);
-
-	if (work)
-		armada_drm_plane_work_call(dcrtc, work, work->cancel);
-}
-
 static void armada_drm_crtc_queue_state_event(struct drm_crtc *crtc)
 {
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
@@ -247,7 +173,6 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 {
 	struct drm_pending_vblank_event *event;
 	void __iomem *base = dcrtc->base;
-	struct drm_plane *ovl_plane;
 
 	if (stat & DMA_FF_UNDERFLOW)
 		DRM_ERROR("video underflow on crtc %u\n", dcrtc->num);
@@ -257,10 +182,6 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
 	if (stat & VSYNC_IRQ)
 		drm_crtc_handle_vblank(&dcrtc->crtc);
 
-	ovl_plane = dcrtc->plane;
-	if (ovl_plane)
-		armada_drm_plane_work_run(dcrtc, ovl_plane);
-
 	spin_lock(&dcrtc->irq_lock);
 	if (stat & GRA_FRAME_IRQ && dcrtc->interlaced) {
 		int i = stat & GRA_FRAME_IRQ0 ? 0 : 1;
@@ -462,19 +383,9 @@ static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc,
 {
 	struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
 	struct drm_pending_vblank_event *event;
-	struct drm_plane *plane;
 
 	DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
-	/*
-	 * For transition only - we must wait for completion of our
-	 * untransitioned paths before changing anything.
-	 */
-	plane = dcrtc->plane;
-	if (plane)
-		WARN_ON(!armada_drm_plane_work_wait(drm_to_armada_plane(plane),
-						    HZ));
-
 	drm_crtc_vblank_off(crtc);
 	armada_drm_crtc_update(dcrtc, false);
 
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h
index afc9266bc1e2..5b607d45f469 100644
--- a/drivers/gpu/drm/armada/armada_crtc.h
+++ b/drivers/gpu/drm/armada/armada_crtc.h
@@ -35,29 +35,12 @@ struct armada_crtc;
 struct armada_plane;
 struct armada_variant;
 
-struct armada_plane_work {
-	void (*fn)(struct armada_crtc *, struct armada_plane_work *);
-	void (*cancel)(struct armada_crtc *, struct armada_plane_work *);
-	bool need_kfree;
-	struct drm_plane *plane;
-	struct drm_framebuffer *old_fb;
-	struct drm_pending_vblank_event *event;
-	struct armada_regs regs[24];
-};
-
 struct armada_plane {
 	struct drm_plane	base;
 	wait_queue_head_t	frame_wait;
-	struct armada_plane_work *work;
 };
 #define drm_to_armada_plane(p) container_of(p, struct armada_plane, base)
 
-int armada_drm_plane_work_queue(struct armada_crtc *dcrtc,
-	struct armada_plane_work *work);
-int armada_drm_plane_work_wait(struct armada_plane *plane, long timeout);
-void armada_drm_plane_work_cancel(struct armada_crtc *dcrtc,
-	struct armada_plane *plane);
-
 struct armada_crtc {
 	struct drm_crtc		crtc;
 	const struct armada_variant *variant;
@@ -73,8 +56,6 @@ struct armada_crtc {
 	bool			interlaced;
 	bool			cursor_update;
 
-	struct drm_plane	*plane;
-
 	struct armada_gem_object	*cursor_obj;
 	int			cursor_x;
 	int			cursor_y;
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index 7de8b6bd7847..ec2043b6f61f 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -27,9 +27,6 @@
 
 struct armada_ovl_plane {
 	struct armada_plane base;
-	struct armada_plane_work works[2];
-	bool next_work;
-	bool wait_vblank;
 };
 #define drm_to_armada_ovl_plane(p) \
 	container_of(p, struct armada_ovl_plane, base.base)
@@ -74,18 +71,6 @@ static inline u32 armada_csc(struct drm_plane_state *state)
 }
 
 /* === Plane support === */
-static void armada_ovl_plane_work(struct armada_crtc *dcrtc,
-	struct armada_plane_work *work)
-{
-	unsigned long flags;
-
-	trace_armada_ovl_plane_work(&dcrtc->crtc, work->plane);
-
-	spin_lock_irqsave(&dcrtc->irq_lock, flags);
-	armada_drm_crtc_update_regs(dcrtc, work->regs);
-	spin_unlock_irqrestore(&dcrtc->irq_lock, flags);
-}
-
 static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 	struct drm_plane_state *old_state)
 {
@@ -109,8 +94,6 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 	dcrtc = drm_to_armada_crtc(state->crtc);
 	regs = dcrtc->regs + dcrtc->regs_idx;
 
-	drm_to_armada_ovl_plane(plane)->wait_vblank = false;
-
 	idx = 0;
 	if (!old_state->visible && state->visible)
 		armada_reg_queue_mod(regs, idx,
@@ -173,8 +156,6 @@ static void armada_drm_overlay_plane_atomic_update(struct drm_plane *plane,
 				       CFG_SWAPYU | CFG_YUV2RGB) |
 			   CFG_DMA_FTOGGLE | CFG_DMA_TSTMODE |
 			   CFG_DMA_ENA;
-
-		drm_to_armada_ovl_plane(plane)->wait_vblank = true;
 	} else if (old_state->visible != state->visible) {
 		cfg = state->visible ? CFG_DMA_ENA : 0;
 		cfg_mask = CFG_DMA_ENA;
@@ -262,9 +243,6 @@ static void armada_drm_overlay_plane_atomic_disable(struct drm_plane *plane,
 			     LCD_SPU_SRAM_PARA1);
 
 	dcrtc->regs_idx += idx;
-
-	if (dcrtc->plane == plane)
-		dcrtc->plane = NULL;
 }
 
 static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = {
@@ -275,108 +253,50 @@ static const struct drm_plane_helper_funcs armada_overlay_plane_helper_funcs = {
 	.atomic_disable	= armada_drm_overlay_plane_atomic_disable,
 };
 
-static int armada_overlay_commit(struct drm_plane *plane,
-	struct drm_plane_state *state)
-{
-	struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
-	const struct drm_plane_helper_funcs *plane_funcs;
-	struct armada_crtc *dcrtc = drm_to_armada_crtc(state->crtc);
-	struct armada_plane_work *work;
-	int ret;
-
-	plane_funcs = plane->helper_private;
-	ret = plane_funcs->atomic_check(plane, state);
-	if (ret)
-		goto put_state;
-
-	work = &dplane->works[dplane->next_work];
-
-	if (plane->state->fb != state->fb) {
-		/*
-		 * Take a reference on the new framebuffer - we want to
-		 * hold on to it while the hardware is displaying it.
-		 */
-		drm_framebuffer_reference(state->fb);
-
-		work->old_fb = plane->state->fb;
-	} else {
-		work->old_fb = NULL;
-	}
-
-	/* Point of no return */
-	swap(plane->state, state);
-
-	/* No CRTC, can't update */
-	if (!plane->state->crtc)
-		goto put_state;
-
-	dcrtc->regs_idx = 0;
-	dcrtc->regs = work->regs;
-
-	plane_funcs->atomic_update(plane, state);
-
-	/* If nothing was updated, short-circuit */
-	if (dcrtc->regs_idx == 0)
-		goto put_state;
-
-	armada_reg_queue_end(dcrtc->regs, dcrtc->regs_idx);
-
-	/* Wait for pending work to complete */
-	if (armada_drm_plane_work_wait(&dplane->base, HZ / 25) == 0)
-		armada_drm_plane_work_cancel(dcrtc, &dplane->base);
-
-	/* Just updating the position/size? */
-	if (!dplane->wait_vblank) {
-		armada_ovl_plane_work(dcrtc, work);
-		goto put_state;
-	}
-
-	dcrtc->plane = plane;
-
-	/* 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);
-		ret = 0;
-	}
-
-	dplane->next_work = !dplane->next_work;
-
-put_state:
-	plane->funcs->atomic_destroy_state(plane, state);
-	return ret;
-}
-
 static int
-armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
+armada_overlay_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 drm_plane_state *state;
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	int ret = 0;
 
 	trace_armada_ovl_plane_update(plane, crtc, fb,
 				 crtc_x, crtc_y, crtc_w, crtc_h,
 				 src_x, src_y, src_w, src_h);
 
-	/* Construct new state for the overlay plane */
-	state = plane->funcs->atomic_duplicate_state(plane);
+	state = drm_atomic_state_alloc(plane->dev);
 	if (!state)
 		return -ENOMEM;
 
-	state->crtc = crtc;
-	drm_atomic_set_fb_for_plane(state, fb);
-	state->crtc_x = crtc_x;
-	state->crtc_y = crtc_y;
-	state->crtc_h = crtc_h;
-	state->crtc_w = crtc_w;
-	state->src_x = src_x;
-	state->src_y = src_y;
-	state->src_h = src_h;
-	state->src_w = src_w;
-
-	return armada_overlay_commit(plane, state);
+	state->acquire_ctx = ctx;
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
+	}
+
+	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+	if (ret != 0)
+		goto fail;
+
+	drm_atomic_set_fb_for_plane(plane_state, fb);
+	plane_state->crtc_x = crtc_x;
+	plane_state->crtc_y = crtc_y;
+	plane_state->crtc_h = crtc_h;
+	plane_state->crtc_w = crtc_w;
+	plane_state->src_x = src_x;
+	plane_state->src_y = src_y;
+	plane_state->src_h = src_h;
+	plane_state->src_w = src_w;
+
+	ret = drm_atomic_nonblocking_commit(state);
+fail:
+	drm_atomic_state_put(state);
+	return ret;
 }
 
 static void armada_ovl_plane_destroy(struct drm_plane *plane)
@@ -388,25 +308,6 @@ static void armada_ovl_plane_destroy(struct drm_plane *plane)
 	kfree(dplane);
 }
 
-static int armada_ovl_plane_set_property(struct drm_plane *plane,
-	struct drm_property *property, uint64_t val)
-{
-	struct drm_plane_state *state;
-	int ret;
-
-	state = plane->funcs->atomic_duplicate_state(plane);
-	if (!state)
-		return -ENOMEM;
-
-	ret = plane->funcs->atomic_set_property(plane, state, property, val);
-	if (ret) {
-		plane->funcs->atomic_destroy_state(plane, state);
-		return ret;
-	}
-
-	return armada_overlay_commit(plane, state);
-}
-
 static void armada_overlay_reset(struct drm_plane *plane)
 {
 	struct armada_overlay_state *state;
@@ -510,9 +411,6 @@ static int armada_overlay_set_property(struct drm_plane *plane,
 		drm_to_overlay_state(state)->contrast = val;
 	} else if (property == priv->saturation_prop) {
 		drm_to_overlay_state(state)->saturation = val;
-	} else if (property == plane->color_encoding_property) {
-		/* transitional only */
-		state->color_encoding = val;
 	} else {
 		return -EINVAL;
 	}
@@ -572,10 +470,9 @@ static int armada_overlay_get_property(struct drm_plane *plane,
 }
 
 static const struct drm_plane_funcs armada_ovl_plane_funcs = {
-	.update_plane	= armada_ovl_plane_update,
-	.disable_plane	= drm_plane_helper_disable,
+	.update_plane	= armada_overlay_plane_update,
+	.disable_plane	= drm_atomic_helper_disable_plane,
 	.destroy	= armada_ovl_plane_destroy,
-	.set_property	= armada_ovl_plane_set_property,
 	.reset		= armada_overlay_reset,
 	.atomic_duplicate_state = armada_overlay_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
@@ -670,11 +567,6 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs)
 		return ret;
 	}
 
-	dplane->works[0].plane = &dplane->base.base;
-	dplane->works[0].fn = armada_ovl_plane_work;
-	dplane->works[1].plane = &dplane->base.base;
-	dplane->works[1].fn = armada_ovl_plane_work;
-
 	drm_plane_helper_add(&dplane->base.base,
 			     &armada_overlay_plane_helper_funcs);
 
-- 
2.7.4



More information about the dri-devel mailing list