diff mbox

[PATCHv2,15/45] drm: omapdrm: Implement planes atomic operations

Message ID 1433408582-9828-16-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>

Implement the CRTC .atomic_begin() and .atomic_flush() operations, the
plane .atomic_check(), .atomic_update() and operations, and use the
transitional atomic helpers to implement the plane update and disable
operations on top of the new atomic operations.

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  |  14 ++++
 drivers/gpu/drm/omapdrm/omap_plane.c | 127 ++++++++++++++++++++++-------------
 2 files changed, 93 insertions(+), 48 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 5f4f5ad93345..277cad1dacf7 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -652,6 +652,18 @@  static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 	return omap_crtc_flush(crtc);
 }
 
+static void omap_crtc_atomic_begin(struct drm_crtc *crtc)
+{
+	dispc_runtime_get();
+}
+
+static void omap_crtc_atomic_flush(struct drm_crtc *crtc)
+{
+	omap_crtc_flush(crtc);
+
+	dispc_runtime_put();
+}
+
 static void page_flip_worker(struct work_struct *work)
 {
 	struct omap_crtc *omap_crtc =
@@ -792,6 +804,8 @@  static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
 	.mode_set_base = omap_crtc_mode_set_base,
 	.disable = omap_crtc_disable,
 	.enable = omap_crtc_enable,
+	.atomic_begin = omap_crtc_atomic_begin,
+	.atomic_flush = omap_crtc_atomic_flush,
 };
 
 /* -----------------------------------------------------------------------------
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index 533dcc15f03c..7587bac1b222 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -18,6 +18,7 @@ 
  */
 
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_plane_helper.h>
 
 #include "omap_dmm_tiler.h"
 #include "omap_drv.h"
@@ -87,30 +88,23 @@  static int omap_plane_update_pin(struct drm_plane *plane)
 	return 0;
 }
 
-static int omap_plane_setup(struct omap_plane *omap_plane)
+static int __omap_plane_setup(struct omap_plane *omap_plane,
+			      struct drm_crtc *crtc,
+			      struct drm_framebuffer *fb)
 {
 	struct omap_overlay_info *info = &omap_plane->info;
-	struct drm_plane *plane = &omap_plane->base;
-	struct drm_device *dev = plane->dev;
-	struct drm_crtc *crtc = plane->crtc;
+	struct drm_device *dev = omap_plane->base.dev;
 	int ret;
 
 	DBG("%s, enabled=%d", omap_plane->name, omap_plane->enabled);
 
-	/* if fb has changed, pin new fb: */
-	ret = omap_plane_update_pin(plane);
-	if (ret)
-		return ret;
-
-	dispc_runtime_get();
-
 	if (!omap_plane->enabled) {
 		dispc_ovl_enable(omap_plane->id, false);
-		goto done;
+		return 0;
 	}
 
 	/* update scanout: */
-	omap_framebuffer_update_scanout(plane->fb, &omap_plane->win, info);
+	omap_framebuffer_update_scanout(fb, &omap_plane->win, info);
 
 	DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
 			info->out_width, info->out_height,
@@ -126,13 +120,27 @@  static int omap_plane_setup(struct omap_plane *omap_plane)
 			      omap_crtc_timings(crtc), false);
 	if (ret) {
 		dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
-		goto done;
+		return ret;
 	}
 
 	dispc_ovl_enable(omap_plane->id, true);
 
-done:
+	return 0;
+}
+
+static int omap_plane_setup(struct omap_plane *omap_plane)
+{
+	struct drm_plane *plane = &omap_plane->base;
+	int ret;
+
+	ret = omap_plane_update_pin(plane);
+	if (ret < 0)
+		return ret;
+
+	dispc_runtime_get();
+	ret = __omap_plane_setup(omap_plane, plane->crtc, plane->fb);
 	dispc_runtime_put();
+
 	return ret;
 }
 
@@ -170,45 +178,62 @@  int omap_plane_set_enable(struct drm_plane *plane, bool enable)
 	return omap_plane_setup(omap_plane);
 }
 
-static int omap_plane_update(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 int omap_plane_prepare_fb(struct drm_plane *plane,
+				 struct drm_framebuffer *fb,
+				 const struct drm_plane_state *new_state)
+{
+	return omap_framebuffer_pin(fb);
+}
+
+static void omap_plane_cleanup_fb(struct drm_plane *plane,
+				  struct drm_framebuffer *fb,
+				  const struct drm_plane_state *old_state)
+{
+	omap_framebuffer_unpin(fb);
+}
+
+static void omap_plane_atomic_update(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
-	int ret;
+	struct omap_drm_window *win = &omap_plane->win;
+	struct drm_plane_state *state = plane->state;
+	uint32_t src_w;
+	uint32_t src_h;
 
-	omap_plane->enabled = true;
+	if (!state->fb || !state->crtc)
+		return;
 
-	/* omap_plane_mode_set() takes adjusted src */
+	/* omap_framebuffer_update_scanout() takes adjusted src */
 	switch (omap_plane->win.rotation & 0xf) {
 	case BIT(DRM_ROTATE_90):
 	case BIT(DRM_ROTATE_270):
-		swap(src_w, src_h);
+		src_w = state->src_h;
+		src_h = state->src_w;
+		break;
+	default:
+		src_w = state->src_w;
+		src_h = state->src_h;
 		break;
 	}
 
-	/*
-	 * We don't need to take a reference to the framebuffer as the DRM core
-	 * has already done so for the purpose of setting plane->fb.
-	 */
-	plane->fb = fb;
-	plane->crtc = crtc;
-
-	/* src values are in Q16 fixed point, convert to integer: */
-	ret = omap_plane_mode_set(plane, crtc, fb,
-				  crtc_x, crtc_y, crtc_w, crtc_h,
-				  src_x >> 16, src_y >> 16,
-				  src_w >> 16, src_h >> 16);
-	if (ret < 0)
-		return ret;
+	/* src values are in Q16 fixed point, convert to integer. */
+	win->crtc_x = state->crtc_x;
+	win->crtc_y = state->crtc_y;
+	win->crtc_w = state->crtc_w;
+	win->crtc_h = state->crtc_h;
 
-	return omap_crtc_flush(plane->crtc);
+	win->src_x = state->src_x >> 16;
+	win->src_y = state->src_y >> 16;
+	win->src_w = src_w >> 16;
+	win->src_h = src_h >> 16;
+
+	omap_plane->enabled = true;
+	__omap_plane_setup(omap_plane, state->crtc, state->fb);
 }
 
-static int omap_plane_disable(struct drm_plane *plane)
+static void omap_plane_atomic_disable(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
 
@@ -217,15 +242,19 @@  static int omap_plane_disable(struct drm_plane *plane)
 				? 0 : omap_plane->id;
 
 	if (!omap_plane->enabled)
-		return 0;
+		return;
 
-	/* Disabling a plane never fails. */
 	omap_plane->enabled = false;
-	omap_plane_setup(omap_plane);
-
-	return omap_crtc_flush(plane->crtc);
+	__omap_plane_setup(omap_plane, NULL, NULL);
 }
 
+static const struct drm_plane_helper_funcs omap_plane_helper_funcs = {
+	.prepare_fb = omap_plane_prepare_fb,
+	.cleanup_fb = omap_plane_cleanup_fb,
+	.atomic_update = omap_plane_atomic_update,
+	.atomic_disable = omap_plane_atomic_disable,
+};
+
 static void omap_plane_destroy(struct drm_plane *plane)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
@@ -287,8 +316,8 @@  int omap_plane_set_property(struct drm_plane *plane,
 }
 
 static const struct drm_plane_funcs omap_plane_funcs = {
-	.update_plane = omap_plane_update,
-	.disable_plane = omap_plane_disable,
+	.update_plane = drm_plane_helper_update,
+	.disable_plane = drm_plane_helper_disable,
 	.reset = drm_atomic_helper_plane_reset,
 	.destroy = omap_plane_destroy,
 	.set_property = omap_plane_set_property,
@@ -352,6 +381,8 @@  struct drm_plane *omap_plane_init(struct drm_device *dev,
 	if (ret < 0)
 		goto error;
 
+	drm_plane_helper_add(plane, &omap_plane_helper_funcs);
+
 	omap_plane_install_properties(plane, &plane->base);
 
 	/* get our starting configuration, set defaults for parameters