diff mbox

[PATCH/RFC,372/390] drm/rcar-du: Add configurable z-order support for planes

Message ID 1364525119-31791-373-git-send-email-horms+renesas@verge.net.au (mailing list archive)
State New, archived
Headers show

Commit Message

Simon Horman March 29, 2013, 2:45 a.m. UTC
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Create a new zpos property and instantiate it for each plane with an
initial value of 0. Planes with a higher zpos will be displayed on top.
Two planes with identical zpos values will be displayed in the plane
index number.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
(cherry picked from commit 678f6e92eef5f92e88422143a709209f58ded028)

Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 drivers/gpu/drm/rcar-du/rcar_du_crtc.c  |   49 ++++++++++++++++++---------
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h  |    3 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.h   |    2 ++
 drivers/gpu/drm/rcar-du/rcar_du_plane.c |   55 +++++++++++++++++++++++++++++--
 drivers/gpu/drm/rcar-du/rcar_du_plane.h |    1 +
 5 files changed, 91 insertions(+), 19 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 934e6a5..57e6b89 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -111,36 +111,47 @@  static void rcar_du_crtc_start_stop(struct rcar_du_crtc *rcrtc, bool start)
 		rcar_du_crtc_write(rcrtc, DSYSR, value | DSYSR_DRES);
 }
 
-void rcar_du_crtc_enable_plane(struct rcar_du_plane *rplane, bool enable)
+void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
 {
-	struct rcar_du_crtc *rcrtc = to_rcar_crtc(rplane->crtc);
-	struct rcar_du_device *rcdu = rplane->crtc->dev->dev_private;
-	unsigned int prio;
+	struct rcar_du_device *rcdu = crtc->dev->dev_private;
+	struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
+	struct rcar_du_plane *planes[ARRAY_SIZE(rcdu->planes.planes)];
+	unsigned int num_planes = 0;
+	unsigned int prio = 0;
 	unsigned int i;
 	u32 dspr = 0;
 
-	mutex_lock(&rcdu->planes.lock);
-
-	rplane->enabled = enable;
-
-	for (i = 0, prio = 28; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
+	for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
 		struct rcar_du_plane *plane = &rcdu->planes.planes[i];
+		unsigned int j;
 
 		if (plane->crtc != &rcrtc->crtc || !plane->enabled)
 			continue;
 
-		dspr |= (plane->hwindex + 1) << prio;
+		/* Insert the plane in the sorted planes array. */
+		for (j = num_planes++; j > 0; --j) {
+			if (planes[j-1]->zpos <= plane->zpos)
+				break;
+			planes[j] = planes[j-1];
+		}
+
+		planes[j] = plane;
+		prio += plane->format->planes * 4;
+	}
+
+	for (i = 0; i < num_planes; ++i) {
+		struct rcar_du_plane *plane = planes[i];
+
 		prio -= 4;
+		dspr |= (plane->hwindex + 1) << prio;
 
 		if (plane->format->planes == 2) {
-			dspr |= (plane->hwindex + 2) << prio;
 			prio -= 4;
+			dspr |= (plane->hwindex + 2) << prio;
 		}
 	}
 
 	rcar_du_crtc_write(rcrtc, DS1PR, dspr);
-
-	mutex_unlock(&rcdu->planes.lock);
 }
 
 /*
@@ -180,7 +191,11 @@  static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
 
 	rcar_du_crtc_set_display_timing(rcrtc);
 	rcar_du_plane_setup(rcrtc->plane);
-	rcar_du_crtc_enable_plane(rcrtc->plane, true);
+
+	mutex_lock(&rcdu->planes.lock);
+	rcrtc->plane->enabled = true;
+	rcar_du_crtc_update_planes(crtc);
+	mutex_unlock(&rcdu->planes.lock);
 
 	/* Setup planes. */
 	list_for_each_entry(plane, &rcdu->ddev->mode_config.plane_list, head) {
@@ -205,7 +220,11 @@  static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
 	if (!rcrtc->started)
 		return;
 
-	rcar_du_crtc_enable_plane(rcrtc->plane, false);
+	mutex_lock(&rcdu->planes.lock);
+	rcrtc->plane->enabled = false;
+	rcar_du_crtc_update_planes(crtc);
+	mutex_unlock(&rcdu->planes.lock);
+
 	rcar_du_crtc_start_stop(rcrtc, false);
 
 	clk_disable(rcdu->clock);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index e0dde03..c7b668b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -42,6 +42,7 @@  void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
 				   struct drm_file *file);
 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
 void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
-void rcar_du_crtc_enable_plane(struct rcar_du_plane *plane, bool enable);
+
+void rcar_du_crtc_update_planes(struct drm_crtc *crtc);
 
 #endif /* __RCAR_DU_CRTC_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index bddb4f8..62737bb 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -40,6 +40,8 @@  struct rcar_du_device {
 		struct rcar_du_plane planes[8];
 		unsigned int free;
 		struct mutex lock;
+
+		struct drm_property *zpos;
 	} planes;
 };
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 94bd0e2..cb4ded5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -245,15 +245,24 @@  rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
 	rcar_du_plane_compute_base(rplane, fb);
 	rcar_du_plane_setup(rplane);
 
-	rcar_du_crtc_enable_plane(rplane, true);
+	mutex_lock(&rcdu->planes.lock);
+	rplane->enabled = true;
+	rcar_du_crtc_update_planes(rplane->crtc);
+	mutex_unlock(&rcdu->planes.lock);
+
 	return 0;
 }
 
 static int rcar_du_plane_disable(struct drm_plane *plane)
 {
+	struct rcar_du_device *rcdu = plane->dev->dev_private;
 	struct rcar_du_plane *rplane = to_rcar_plane(plane);
 
-	rcar_du_crtc_enable_plane(rplane, false);
+	mutex_lock(&rcdu->planes.lock);
+	rplane->enabled = false;
+	rcar_du_crtc_update_planes(rplane->crtc);
+	mutex_unlock(&rcdu->planes.lock);
+
 	rcar_du_plane_release(rplane);
 
 	rplane->crtc = NULL;
@@ -262,9 +271,35 @@  static int rcar_du_plane_disable(struct drm_plane *plane)
 	return 0;
 }
 
+static int rcar_du_plane_set_property(struct drm_plane *plane,
+				      struct drm_property *property,
+				      uint64_t value)
+{
+	struct rcar_du_device *rcdu = plane->dev->dev_private;
+	struct rcar_du_plane *rplane = to_rcar_plane(plane);
+
+	if (property != rcdu->planes.zpos)
+		return -EINVAL;
+
+	mutex_lock(&rcdu->planes.lock);
+	if (rplane->zpos == value)
+		goto done;
+
+	rplane->zpos = value;
+	if (!rplane->enabled)
+		goto done;
+
+	rcar_du_crtc_update_planes(rplane->crtc);
+
+done:
+	mutex_unlock(&rcdu->planes.lock);
+	return 0;
+}
+
 static const struct drm_plane_funcs rcar_du_plane_funcs = {
 	.update_plane = rcar_du_plane_update,
 	.disable_plane = rcar_du_plane_disable,
+	.set_property = rcar_du_plane_set_property,
 	.destroy = drm_plane_cleanup,
 };
 
@@ -288,21 +323,35 @@  int rcar_du_plane_init(struct rcar_du_device *rcdu)
 	mutex_init(&rcdu->planes.lock);
 	rcdu->planes.free = 0xff;
 
+	rcdu->planes.zpos =
+		drm_property_create_range(rcdu->ddev, 0, "zpos",
+					  ARRAY_SIZE(rcdu->crtc),
+					  ARRAY_SIZE(rcdu->planes.planes) - 1);
+	if (rcdu->planes.zpos == NULL)
+		return -ENOMEM;
+
 	for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) {
 		struct rcar_du_plane *plane = &rcdu->planes.planes[i];
 
 		plane->dev = rcdu;
 		plane->hwindex = -1;
+		plane->zpos = 1;
 
 		/* Reserve one plane per CRTC */
-		if (i < ARRAY_SIZE(rcdu->crtc))
+		if (i < ARRAY_SIZE(rcdu->crtc)) {
+			plane->zpos = 0;
 			continue;
+		}
 
 		ret = drm_plane_init(rcdu->ddev, &plane->plane, 1,
 				     &rcar_du_plane_funcs, formats,
 				     ARRAY_SIZE(formats), false);
 		if (ret < 0)
 			return ret;
+
+		drm_object_attach_property(&plane->plane.base,
+					   rcdu->planes.zpos, 1);
+
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 1e30237..2090ca4 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -29,6 +29,7 @@  struct rcar_du_plane {
 	bool enabled;
 
 	int hwindex;		/* 0-based, -1 means unused */
+	unsigned int zpos;
 
 	const struct rcar_du_format_info *format;