diff mbox

[PATCHv2,24/45] drm: omapdrm: Switch crtc and plane set_property to atomic helpers

Message ID 1433408582-9828-25-git-send-email-tomi.valkeinen@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomi Valkeinen June 4, 2015, 9:02 a.m. UTC
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

Allow setting up plane properties atomically using the plane
set_property atomic helper. The properties are now stored in the plane
state (requiring subclassing it) and applied when updating the planes.

The CRTC exposes the properties of its primary plane for legacy reason.
We can't get rid of that API, so simply delegate it to the primary
plane.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c  |  45 +++++++--
 drivers/gpu/drm/omapdrm/omap_drv.h   |   2 -
 drivers/gpu/drm/omapdrm/omap_plane.c | 180 +++++++++++++++++++++++------------
 3 files changed, 156 insertions(+), 71 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 646563e47562..b32a6fb05338 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -540,17 +540,44 @@  static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
 	omap_crtc_flush(crtc);
 
 	dispc_runtime_put();
+
+	crtc->invert_dimensions = !!(crtc->primary->state->rotation &
+				    (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270)));
 }
 
-static int omap_crtc_set_property(struct drm_crtc *crtc,
-		struct drm_property *property, uint64_t val)
+static int omap_crtc_atomic_set_property(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state,
+					 struct drm_property *property,
+					 uint64_t val)
 {
-	if (property == crtc->dev->mode_config.rotation_property) {
-		crtc->invert_dimensions =
-				!!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270)));
-	}
+	struct drm_plane_state *plane_state;
+	struct drm_plane *plane = crtc->primary;
+
+	/*
+	 * Delegate property set to the primary plane. Get the plane state and
+	 * set the property directly.
+	 */
+
+	plane_state = drm_atomic_get_plane_state(state->state, plane);
+	if (!plane_state)
+		return -EINVAL;
+
+	return drm_atomic_plane_set_property(plane, plane_state, property, val);
+}
 
-	return omap_plane_set_property(crtc->primary, property, val);
+static int omap_crtc_atomic_get_property(struct drm_crtc *crtc,
+					 const struct drm_crtc_state *state,
+					 struct drm_property *property,
+					 uint64_t *val)
+{
+	/*
+	 * Delegate property get to the primary plane. The
+	 * drm_atomic_plane_get_property() function isn't exported, but can be
+	 * called through drm_object_property_get_value() as that will call
+	 * drm_atomic_get_property() for atomic drivers.
+	 */
+	return drm_object_property_get_value(&crtc->primary->base, property,
+					     val);
 }
 
 static const struct drm_crtc_funcs omap_crtc_funcs = {
@@ -558,9 +585,11 @@  static const struct drm_crtc_funcs omap_crtc_funcs = {
 	.set_config = drm_atomic_helper_set_config,
 	.destroy = omap_crtc_destroy,
 	.page_flip = drm_atomic_helper_page_flip,
-	.set_property = omap_crtc_set_property,
+	.set_property = drm_atomic_helper_crtc_set_property,
 	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.atomic_set_property = omap_crtc_atomic_set_property,
+	.atomic_get_property = omap_crtc_atomic_get_property,
 };
 
 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 580fe10184d7..f5209412fae6 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -154,8 +154,6 @@  struct drm_plane *omap_plane_init(struct drm_device *dev,
 int omap_plane_set_enable(struct drm_plane *plane, bool enable);
 void omap_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj);
-int omap_plane_set_property(struct drm_plane *plane,
-		struct drm_property *property, uint64_t val);
 
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
 		struct omap_dss_device *dssdev);
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 7813e48b6896..7011cb23d3eb 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -51,10 +51,22 @@  struct omap_plane {
 	struct omap_drm_irq error_irq;
 };
 
-static int __omap_plane_setup(struct omap_plane *omap_plane,
-			      struct drm_crtc *crtc,
-			      struct drm_framebuffer *fb)
+struct omap_plane_state {
+	struct drm_plane_state base;
+
+	unsigned int zorder;
+};
+
+static inline struct omap_plane_state *
+to_omap_plane_state(struct drm_plane_state *state)
 {
+	return container_of(state, struct omap_plane_state, base);
+}
+
+static int omap_plane_setup(struct omap_plane *omap_plane)
+{
+	struct drm_plane_state *state = omap_plane->base.state;
+	struct omap_plane_state *omap_state = to_omap_plane_state(state);
 	struct omap_overlay_info *info = &omap_plane->info;
 	struct drm_device *dev = omap_plane->base.dev;
 	int ret;
@@ -66,8 +78,10 @@  static int __omap_plane_setup(struct omap_plane *omap_plane,
 		return 0;
 	}
 
+	info->zorder = omap_state->zorder;
+
 	/* update scanout: */
-	omap_framebuffer_update_scanout(fb, &omap_plane->win, info);
+	omap_framebuffer_update_scanout(state->fb, &omap_plane->win, info);
 
 	DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
 			info->out_width, info->out_height,
@@ -76,11 +90,11 @@  static int __omap_plane_setup(struct omap_plane *omap_plane,
 			&info->paddr, &info->p_uv_addr);
 
 	dispc_ovl_set_channel_out(omap_plane->id,
-				  omap_crtc_channel(crtc));
+				  omap_crtc_channel(state->crtc));
 
 	/* and finally, update omapdss: */
 	ret = dispc_ovl_setup(omap_plane->id, info, false,
-			      omap_crtc_timings(crtc), false);
+			      omap_crtc_timings(state->crtc), false);
 	if (ret) {
 		dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
 		return ret;
@@ -91,27 +105,21 @@  static int __omap_plane_setup(struct omap_plane *omap_plane,
 	return 0;
 }
 
-static int omap_plane_setup(struct omap_plane *omap_plane)
-{
-	struct drm_plane *plane = &omap_plane->base;
-	int ret;
-
-	dispc_runtime_get();
-	ret = __omap_plane_setup(omap_plane, plane->crtc, plane->fb);
-	dispc_runtime_put();
-
-	return ret;
-}
-
 int omap_plane_set_enable(struct drm_plane *plane, bool enable)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
+	int ret;
 
 	if (enable == omap_plane->enabled)
 		return 0;
 
 	omap_plane->enabled = enable;
-	return omap_plane_setup(omap_plane);
+
+	dispc_runtime_get();
+	ret = omap_plane_setup(omap_plane);
+	dispc_runtime_put();
+
+	return ret;
 }
 
 static int omap_plane_prepare_fb(struct drm_plane *plane,
@@ -140,8 +148,10 @@  static void omap_plane_atomic_update(struct drm_plane *plane,
 	if (!state->fb || !state->crtc)
 		return;
 
+	win->rotation = state->rotation;
+
 	/* omap_framebuffer_update_scanout() takes adjusted src */
-	switch (omap_plane->win.rotation & 0xf) {
+	switch (state->rotation & 0xf) {
 	case BIT(DRM_ROTATE_90):
 	case BIT(DRM_ROTATE_270):
 		src_w = state->src_h;
@@ -165,23 +175,24 @@  static void omap_plane_atomic_update(struct drm_plane *plane,
 	win->src_h = src_h >> 16;
 
 	omap_plane->enabled = true;
-	__omap_plane_setup(omap_plane, state->crtc, state->fb);
+	omap_plane_setup(omap_plane);
 }
 
 static void omap_plane_atomic_disable(struct drm_plane *plane,
 				      struct drm_plane_state *old_state)
 {
+	struct omap_plane_state *omap_state = to_omap_plane_state(plane->state);
 	struct omap_plane *omap_plane = to_omap_plane(plane);
 
-	omap_plane->win.rotation = BIT(DRM_ROTATE_0);
-	omap_plane->info.zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
-				? 0 : omap_plane->id;
+	plane->state->rotation = BIT(DRM_ROTATE_0);
+	omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
+			   ? 0 : omap_plane->id;
 
 	if (!omap_plane->enabled)
 		return;
 
 	omap_plane->enabled = false;
-	__omap_plane_setup(omap_plane, NULL, NULL);
+	omap_plane_setup(omap_plane);
 }
 
 static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
@@ -191,6 +202,33 @@  static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
 	.atomic_disable = omap_plane_atomic_disable,
 };
 
+static void omap_plane_reset(struct drm_plane *plane)
+{
+	struct omap_plane *omap_plane = to_omap_plane(plane);
+	struct omap_plane_state *omap_state;
+
+	if (plane->state && plane->state->fb)
+		drm_framebuffer_unreference(plane->state->fb);
+
+	kfree(plane->state);
+	plane->state = NULL;
+
+	omap_state = kzalloc(sizeof(*omap_state), GFP_KERNEL);
+	if (omap_state == NULL)
+		return;
+
+	/*
+	 * Set defaults depending on whether we are a primary or overlay
+	 * plane.
+	 */
+	omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY
+			   ? 0 : omap_plane->id;
+	omap_state->base.rotation = BIT(DRM_ROTATE_0);
+
+	plane->state = &omap_state->base;
+	plane->state->plane = plane;
+}
+
 static void omap_plane_destroy(struct drm_plane *plane)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
@@ -220,45 +258,75 @@  void omap_plane_install_properties(struct drm_plane *plane,
 	drm_object_attach_property(obj, priv->zorder_prop, 0);
 }
 
-int omap_plane_set_property(struct drm_plane *plane,
-		struct drm_property *property, uint64_t val)
+static struct drm_plane_state *
+omap_plane_atomic_duplicate_state(struct drm_plane *plane)
+{
+	struct omap_plane_state *state;
+	struct omap_plane_state *copy;
+
+	if (WARN_ON(!plane->state))
+		return NULL;
+
+	state = to_omap_plane_state(plane->state);
+	copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
+	if (copy == NULL)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &copy->base);
+
+	return &copy->base;
+}
+
+static void omap_plane_atomic_destroy_state(struct drm_plane *plane,
+					    struct drm_plane_state *state)
+{
+	__drm_atomic_helper_plane_destroy_state(plane, state);
+	kfree(to_omap_plane_state(state));
+}
+
+static int omap_plane_atomic_set_property(struct drm_plane *plane,
+					  struct drm_plane_state *state,
+					  struct drm_property *property,
+					  uint64_t val)
 {
-	struct omap_plane *omap_plane = to_omap_plane(plane);
 	struct omap_drm_private *priv = plane->dev->dev_private;
-	int ret;
+	struct omap_plane_state *omap_state = to_omap_plane_state(state);
 
-	if (property == plane->dev->mode_config.rotation_property) {
-		DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val);
-		omap_plane->win.rotation = val;
-	} else if (property == priv->zorder_prop) {
-		DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
-		omap_plane->info.zorder = val;
-	} else {
+	if (property == priv->zorder_prop)
+		omap_state->zorder = val;
+	else
 		return -EINVAL;
-	}
 
-	/*
-	 * We're done if the plane is disabled, properties will be applied the
-	 * next time it becomes enabled.
-	 */
-	if (!omap_plane->enabled)
-		return 0;
+	return 0;
+}
 
-	ret = omap_plane_setup(omap_plane);
-	if (ret < 0)
-		return ret;
+static int omap_plane_atomic_get_property(struct drm_plane *plane,
+					  const struct drm_plane_state *state,
+					  struct drm_property *property,
+					  uint64_t *val)
+{
+	struct omap_drm_private *priv = plane->dev->dev_private;
+	const struct omap_plane_state *omap_state =
+		container_of(state, const struct omap_plane_state, base);
+
+	if (property == priv->zorder_prop)
+		*val = omap_state->zorder;
+	else
+		return -EINVAL;
 
-	return omap_crtc_flush(plane->crtc);
+	return 0;
 }
 
 static const struct drm_plane_funcs omap_plane_funcs = {
 	.update_plane = drm_atomic_helper_update_plane,
 	.disable_plane = drm_atomic_helper_disable_plane,
-	.reset = drm_atomic_helper_plane_reset,
+	.reset = omap_plane_reset,
 	.destroy = omap_plane_destroy,
-	.set_property = omap_plane_set_property,
-	.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
-	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+	.set_property = drm_atomic_helper_plane_set_property,
+	.atomic_duplicate_state = omap_plane_atomic_duplicate_state,
+	.atomic_destroy_state = omap_plane_atomic_destroy_state,
+	.atomic_set_property = omap_plane_atomic_set_property,
+	.atomic_get_property = omap_plane_atomic_get_property,
 };
 
 static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
@@ -330,16 +398,6 @@  struct drm_plane *omap_plane_init(struct drm_device *dev,
 	info->global_alpha = 0xff;
 	info->mirror = 0;
 
-	/* Set defaults depending on whether we are a CRTC or overlay
-	 * layer.
-	 * TODO add ioctl to give userspace an API to change this.. this
-	 * will come in a subsequent patch.
-	 */
-	if (type == DRM_PLANE_TYPE_PRIMARY)
-		omap_plane->info.zorder = 0;
-	else
-		omap_plane->info.zorder = id;
-
 	return plane;
 
 error: