All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Enable Atomic Mode Set on vmwgfx
@ 2017-03-27 22:00 Sinclair Yeh
  2017-03-27 22:00 ` [PATCH 01/11] drm/vmwgfx: Add universal plane support Sinclair Yeh
                   ` (11 more replies)
  0 siblings, 12 replies; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

This series enables atomic mode set on vmwgfx.  Developed in
collaboration with Thomas Hellstrom and the VMWare Graphics
Team.

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

^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 01/11] drm/vmwgfx: Add universal plane support
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
@ 2017-03-27 22:00 ` Sinclair Yeh
  2017-03-28  7:07   ` Daniel Vetter
  2017-03-27 22:00 ` [PATCH 02/11] drm/vmwgfx: CRTC atomic state Sinclair Yeh
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Universal support is prerequisite for atomic mode set.

Explicitly create planes for the cursor and the primary FB.  With
a functional cursor plane, the DRM will no longer use the legacy
cursor_set2 and cursor_move entry points.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.c  |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 271 +++++++++++++++++------------------
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  39 +++--
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 108 ++++++++++----
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |  87 +++++++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  89 ++++++++++--
 7 files changed, 398 insertions(+), 198 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 541a588..45d711e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -645,6 +645,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 	spin_lock_init(&dev_priv->waiter_lock);
 	spin_lock_init(&dev_priv->cap_lock);
 	spin_lock_init(&dev_priv->svga_lock);
+	spin_lock_init(&dev_priv->cursor_lock);
 
 	for (i = vmw_res_context; i < vmw_res_max; ++i) {
 		idr_init(&dev_priv->res_idr[i]);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 9ae4477..ef0181c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -414,6 +414,7 @@ struct vmw_private {
 	unsigned num_implicit;
 	struct vmw_framebuffer *implicit_fb;
 	struct mutex global_kms_state_mutex;
+	spinlock_t cursor_lock;
 
 	/*
 	 * Context and surface management.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 6bcba56..c9f5dda 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -33,10 +33,9 @@
 
 void vmw_du_cleanup(struct vmw_display_unit *du)
 {
-	if (du->cursor_surface)
-		vmw_surface_unreference(&du->cursor_surface);
-	if (du->cursor_dmabuf)
-		vmw_dmabuf_unreference(&du->cursor_dmabuf);
+	drm_plane_cleanup(&du->primary);
+	drm_plane_cleanup(&du->cursor);
+
 	drm_connector_unregister(&du->connector);
 	drm_crtc_cleanup(&du->crtc);
 	drm_encoder_cleanup(&du->encoder);
@@ -47,9 +46,9 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
  * Display Unit Cursor functions
  */
 
-int vmw_cursor_update_image(struct vmw_private *dev_priv,
-			    u32 *image, u32 width, u32 height,
-			    u32 hotspotX, u32 hotspotY)
+static int vmw_cursor_update_image(struct vmw_private *dev_priv,
+				   u32 *image, u32 width, u32 height,
+				   u32 hotspotX, u32 hotspotY)
 {
 	struct {
 		u32 cmd;
@@ -83,10 +82,10 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv,
 	return 0;
 }
 
-int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
-			     struct vmw_dma_buffer *dmabuf,
-			     u32 width, u32 height,
-			     u32 hotspotX, u32 hotspotY)
+static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
+				    struct vmw_dma_buffer *dmabuf,
+				    u32 width, u32 height,
+				    u32 hotspotX, u32 hotspotY)
 {
 	struct ttm_bo_kmap_obj map;
 	unsigned long kmap_offset;
@@ -120,145 +119,22 @@ int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
 }
 
 
-void vmw_cursor_update_position(struct vmw_private *dev_priv,
-				bool show, int x, int y)
+static void vmw_cursor_update_position(struct vmw_private *dev_priv,
+				       bool show, int x, int y)
 {
 	u32 *fifo_mem = dev_priv->mmio_virt;
 	uint32_t count;
 
+	spin_lock(&dev_priv->cursor_lock);
 	vmw_mmio_write(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
 	vmw_mmio_write(x, fifo_mem + SVGA_FIFO_CURSOR_X);
 	vmw_mmio_write(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
 	count = vmw_mmio_read(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
 	vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
+	spin_unlock(&dev_priv->cursor_lock);
 }
 
 
-/*
- * vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
- */
-int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
-			    uint32_t handle, uint32_t width, uint32_t height,
-			    int32_t hot_x, int32_t hot_y)
-{
-	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
-	struct vmw_surface *surface = NULL;
-	struct vmw_dma_buffer *dmabuf = NULL;
-	s32 hotspot_x, hotspot_y;
-	int ret;
-
-	/*
-	 * FIXME: Unclear whether there's any global state touched by the
-	 * cursor_set function, especially vmw_cursor_update_position looks
-	 * suspicious. For now take the easy route and reacquire all locks. We
-	 * can do this since the caller in the drm core doesn't check anything
-	 * which is protected by any looks.
-	 */
-	drm_modeset_unlock_crtc(crtc);
-	drm_modeset_lock_all(dev_priv->dev);
-	hotspot_x = hot_x + du->hotspot_x;
-	hotspot_y = hot_y + du->hotspot_y;
-
-	/* A lot of the code assumes this */
-	if (handle && (width != 64 || height != 64)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (handle) {
-		struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
-
-		ret = vmw_user_lookup_handle(dev_priv, tfile,
-					     handle, &surface, &dmabuf);
-		if (ret) {
-			DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
-			ret = -EINVAL;
-			goto out;
-		}
-	}
-
-	/* need to do this before taking down old image */
-	if (surface && !surface->snooper.image) {
-		DRM_ERROR("surface not suitable for cursor\n");
-		vmw_surface_unreference(&surface);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* takedown old cursor */
-	if (du->cursor_surface) {
-		vmw_surface_unreference(&du->cursor_surface);
-	}
-	if (du->cursor_dmabuf)
-		vmw_dmabuf_unreference(&du->cursor_dmabuf);
-
-	/* setup new image */
-	ret = 0;
-	if (surface) {
-		/* vmw_user_surface_lookup takes one reference */
-		du->cursor_surface = surface;
-
-		du->cursor_age = du->cursor_surface->snooper.age;
-		ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
-					      64, 64, hotspot_x, hotspot_y);
-	} else if (dmabuf) {
-		/* vmw_user_surface_lookup takes one reference */
-		du->cursor_dmabuf = dmabuf;
-
-		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
-					       hotspot_x, hotspot_y);
-	} else {
-		vmw_cursor_update_position(dev_priv, false, 0, 0);
-		goto out;
-	}
-
-	if (!ret) {
-		vmw_cursor_update_position(dev_priv, true,
-					   du->cursor_x + hotspot_x,
-					   du->cursor_y + hotspot_y);
-		du->core_hotspot_x = hot_x;
-		du->core_hotspot_y = hot_y;
-	}
-
-out:
-	drm_modeset_unlock_all(dev_priv->dev);
-	drm_modeset_lock_crtc(crtc, crtc->cursor);
-
-	return ret;
-}
-
-int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
-{
-	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
-	bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false;
-
-	du->cursor_x = x + du->set_gui_x;
-	du->cursor_y = y + du->set_gui_y;
-
-	/*
-	 * FIXME: Unclear whether there's any global state touched by the
-	 * cursor_set function, especially vmw_cursor_update_position looks
-	 * suspicious. For now take the easy route and reacquire all locks. We
-	 * can do this since the caller in the drm core doesn't check anything
-	 * which is protected by any looks.
-	 */
-	drm_modeset_unlock_crtc(crtc);
-	drm_modeset_lock_all(dev_priv->dev);
-
-	vmw_cursor_update_position(dev_priv, shown,
-				   du->cursor_x + du->hotspot_x +
-				   du->core_hotspot_x,
-				   du->cursor_y + du->hotspot_y +
-				   du->core_hotspot_y);
-
-	drm_modeset_unlock_all(dev_priv->dev);
-	drm_modeset_lock_crtc(crtc, crtc->cursor);
-
-	return 0;
-}
-
 void vmw_kms_cursor_snoop(struct vmw_surface *srf,
 			  struct ttm_object_file *tfile,
 			  struct ttm_buffer_object *bo,
@@ -393,6 +269,125 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
 	mutex_unlock(&dev->mode_config.mutex);
 }
 
+
+
+/**
+ * vmw_du_cursor_plane_update() - Update cursor image and location
+ *
+ * @plane: plane object to update
+ * @crtc: owning CRTC of @plane
+ * @fb: framebuffer to flip onto plane
+ * @crtc_x: x offset of plane on crtc
+ * @crtc_y: y offset of plane on crtc
+ * @crtc_w: width of plane rectangle on crtc
+ * @crtc_h: height of plane rectangle on crtc
+ * @src_x: Not used
+ * @src_y: Not used
+ * @src_w: Not used
+ * @src_h: Not used
+ *
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+int vmw_du_cursor_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)
+{
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	struct vmw_surface *surface = NULL;
+	struct vmw_dma_buffer *dmabuf = NULL;
+	s32 hotspot_x, hotspot_y;
+	int ret;
+
+	hotspot_x = du->hotspot_x + fb->hot_x;
+	hotspot_y = du->hotspot_y + fb->hot_y;
+
+	/* A lot of the code assumes this */
+	if (crtc_w != 64 || crtc_h != 64) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (vmw_framebuffer_to_vfb(fb)->dmabuf)
+		dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
+	else
+		surface = vmw_framebuffer_to_vfbs(fb)->surface;
+
+	if (surface && !surface->snooper.image) {
+		DRM_ERROR("surface not suitable for cursor\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* setup new image */
+	ret = 0;
+	if (surface) {
+		/* vmw_user_surface_lookup takes one reference */
+		du->cursor_surface = surface;
+
+		du->cursor_age = du->cursor_surface->snooper.age;
+
+		ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
+					      64, 64, hotspot_x, hotspot_y);
+	} else if (dmabuf) {
+		/* vmw_user_surface_lookup takes one reference */
+		du->cursor_dmabuf = dmabuf;
+
+		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
+					       hotspot_x, hotspot_y);
+	} else {
+		vmw_cursor_update_position(dev_priv, false, 0, 0);
+		goto out;
+	}
+
+	if (!ret) {
+		du->cursor_x = crtc_x + du->set_gui_x;
+		du->cursor_y = crtc_y + du->set_gui_y;
+
+		vmw_cursor_update_position(dev_priv, true,
+					   du->cursor_x + hotspot_x,
+					   du->cursor_y + hotspot_y);
+	}
+
+out:
+	return ret;
+}
+
+
+int vmw_du_cursor_plane_disable(struct drm_plane *plane)
+{
+	if (plane->fb) {
+		drm_framebuffer_unreference(plane->fb);
+		plane->fb = NULL;
+	}
+
+	return -EINVAL;
+}
+
+
+void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
+{
+	vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
+
+	drm_plane_cleanup(plane);
+}
+
+
+void vmw_du_primary_plane_destroy(struct drm_plane *plane)
+{
+	drm_plane_cleanup(plane);
+
+	/* Planes are static in our case so we don't free it */
+}
+
+
 /*
  * Generic framebuffer code
  */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index cb36e1d..e400bfb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -33,6 +33,8 @@
 #include <drm/drm_encoder.h>
 #include "vmwgfx_drv.h"
 
+
+
 /**
  * struct vmw_kms_dirty - closure structure for the vmw_kms_helper_dirty
  * function.
@@ -125,19 +127,17 @@ struct vmw_framebuffer_dmabuf {
 };
 
 
-/*
- * Basic cursor manipulation
- */
-int vmw_cursor_update_image(struct vmw_private *dev_priv,
-			    u32 *image, u32 width, u32 height,
-			    u32 hotspotX, u32 hotspotY);
-int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
-			     struct vmw_dma_buffer *dmabuf,
-			     u32 width, u32 height,
-			     u32 hotspotX, u32 hotspotY);
-void vmw_cursor_update_position(struct vmw_private *dev_priv,
-				bool show, int x, int y);
+static const uint32_t vmw_primary_plane_formats[] = {
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+};
 
+static const uint32_t vmw_cursor_plane_formats[] = {
+	DRM_FORMAT_ARGB8888,
+};
 
 /**
  * Base class display unit.
@@ -150,6 +150,8 @@ struct vmw_display_unit {
 	struct drm_crtc crtc;
 	struct drm_encoder encoder;
 	struct drm_connector connector;
+	struct drm_plane primary;
+	struct drm_plane cursor;
 
 	struct vmw_surface *cursor_surface;
 	struct vmw_dma_buffer *cursor_dmabuf;
@@ -270,6 +272,19 @@ void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
 void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
 						bool immutable);
 
+/* Universal Plane Helpers */
+void vmw_du_primary_plane_destroy(struct drm_plane *plane);
+void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
+int vmw_du_cursor_plane_disable(struct drm_plane *plane);
+int vmw_du_cursor_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);
+
 
 /*
  * Legacy display unit functions - vmwgfx_ldu.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 3806148..3efcbe5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -75,10 +75,9 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 {
 	struct vmw_legacy_display *lds = dev_priv->ldu_priv;
 	struct vmw_legacy_display_unit *entry;
-	struct vmw_display_unit *du = NULL;
 	struct drm_framebuffer *fb = NULL;
 	struct drm_crtc *crtc = NULL;
-	int i = 0, ret;
+	int i = 0;
 
 	/* If there is no display topology the host just assumes
 	 * that the guest will set the same layout as the host.
@@ -132,25 +131,6 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
 	lds->last_num_active = lds->num_active;
 
-
-	/* Find the first du with a cursor. */
-	list_for_each_entry(entry, &lds->active, active) {
-		du = &entry->base;
-
-		if (!du->cursor_dmabuf)
-			continue;
-
-		ret = vmw_cursor_update_dmabuf(dev_priv,
-					       du->cursor_dmabuf,
-					       64, 64,
-					       du->hotspot_x,
-					       du->hotspot_y);
-		if (ret == 0)
-			break;
-
-		DRM_ERROR("Could not update cursor image\n");
-	}
-
 	return 0;
 }
 
@@ -298,8 +278,6 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 }
 
 static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
-	.cursor_set2 = vmw_du_crtc_cursor_set2,
-	.cursor_move = vmw_du_crtc_cursor_move,
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_ldu_crtc_destroy,
 	.set_config = vmw_ldu_crtc_set_config,
@@ -336,6 +314,23 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
 	.destroy = vmw_ldu_connector_destroy,
 };
 
+/*
+ * Legacy Display Plane Functions
+ */
+
+static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
+	.update_plane = drm_primary_helper_update,
+	.disable_plane = drm_primary_helper_disable,
+	.destroy = vmw_du_primary_plane_destroy,
+};
+
+static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
+	.update_plane = vmw_du_cursor_plane_update,
+	.disable_plane = vmw_du_cursor_plane_disable,
+	.destroy = vmw_du_cursor_plane_destroy,
+};
+
+
 static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 {
 	struct vmw_legacy_display_unit *ldu;
@@ -343,6 +338,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
+	int ret;
 
 	ldu = kzalloc(sizeof(*ldu), GFP_KERNEL);
 	if (!ldu)
@@ -361,19 +357,61 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	ldu->base.pref_mode = NULL;
 	ldu->base.is_implicit = true;
 
-	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
-			   DRM_MODE_CONNECTOR_VIRTUAL);
+	/* Initialize primary plane */
+	ret = drm_universal_plane_init(dev, &ldu->base.primary,
+				       0, &vmw_ldu_plane_funcs,
+				       vmw_primary_plane_formats,
+				       ARRAY_SIZE(vmw_primary_plane_formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize primary plane");
+		goto err_free;
+	}
+
+	/* Initialize cursor plane */
+	ret = drm_universal_plane_init(dev, &ldu->base.cursor,
+			0, &vmw_ldu_cursor_funcs,
+			vmw_cursor_plane_formats,
+			ARRAY_SIZE(vmw_cursor_plane_formats),
+			DRM_PLANE_TYPE_CURSOR, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize cursor plane");
+		drm_plane_cleanup(&ldu->base.primary);
+		goto err_free;
+	}
+
+	ret = drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		goto err_free;
+	}
 	connector->status = vmw_du_connector_detect(connector, true);
 
-	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
-	drm_mode_connector_attach_encoder(connector, encoder);
+	ret = drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
+			       DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize encoder\n");
+		goto err_free_connector;
+	}
+
+	(void) drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
-	(void) drm_connector_register(connector);
+	ret = drm_connector_register(connector);
+	if (ret) {
+		DRM_ERROR("Failed to register connector\n");
+		goto err_free_encoder;
+	}
 
-	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
+	ret = drm_crtc_init_with_planes(dev, crtc, &ldu->base.primary,
+					&ldu->base.cursor,
+					&vmw_legacy_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize CRTC\n");
+		goto err_free_unregister;
+	}
 
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
@@ -390,6 +428,16 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 			 1);
 
 	return 0;
+
+err_free_unregister:
+	drm_connector_unregister(connector);
+err_free_encoder:
+	drm_encoder_cleanup(encoder);
+err_free_connector:
+	drm_connector_cleanup(connector);
+err_free:
+	kfree(ldu);
+	return ret;
 }
 
 int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index d4268ef..8ffccb8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -459,8 +459,6 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 }
 
 static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
-	.cursor_set2 = vmw_du_crtc_cursor_set2,
-	.cursor_move = vmw_du_crtc_cursor_move,
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_sou_crtc_destroy,
 	.set_config = vmw_sou_crtc_set_config,
@@ -497,6 +495,23 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
 	.destroy = vmw_sou_connector_destroy,
 };
 
+/*
+ * Screen Object Display Plane Functions
+ */
+
+static const struct drm_plane_funcs vmw_sou_plane_funcs = {
+	.update_plane = drm_primary_helper_update,
+	.disable_plane = drm_primary_helper_disable,
+	.destroy = vmw_du_primary_plane_destroy,
+};
+
+static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
+	.update_plane = vmw_du_cursor_plane_update,
+	.disable_plane = vmw_du_cursor_plane_disable,
+	.destroy = vmw_du_cursor_plane_destroy,
+};
+
+
 static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 {
 	struct vmw_screen_object_unit *sou;
@@ -504,6 +519,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
+	int ret;
 
 	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
 	if (!sou)
@@ -521,19 +537,62 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	sou->base.pref_mode = NULL;
 	sou->base.is_implicit = false;
 
-	drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
-			   DRM_MODE_CONNECTOR_VIRTUAL);
+	/* Initialize primary plane */
+	ret = drm_universal_plane_init(dev, &sou->base.primary,
+				       0, &vmw_sou_plane_funcs,
+				       vmw_primary_plane_formats,
+				       ARRAY_SIZE(vmw_primary_plane_formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize primary plane");
+		goto err_free;
+	}
+
+	/* Initialize cursor plane */
+	ret = drm_universal_plane_init(dev, &sou->base.cursor,
+			0, &vmw_sou_cursor_funcs,
+			vmw_cursor_plane_formats,
+			ARRAY_SIZE(vmw_cursor_plane_formats),
+			DRM_PLANE_TYPE_CURSOR, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize cursor plane");
+		drm_plane_cleanup(&sou->base.primary);
+		goto err_free;
+	}
+
+	ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		goto err_free;
+	}
+
 	connector->status = vmw_du_connector_detect(connector, true);
 
-	drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
-	drm_mode_connector_attach_encoder(connector, encoder);
+	ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
+			       DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize encoder\n");
+		goto err_free_connector;
+	}
+
+	(void) drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
-	(void) drm_connector_register(connector);
+	ret = drm_connector_register(connector);
+	if (ret) {
+		DRM_ERROR("Failed to register connector\n");
+		goto err_free_encoder;
+	}
 
-	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
+	ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
+					&sou->base.cursor,
+					&vmw_screen_object_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize CRTC\n");
+		goto err_free_unregister;
+	}
 
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
@@ -550,6 +609,16 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 			 sou->base.is_implicit);
 
 	return 0;
+
+err_free_unregister:
+	drm_connector_unregister(connector);
+err_free_encoder:
+	drm_encoder_cleanup(encoder);
+err_free_connector:
+	drm_connector_cleanup(connector);
+err_free:
+	kfree(sou);
+	return ret;
 }
 
 int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index b27cd18..4d9dd1b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1015,8 +1015,6 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
  *  Screen Target CRTC dispatch table
  */
 static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
-	.cursor_set2 = vmw_du_crtc_cursor_set2,
-	.cursor_move = vmw_du_crtc_cursor_move,
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_stdu_crtc_destroy,
 	.set_config = vmw_stdu_crtc_set_config,
@@ -1081,6 +1079,23 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 
 
 
+/******************************************************************************
+ * Screen Target Display Plane Functions
+ *****************************************************************************/
+
+static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
+	.update_plane = drm_primary_helper_update,
+	.disable_plane = drm_primary_helper_disable,
+	.destroy = vmw_du_primary_plane_destroy,
+};
+
+static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
+	.update_plane = vmw_du_cursor_plane_update,
+	.disable_plane = vmw_du_cursor_plane_disable,
+	.destroy = vmw_du_cursor_plane_destroy,
+};
+
+
 /**
  * vmw_stdu_init - Sets up a Screen Target Display Unit
  *
@@ -1097,7 +1112,9 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
+	struct drm_plane *primary, *cursor;
 	struct drm_crtc *crtc;
+	int    ret;
 
 
 	stdu = kzalloc(sizeof(*stdu), GFP_KERNEL);
@@ -1108,25 +1125,69 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 	crtc = &stdu->base.crtc;
 	encoder = &stdu->base.encoder;
 	connector = &stdu->base.connector;
+	primary = &stdu->base.primary;
+	cursor = &stdu->base.cursor;
 
 	stdu->base.pref_active = (unit == 0);
 	stdu->base.pref_width  = dev_priv->initial_width;
 	stdu->base.pref_height = dev_priv->initial_height;
 	stdu->base.is_implicit = false;
 
-	drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
-			   DRM_MODE_CONNECTOR_VIRTUAL);
+	/* Initialize primary plane */
+	ret = drm_universal_plane_init(dev, primary,
+				       0, &vmw_stdu_plane_funcs,
+				       vmw_primary_plane_formats,
+				       ARRAY_SIZE(vmw_primary_plane_formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize primary plane");
+		goto err_free;
+	}
+
+	/* Initialize cursor plane */
+	ret = drm_universal_plane_init(dev, cursor,
+			0, &vmw_stdu_cursor_funcs,
+			vmw_cursor_plane_formats,
+			ARRAY_SIZE(vmw_cursor_plane_formats),
+			DRM_PLANE_TYPE_CURSOR, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize cursor plane");
+		drm_plane_cleanup(&stdu->base.primary);
+		goto err_free;
+	}
+
+	ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
+				 DRM_MODE_CONNECTOR_VIRTUAL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize connector\n");
+		goto err_free;
+	}
 	connector->status = vmw_du_connector_detect(connector, false);
 
-	drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
-			 DRM_MODE_ENCODER_VIRTUAL, NULL);
-	drm_mode_connector_attach_encoder(connector, encoder);
+	ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
+			       DRM_MODE_ENCODER_VIRTUAL, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize encoder\n");
+		goto err_free_connector;
+	}
+
+	(void) drm_mode_connector_attach_encoder(connector, encoder);
 	encoder->possible_crtcs = (1 << unit);
 	encoder->possible_clones = 0;
 
-	(void) drm_connector_register(connector);
+	ret = drm_connector_register(connector);
+	if (ret) {
+		DRM_ERROR("Failed to register connector\n");
+		goto err_free_encoder;
+	}
 
-	drm_crtc_init(dev, crtc, &vmw_stdu_crtc_funcs);
+	ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
+					&stdu->base.cursor,
+					&vmw_stdu_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("Failed to initialize CRTC\n");
+		goto err_free_unregister;
+	}
 
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
@@ -1142,6 +1203,16 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 			 dev_priv->implicit_placement_property,
 			 stdu->base.is_implicit);
 	return 0;
+
+err_free_unregister:
+	drm_connector_unregister(connector);
+err_free_encoder:
+	drm_encoder_cleanup(encoder);
+err_free_connector:
+	drm_connector_cleanup(connector);
+err_free:
+	kfree(stdu);
+	return ret;
 }
 
 
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 02/11] drm/vmwgfx: CRTC atomic state
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
  2017-03-27 22:00 ` [PATCH 01/11] drm/vmwgfx: Add universal plane support Sinclair Yeh
@ 2017-03-27 22:00 ` Sinclair Yeh
  2017-03-27 22:00 ` [PATCH 03/11] drm/vmwgfx: Plane " Sinclair Yeh
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Create and Add CRTC state.  We currently do not track any properties
or custom states so we can technically use the DRM helpers.  Creating
this code just to make potential future additions easier.

Most of the new code will be compiled but not enabled until
plane/connector state handling code is also in place.

This is the first of a series to enable atomic mode set for vmwgfx.

The atomic enabling effort was done in collaboration with Thomas
Hellstrom and the VMware Graphics Team.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 81 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  | 23 ++++++++--
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 10 +++++
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 10 +++++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 10 +++++
 5 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index c9f5dda..18bd8dc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -26,6 +26,8 @@
  **************************************************************************/
 
 #include "vmwgfx_kms.h"
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 
 
 /* Might need a hrtimer here? */
@@ -388,6 +390,84 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
 }
 
 
+/**
+ * vmw_du_crtc_duplicate_state - duplicate crtc state
+ * @crtc: DRM crtc
+ *
+ * Allocates and returns a copy of the crtc state (both common and
+ * vmw-specific) for the specified crtc.
+ *
+ * Returns: The newly allocated crtc state, or NULL on failure.
+ */
+struct drm_crtc_state *
+vmw_du_crtc_duplicate_state(struct drm_crtc *crtc)
+{
+	struct drm_crtc_state *state;
+	struct vmw_crtc_state *vcs;
+
+	if (WARN_ON(!crtc->state))
+		return NULL;
+
+	vcs = kmemdup(crtc->state, sizeof(*vcs), GFP_KERNEL);
+
+	if (!vcs)
+		return NULL;
+
+	state = &vcs->base;
+
+	__drm_atomic_helper_crtc_duplicate_state(crtc, state);
+
+	return state;
+}
+
+
+/**
+ * vmw_du_crtc_reset - creates a blank vmw crtc state
+ * @crtc: DRM crtc
+ *
+ * Resets the atomic state for @crtc by freeing the state pointer (which
+ * might be NULL, e.g. at driver load time) and allocating a new empty state
+ * object.
+ */
+void vmw_du_crtc_reset(struct drm_crtc *crtc)
+{
+	struct vmw_crtc_state *vcs;
+
+
+	if (crtc->state) {
+		__drm_atomic_helper_crtc_destroy_state(crtc->state);
+
+		kfree(vmw_crtc_state_to_vcs(crtc->state));
+	}
+
+	vcs = kzalloc(sizeof(*vcs), GFP_KERNEL);
+
+	if (!vcs) {
+		DRM_ERROR("Cannot allocate vmw_crtc_state\n");
+		return;
+	}
+
+	crtc->state = &vcs->base;
+	crtc->state->crtc = crtc;
+}
+
+
+/**
+ * vmw_du_crtc_destroy_state - destroy crtc state
+ * @crtc: DRM crtc
+ * @state: state object to destroy
+ *
+ * Destroys the crtc state (both common and vmw-specific) for the
+ * specified plane.
+ */
+void
+vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
+			  struct drm_crtc_state *state)
+{
+	drm_atomic_helper_crtc_destroy_state(crtc, state);
+}
+
+
 /*
  * Generic framebuffer code
  */
@@ -1600,6 +1680,7 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
 }
 
 
+
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv)
 {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index e400bfb..370f75c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -139,6 +139,19 @@ static const uint32_t vmw_cursor_plane_formats[] = {
 	DRM_FORMAT_ARGB8888,
 };
 
+
+#define vmw_crtc_state_to_vcs(x) container_of(x, struct vmw_crtc_state, base)
+
+
+/**
+ * Derived class for crtc state object
+ *
+ * @base DRM crtc object
+ */
+struct vmw_crtc_state {
+	struct drm_crtc_state base;
+};
+
 /**
  * Base class display unit.
  *
@@ -205,6 +218,9 @@ int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
 			    uint32_t handle, uint32_t width, uint32_t height,
 			    int32_t hot_x, int32_t hot_y);
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
+int vmw_du_connector_set_property(struct drm_connector *connector,
+				  struct drm_property *property,
+				  uint64_t val);
 int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
 void vmw_du_connector_save(struct drm_connector *connector);
 void vmw_du_connector_restore(struct drm_connector *connector);
@@ -212,9 +228,6 @@ enum drm_connector_status
 vmw_du_connector_detect(struct drm_connector *connector, bool force);
 int vmw_du_connector_fill_modes(struct drm_connector *connector,
 				uint32_t max_width, uint32_t max_height);
-int vmw_du_connector_set_property(struct drm_connector *connector,
-				  struct drm_property *property,
-				  uint64_t val);
 int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
 			 struct vmw_framebuffer *framebuffer,
 			 const struct drm_clip_rect *clips,
@@ -285,6 +298,10 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
 			       uint32_t src_x, uint32_t src_y,
 			       uint32_t src_w, uint32_t src_h);
 
+void vmw_du_crtc_reset(struct drm_crtc *crtc);
+struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
+void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
+				struct drm_crtc_state *state);
 
 /*
  * Legacy display unit functions - vmwgfx_ldu.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 3efcbe5..3ee33f0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -280,6 +280,9 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_ldu_crtc_destroy,
+	.reset = vmw_du_crtc_reset,
+	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
+	.atomic_destroy_state = vmw_du_crtc_destroy_state,
 	.set_config = vmw_ldu_crtc_set_config,
 };
 
@@ -355,6 +358,11 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	ldu->base.pref_width = dev_priv->initial_width;
 	ldu->base.pref_height = dev_priv->initial_height;
 	ldu->base.pref_mode = NULL;
+
+	/*
+	 * Remove this after enabling atomic because property values can
+	 * only exist in a state object
+	 */
 	ldu->base.is_implicit = true;
 
 	/* Initialize primary plane */
@@ -405,6 +413,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_encoder;
 	}
 
+	/* FIXME: Turn on after plane/connector states are implemented. */
+	/* vmw_du_crtc_reset(crtc); */
 	ret = drm_crtc_init_with_planes(dev, crtc, &ldu->base.primary,
 					&ldu->base.cursor,
 					&vmw_legacy_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 8ffccb8..033e17b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -461,6 +461,9 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_sou_crtc_destroy,
+	.reset = vmw_du_crtc_reset,
+	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
+	.atomic_destroy_state = vmw_du_crtc_destroy_state,
 	.set_config = vmw_sou_crtc_set_config,
 	.page_flip = vmw_sou_crtc_page_flip,
 };
@@ -535,6 +538,11 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	sou->base.pref_width = dev_priv->initial_width;
 	sou->base.pref_height = dev_priv->initial_height;
 	sou->base.pref_mode = NULL;
+
+	/*
+	 * Remove this after enabling atomic because property values can
+	 * only exist in a state object
+	 */
 	sou->base.is_implicit = false;
 
 	/* Initialize primary plane */
@@ -586,6 +594,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_encoder;
 	}
 
+	/* FIXME: Turn on after plane/connector states are implemented. */
+	/* vmw_du_crtc_reset(crtc); */
 	ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
 					&sou->base.cursor,
 					&vmw_screen_object_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 4d9dd1b..3b8fafe 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1017,6 +1017,9 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
 static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_stdu_crtc_destroy,
+	.reset = vmw_du_crtc_reset,
+	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
+	.atomic_destroy_state = vmw_du_crtc_destroy_state,
 	.set_config = vmw_stdu_crtc_set_config,
 	.page_flip = vmw_stdu_crtc_page_flip,
 };
@@ -1131,6 +1134,11 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 	stdu->base.pref_active = (unit == 0);
 	stdu->base.pref_width  = dev_priv->initial_width;
 	stdu->base.pref_height = dev_priv->initial_height;
+
+	/*
+	 * Remove this after enabling atomic because property values can
+	 * only exist in a state object
+	 */
 	stdu->base.is_implicit = false;
 
 	/* Initialize primary plane */
@@ -1181,6 +1189,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_encoder;
 	}
 
+	/* FIXME: Turn on after plane/connector states are implemented. */
+	/* vmw_du_crtc_reset(crtc); */
 	ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
 					&stdu->base.cursor,
 					&vmw_stdu_crtc_funcs, NULL);
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 03/11] drm/vmwgfx: Plane atomic state
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
  2017-03-27 22:00 ` [PATCH 01/11] drm/vmwgfx: Add universal plane support Sinclair Yeh
  2017-03-27 22:00 ` [PATCH 02/11] drm/vmwgfx: CRTC atomic state Sinclair Yeh
@ 2017-03-27 22:00 ` Sinclair Yeh
  2017-03-28  7:33   ` Daniel Vetter
  2017-03-27 22:00 ` [PATCH 04/11] drm/vmwgfx: Connector " Sinclair Yeh
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Add plane state handling functions.

We have to keep track of a few plane states so we cannot use the
DRM helper for this.

Created vmw_plane_state along with functions to reset, duplicate,
and destroty it.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 99 ++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  | 24 +++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 13 +++++
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 13 +++++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 10 ++++
 5 files changed, 159 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 18bd8dc..d2171d9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -35,6 +35,15 @@
 
 void vmw_du_cleanup(struct vmw_display_unit *du)
 {
+	if (du->cursor.state && du->cursor.state->fb) {
+		/*
+		 * On a layout change, the user mode doesn't call
+		 * drm_mode_cursor_ioctl() to release the cursor, so
+		 * we need to manualy release a reference of it.
+		 */
+		drm_framebuffer_unreference(du->cursor.state->fb);
+	}
+
 	drm_plane_cleanup(&du->primary);
 	drm_plane_cleanup(&du->cursor);
 
@@ -468,6 +477,96 @@ vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
 }
 
 
+/**
+ * vmw_du_plane_duplicate_state - duplicate plane state
+ * @plane: drm plane
+ *
+ * Allocates and returns a copy of the plane state (both common and
+ * vmw-specific) for the specified plane.
+ *
+ * Returns: The newly allocated plane state, or NULL on failure.
+ */
+struct drm_plane_state *
+vmw_du_plane_duplicate_state(struct drm_plane *plane)
+{
+	struct drm_plane_state *state;
+	struct vmw_plane_state *vps;
+
+	vps = kmemdup(plane->state, sizeof(*vps), GFP_KERNEL);
+
+	if (!vps)
+		return NULL;
+
+	vps->pinned = 0;
+
+	/* Each ref counted resource needs to be acquired again */
+	if (vps->surf)
+		(void) vmw_surface_reference(vps->surf);
+
+	if (vps->dmabuf)
+		(void) vmw_dmabuf_reference(vps->dmabuf);
+
+	state = &vps->base;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, state);
+
+	return state;
+}
+
+
+/**
+ * vmw_du_plane_reset - creates a blank vmw plane state
+ * @plane: drm plane
+ *
+ * Resets the atomic state for @plane by freeing the state pointer (which might
+ * be NULL, e.g. at driver load time) and allocating a new empty state object.
+ */
+void vmw_du_plane_reset(struct drm_plane *plane)
+{
+	struct vmw_plane_state *vps;
+
+
+	if (plane->state)
+		vmw_du_plane_destroy_state(plane, plane->state);
+
+	vps = kzalloc(sizeof(*vps), GFP_KERNEL);
+
+	if (!vps) {
+		DRM_ERROR("Cannot allocate vmw_plane_state\n");
+		return;
+	}
+
+	plane->state = &vps->base;
+	plane->state->plane = plane;
+	plane->state->rotation = DRM_ROTATE_0;
+}
+
+
+/**
+ * vmw_du_plane_destroy_state - destroy plane state
+ * @plane: DRM plane
+ * @state: state object to destroy
+ *
+ * Destroys the plane state (both common and vmw-specific) for the
+ * specified plane.
+ */
+void
+vmw_du_plane_destroy_state(struct drm_plane *plane,
+			   struct drm_plane_state *state)
+{
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
+
+
+	if (vps->surf)
+		vmw_surface_unreference(&vps->surf);
+
+	if (vps->dmabuf)
+		vmw_dmabuf_unreference(&vps->dmabuf);
+
+	drm_atomic_helper_plane_destroy_state(plane, state);
+}
+
+
 /*
  * Generic framebuffer code
  */
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 370f75c..5602c24 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -141,6 +141,7 @@ static const uint32_t vmw_cursor_plane_formats[] = {
 
 
 #define vmw_crtc_state_to_vcs(x) container_of(x, struct vmw_crtc_state, base)
+#define vmw_plane_state_to_vps(x) container_of(x, struct vmw_plane_state, base)
 
 
 /**
@@ -153,6 +154,25 @@ struct vmw_crtc_state {
 };
 
 /**
+ * Derived class for plane state object
+ *
+ * @base DRM plane object
+ * @surf Display surface for STDU
+ * @dmabuf display dmabuf for SOU
+ * @content_fb_type Used by STDU.
+ * @pinned pin count for STDU display surface
+ */
+struct vmw_plane_state {
+	struct drm_plane_state base;
+	struct vmw_surface *surf;
+	struct vmw_dma_buffer *dmabuf;
+
+	int content_fb_type;
+
+	int pinned;
+};
+
+/**
  * Base class display unit.
  *
  * Since the SVGA hw doesn't have a concept of a crtc, encoder or connector
@@ -298,6 +318,10 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
 			       uint32_t src_x, uint32_t src_y,
 			       uint32_t src_w, uint32_t src_h);
 
+void vmw_du_plane_reset(struct drm_plane *plane);
+struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
+void vmw_du_plane_destroy_state(struct drm_plane *plane,
+				struct drm_plane_state *state);
 void vmw_du_crtc_reset(struct drm_crtc *crtc);
 struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
 void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 3ee33f0..36cd1fe 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -325,12 +325,18 @@ static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
 	.update_plane = drm_primary_helper_update,
 	.disable_plane = drm_primary_helper_disable,
 	.destroy = vmw_du_primary_plane_destroy,
+	.reset = vmw_du_plane_reset,
+	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
+	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
 static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
 	.update_plane = vmw_du_cursor_plane_update,
 	.disable_plane = vmw_du_cursor_plane_disable,
 	.destroy = vmw_du_cursor_plane_destroy,
+	.reset = vmw_du_plane_reset,
+	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
+	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
 
@@ -340,6 +346,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
+	struct drm_plane *primary, *cursor;
 	struct drm_crtc *crtc;
 	int ret;
 
@@ -351,6 +358,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	crtc = &ldu->base.crtc;
 	encoder = &ldu->base.encoder;
 	connector = &ldu->base.connector;
+	primary = &ldu->base.primary;
+	cursor = &ldu->base.cursor;
 
 	INIT_LIST_HEAD(&ldu->active);
 
@@ -366,6 +375,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	ldu->base.is_implicit = true;
 
 	/* Initialize primary plane */
+	vmw_du_plane_reset(primary);
+
 	ret = drm_universal_plane_init(dev, &ldu->base.primary,
 				       0, &vmw_ldu_plane_funcs,
 				       vmw_primary_plane_formats,
@@ -377,6 +388,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	}
 
 	/* Initialize cursor plane */
+	vmw_du_plane_reset(cursor);
+
 	ret = drm_universal_plane_init(dev, &ldu->base.cursor,
 			0, &vmw_ldu_cursor_funcs,
 			vmw_cursor_plane_formats,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 033e17b..cfba59a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -506,12 +506,18 @@ static const struct drm_plane_funcs vmw_sou_plane_funcs = {
 	.update_plane = drm_primary_helper_update,
 	.disable_plane = drm_primary_helper_disable,
 	.destroy = vmw_du_primary_plane_destroy,
+	.reset = vmw_du_plane_reset,
+	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
+	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
 static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
 	.update_plane = vmw_du_cursor_plane_update,
 	.disable_plane = vmw_du_cursor_plane_disable,
 	.destroy = vmw_du_cursor_plane_destroy,
+	.reset = vmw_du_plane_reset,
+	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
+	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
 
@@ -521,6 +527,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_connector *connector;
 	struct drm_encoder *encoder;
+	struct drm_plane *primary, *cursor;
 	struct drm_crtc *crtc;
 	int ret;
 
@@ -532,6 +539,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	crtc = &sou->base.crtc;
 	encoder = &sou->base.encoder;
 	connector = &sou->base.connector;
+	primary = &sou->base.primary;
+	cursor = &sou->base.cursor;
 
 	sou->base.active_implicit = false;
 	sou->base.pref_active = (unit == 0);
@@ -546,6 +555,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	sou->base.is_implicit = false;
 
 	/* Initialize primary plane */
+	vmw_du_plane_reset(primary);
+
 	ret = drm_universal_plane_init(dev, &sou->base.primary,
 				       0, &vmw_sou_plane_funcs,
 				       vmw_primary_plane_formats,
@@ -557,6 +568,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	}
 
 	/* Initialize cursor plane */
+	vmw_du_plane_reset(cursor);
+
 	ret = drm_universal_plane_init(dev, &sou->base.cursor,
 			0, &vmw_sou_cursor_funcs,
 			vmw_cursor_plane_formats,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 3b8fafe..2a0f550 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1090,12 +1090,18 @@ static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
 	.update_plane = drm_primary_helper_update,
 	.disable_plane = drm_primary_helper_disable,
 	.destroy = vmw_du_primary_plane_destroy,
+	.reset = vmw_du_plane_reset,
+	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
+	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
 static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
 	.update_plane = vmw_du_cursor_plane_update,
 	.disable_plane = vmw_du_cursor_plane_disable,
 	.destroy = vmw_du_cursor_plane_destroy,
+	.reset = vmw_du_plane_reset,
+	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
+	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
 
@@ -1142,6 +1148,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 	stdu->base.is_implicit = false;
 
 	/* Initialize primary plane */
+	vmw_du_plane_reset(primary);
+
 	ret = drm_universal_plane_init(dev, primary,
 				       0, &vmw_stdu_plane_funcs,
 				       vmw_primary_plane_formats,
@@ -1153,6 +1161,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 	}
 
 	/* Initialize cursor plane */
+	vmw_du_plane_reset(cursor);
+
 	ret = drm_universal_plane_init(dev, cursor,
 			0, &vmw_stdu_cursor_funcs,
 			vmw_cursor_plane_formats,
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 04/11] drm/vmwgfx: Connector atomic state
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (2 preceding siblings ...)
  2017-03-27 22:00 ` [PATCH 03/11] drm/vmwgfx: Plane " Sinclair Yeh
@ 2017-03-27 22:00 ` Sinclair Yeh
  2017-03-27 22:00 ` [PATCH 05/11] drm/vmwgfx: Add and connect CRTC helper functions Sinclair Yeh
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Add connector handling functions. Start tracking is_implicity in
the connector state.  Eventually, this field should be tracked
exclusively in a connector state.

Now that plane and connector states have been created, we can also
activate the code that use CRTC state.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 139 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  32 +++++++-
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  13 +++-
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |  13 +++-
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  14 +++-
 5 files changed, 204 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index d2171d9..a8e0909 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -567,6 +567,81 @@ vmw_du_plane_destroy_state(struct drm_plane *plane,
 }
 
 
+/**
+ * vmw_du_connector_duplicate_state - duplicate connector state
+ * @connector: DRM connector
+ *
+ * Allocates and returns a copy of the connector state (both common and
+ * vmw-specific) for the specified connector.
+ *
+ * Returns: The newly allocated connector state, or NULL on failure.
+ */
+struct drm_connector_state *
+vmw_du_connector_duplicate_state(struct drm_connector *connector)
+{
+	struct drm_connector_state *state;
+	struct vmw_connector_state *vcs;
+
+	if (WARN_ON(!connector->state))
+		return NULL;
+
+	vcs = kmemdup(connector->state, sizeof(*vcs), GFP_KERNEL);
+
+	if (!vcs)
+		return NULL;
+
+	state = &vcs->base;
+
+	__drm_atomic_helper_connector_duplicate_state(connector, state);
+
+	return state;
+}
+
+
+/**
+ * vmw_du_connector_reset - creates a blank vmw connector state
+ * @connector: DRM connector
+ *
+ * Resets the atomic state for @connector by freeing the state pointer (which
+ * might be NULL, e.g. at driver load time) and allocating a new empty state
+ * object.
+ */
+void vmw_du_connector_reset(struct drm_connector *connector)
+{
+	struct vmw_connector_state *vcs;
+
+
+	if (connector->state) {
+		__drm_atomic_helper_connector_destroy_state(connector->state);
+
+		kfree(vmw_connector_state_to_vcs(connector->state));
+	}
+
+	vcs = kzalloc(sizeof(*vcs), GFP_KERNEL);
+
+	if (!vcs) {
+		DRM_ERROR("Cannot allocate vmw_connector_state\n");
+		return;
+	}
+
+	__drm_atomic_helper_connector_reset(connector, &vcs->base);
+}
+
+
+/**
+ * vmw_du_connector_destroy_state - destroy connector state
+ * @connector: DRM connector
+ * @state: state object to destroy
+ *
+ * Destroys the connector state (both common and vmw-specific) for the
+ * specified plane.
+ */
+void
+vmw_du_connector_destroy_state(struct drm_connector *connector,
+			  struct drm_connector_state *state)
+{
+	drm_atomic_helper_connector_destroy_state(connector, state);
+}
 /*
  * Generic framebuffer code
  */
@@ -1780,6 +1855,70 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
 
 
 
+/**
+ * vmw_du_connector_atomic_set_property - Atomic version of get property
+ *
+ * @crtc - crtc the property is associated with
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int
+vmw_du_connector_atomic_set_property(struct drm_connector *connector,
+				     struct drm_connector_state *state,
+				     struct drm_property *property,
+				     uint64_t val)
+{
+	struct vmw_private *dev_priv = vmw_priv(connector->dev);
+	struct vmw_connector_state *vcs = vmw_connector_state_to_vcs(state);
+	struct vmw_display_unit *du = vmw_connector_to_du(connector);
+
+
+	if (property == dev_priv->implicit_placement_property) {
+		vcs->is_implicit = val;
+
+		/*
+		 * We should really be doing a drm_atomic_commit() to
+		 * commit the new state, but since this doesn't cause
+		 * an immedate state change, this is probably ok
+		 */
+		du->is_implicit = vcs->is_implicit;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+/**
+ * vmw_du_connector_atomic_get_property - Atomic version of get property
+ *
+ * @connector - connector the property is associated with
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int
+vmw_du_connector_atomic_get_property(struct drm_connector *connector,
+				     const struct drm_connector_state *state,
+				     struct drm_property *property,
+				     uint64_t *val)
+{
+	struct vmw_private *dev_priv = vmw_priv(connector->dev);
+	struct vmw_connector_state *vcs = vmw_connector_state_to_vcs(state);
+
+	if (property == dev_priv->implicit_placement_property)
+		*val = vcs->is_implicit;
+	else {
+		DRM_ERROR("Invalid Property %s\n", property->name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv)
 {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 5602c24..cc50bf3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -142,7 +142,8 @@ static const uint32_t vmw_cursor_plane_formats[] = {
 
 #define vmw_crtc_state_to_vcs(x) container_of(x, struct vmw_crtc_state, base)
 #define vmw_plane_state_to_vps(x) container_of(x, struct vmw_plane_state, base)
-
+#define vmw_connector_state_to_vcs(x) \
+		container_of(x, struct vmw_connector_state, base)
 
 /**
  * Derived class for crtc state object
@@ -172,6 +173,20 @@ struct vmw_plane_state {
 	int pinned;
 };
 
+
+/**
+ * Derived class for connector state object
+ *
+ * @base DRM connector object
+ * @is_implicit connector property
+ *
+ */
+struct vmw_connector_state {
+	struct drm_connector_state base;
+
+	bool is_implicit;
+};
+
 /**
  * Base class display unit.
  *
@@ -241,6 +256,15 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 int vmw_du_connector_set_property(struct drm_connector *connector,
 				  struct drm_property *property,
 				  uint64_t val);
+int vmw_du_connector_atomic_set_property(struct drm_connector *connector,
+					 struct drm_connector_state *state,
+					 struct drm_property *property,
+					 uint64_t val);
+int
+vmw_du_connector_atomic_get_property(struct drm_connector *connector,
+				     const struct drm_connector_state *state,
+				     struct drm_property *property,
+				     uint64_t *val);
 int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
 void vmw_du_connector_save(struct drm_connector *connector);
 void vmw_du_connector_restore(struct drm_connector *connector);
@@ -326,6 +350,12 @@ void vmw_du_crtc_reset(struct drm_crtc *crtc);
 struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
 void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
 				struct drm_crtc_state *state);
+void vmw_du_connector_reset(struct drm_connector *connector);
+struct drm_connector_state *
+vmw_du_connector_duplicate_state(struct drm_connector *connector);
+
+void vmw_du_connector_destroy_state(struct drm_connector *connector,
+				    struct drm_connector_state *state);
 
 /*
  * Legacy display unit functions - vmwgfx_ldu.c
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 36cd1fe..276c744 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -27,6 +27,8 @@
 
 #include "vmwgfx_kms.h"
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 
 
 #define vmw_crtc_to_ldu(x) \
@@ -315,6 +317,11 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
 	.fill_modes = vmw_du_connector_fill_modes,
 	.set_property = vmw_du_connector_set_property,
 	.destroy = vmw_ldu_connector_destroy,
+	.reset = vmw_du_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.atomic_set_property = vmw_du_connector_atomic_set_property,
+	.atomic_get_property = vmw_du_connector_atomic_get_property,
 };
 
 /*
@@ -408,6 +415,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 	connector->status = vmw_du_connector_detect(connector, true);
+	vmw_connector_state_to_vcs(connector->state)->is_implicit = true;
+
 
 	ret = drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
 			       DRM_MODE_ENCODER_VIRTUAL, NULL);
@@ -426,8 +435,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_encoder;
 	}
 
-	/* FIXME: Turn on after plane/connector states are implemented. */
-	/* vmw_du_crtc_reset(crtc); */
+
+	vmw_du_crtc_reset(crtc);
 	ret = drm_crtc_init_with_planes(dev, crtc, &ldu->base.primary,
 					&ldu->base.cursor,
 					&vmw_legacy_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index cfba59a..36d42f5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -27,6 +27,8 @@
 
 #include "vmwgfx_kms.h"
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
 
 
 #define vmw_crtc_to_sou(x) \
@@ -496,6 +498,11 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
 	.fill_modes = vmw_du_connector_fill_modes,
 	.set_property = vmw_du_connector_set_property,
 	.destroy = vmw_sou_connector_destroy,
+	.reset = vmw_du_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.atomic_set_property = vmw_du_connector_atomic_set_property,
+	.atomic_get_property = vmw_du_connector_atomic_get_property,
 };
 
 /*
@@ -589,6 +596,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	}
 
 	connector->status = vmw_du_connector_detect(connector, true);
+	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
+
 
 	ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
 			       DRM_MODE_ENCODER_VIRTUAL, NULL);
@@ -607,8 +616,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_encoder;
 	}
 
-	/* FIXME: Turn on after plane/connector states are implemented. */
-	/* vmw_du_crtc_reset(crtc); */
+
+	vmw_du_crtc_reset(crtc);
 	ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
 					&sou->base.cursor,
 					&vmw_screen_object_crtc_funcs, NULL);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 2a0f550..b1fae49 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -28,6 +28,9 @@
 #include "vmwgfx_kms.h"
 #include "device_include/svga3d_surfacedefs.h"
 #include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+
 
 #define vmw_crtc_to_stdu(x) \
 	container_of(x, struct vmw_screen_target_display_unit, base.crtc)
@@ -1078,6 +1081,11 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 	.fill_modes = vmw_du_connector_fill_modes,
 	.set_property = vmw_du_connector_set_property,
 	.destroy = vmw_stdu_connector_destroy,
+	.reset = vmw_du_connector_reset,
+	.atomic_duplicate_state = vmw_du_connector_duplicate_state,
+	.atomic_destroy_state = vmw_du_connector_destroy_state,
+	.atomic_set_property = vmw_du_connector_atomic_set_property,
+	.atomic_get_property = vmw_du_connector_atomic_get_property,
 };
 
 
@@ -1174,6 +1182,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	vmw_du_connector_reset(connector);
+
 	ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
 				 DRM_MODE_CONNECTOR_VIRTUAL);
 	if (ret) {
@@ -1181,6 +1191,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 	connector->status = vmw_du_connector_detect(connector, false);
+	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
 
 	ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
 			       DRM_MODE_ENCODER_VIRTUAL, NULL);
@@ -1199,8 +1210,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_encoder;
 	}
 
-	/* FIXME: Turn on after plane/connector states are implemented. */
-	/* vmw_du_crtc_reset(crtc); */
+	vmw_du_crtc_reset(crtc);
 	ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
 					&stdu->base.cursor,
 					&vmw_stdu_crtc_funcs, NULL);
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 05/11] drm/vmwgfx: Add and connect CRTC helper functions
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (3 preceding siblings ...)
  2017-03-27 22:00 ` [PATCH 04/11] drm/vmwgfx: Connector " Sinclair Yeh
@ 2017-03-27 22:00 ` Sinclair Yeh
  2017-03-28  7:56   ` Daniel Vetter
  2017-03-27 22:00 ` [PATCH 06/11] drm/vmwgfx: Add and connect plane " Sinclair Yeh
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Atomic mode set requires us to refactor existing vmw_stdu_crtc_set_config
code into sections that check the validity of the new mode, and sections
that actually program the hardware state.

vmw_du_crtc_atomic_check() takes CRTC-related checking code.  In a later
patch, vmw_du_primary_plane_atomic_check() will take framebuffer-related
checking code.

These helpers won't be called until we flip on the atomic support
flag or set drm_crtc_funcs->set_config to using the atomic
helper.

v2:
* The state->num_connector is actually the total number of potential
  connectors, not just the one associated with the display unit.
  The proper one to check is ->connector_mask.

* Add the check to only allow plane state to be the same as crtc state
  (Thanks to mlankhorst)

* Make sure to turn on SVGA mode before using VRAM.  SVGA mode is
  disabled in master_drop if dbdev is not running.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  48 ++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   9 +++
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  79 +++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 119 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 117 ++++++++++++++++++++++++++++++++++
 5 files changed, 372 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index a8e0909..6f0f160 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -399,6 +399,54 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
 }
 
 
+int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
+			     struct drm_crtc_state *new_state)
+{
+	struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
+	int connector_mask = 1 << drm_connector_index(&du->connector);
+	bool has_primary = new_state->plane_mask &
+			   BIT(drm_plane_index(crtc->primary));
+
+	/* We always want to have an active plane with an active CRTC */
+	if (has_primary != new_state->enable)
+		return -EINVAL;
+
+
+	if (new_state->connector_mask != connector_mask &&
+	    new_state->connector_mask != 0) {
+		DRM_ERROR("Invalid connectors configuration\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+
+void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
+			      struct drm_crtc_state *old_crtc_state)
+{
+}
+
+
+void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
+			      struct drm_crtc_state *old_crtc_state)
+{
+	struct drm_pending_vblank_event *event = crtc->state->event;
+
+	if (event) {
+		crtc->state->event = NULL;
+
+		spin_lock_irq(&crtc->dev->event_lock);
+		if (drm_crtc_vblank_get(crtc) == 0)
+			drm_crtc_arm_vblank_event(crtc, event);
+		else
+			drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+
+}
+
+
 /**
  * vmw_du_crtc_duplicate_state - duplicate crtc state
  * @crtc: DRM crtc
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index cc50bf3..f711b5d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -161,6 +161,7 @@ struct vmw_crtc_state {
  * @surf Display surface for STDU
  * @dmabuf display dmabuf for SOU
  * @content_fb_type Used by STDU.
+ * @dmabuf_size Size of the dmabuf, used by Screen Object Display Unit
  * @pinned pin count for STDU display surface
  */
 struct vmw_plane_state {
@@ -169,6 +170,7 @@ struct vmw_plane_state {
 	struct vmw_dma_buffer *dmabuf;
 
 	int content_fb_type;
+	unsigned long dmabuf_size;
 
 	int pinned;
 };
@@ -342,10 +344,17 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
 			       uint32_t src_x, uint32_t src_y,
 			       uint32_t src_w, uint32_t src_h);
 
+/* Atomic Helpers */
 void vmw_du_plane_reset(struct drm_plane *plane);
 struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
 void vmw_du_plane_destroy_state(struct drm_plane *plane,
 				struct drm_plane_state *state);
+int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
+			     struct drm_crtc_state *state);
+void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
+			      struct drm_crtc_state *old_crtc_state);
+void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
+			      struct drm_crtc_state *old_crtc_state);
 void vmw_du_crtc_reset(struct drm_crtc *crtc);
 struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
 void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 276c744..d547e80 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -167,6 +167,7 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
 	if (vfb != ld->fb) {
 		if (ld->fb && ld->fb->unpin)
 			ld->fb->unpin(ld->fb);
+		vmw_svga_enable(vmw_priv);
 		if (vfb->pin)
 			vfb->pin(vfb);
 		ld->fb = vfb;
@@ -190,6 +191,68 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
 	return 0;
 }
 
+/**
+ * vmw_ldu_crtc_mode_set_nofb - Enable svga
+ *
+ * @crtc: CRTC associated with the new screen
+ *
+ * For LDU, just enable the svga
+ */
+static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+}
+
+/**
+ * vmw_ldu_crtc_helper_prepare - Noop
+ *
+ * @crtc: CRTC associated with the new screen
+ *
+ * Prepares the CRTC for a mode set, but we don't need to do anything here.
+ *
+ */
+static void vmw_ldu_crtc_helper_prepare(struct drm_crtc *crtc)
+{
+}
+
+/**
+ * vmw_ldu_crtc_helper_commit - Noop
+ *
+ * @crtc: CRTC associated with the new screen
+ *
+ * This is called after a mode set has been completed.  Here's
+ * usually a good place to call vmw_ldu_add_active/vmw_ldu_del_active
+ * but since for LDU the display plane is closely tied to the
+ * CRTC, it makes more sense to do those at plane update time.
+ */
+static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_legacy_display_unit *ldu;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+
+
+	ldu = vmw_crtc_to_ldu(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+	fb       = crtc->primary->fb;
+
+	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
+
+	if (vfb)
+		vmw_ldu_add_active(dev_priv, ldu, vfb);
+	else
+		vmw_ldu_del_active(dev_priv, ldu);
+}
+
+/**
+ * vmw_ldu_crtc_helper_disable - Turns off CRTC
+ *
+ * @crtc: CRTC to be turned off
+ */
+static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc)
+{
+}
+
 static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 {
 	struct vmw_private *dev_priv;
@@ -346,6 +409,20 @@ static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
 	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
+/*
+ * Atomic Helpers
+ */
+static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
+	.prepare = vmw_ldu_crtc_helper_prepare,
+	.commit = vmw_ldu_crtc_helper_commit,
+	.disable = vmw_ldu_crtc_helper_disable,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = vmw_ldu_crtc_mode_set_nofb,
+	.atomic_check = vmw_du_crtc_atomic_check,
+	.atomic_begin = vmw_du_crtc_atomic_begin,
+	.atomic_flush = vmw_du_crtc_atomic_flush,
+};
+
 
 static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 {
@@ -445,6 +522,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_unregister;
 	}
 
+	drm_crtc_helper_add(crtc, &vmw_ldu_crtc_helper_funcs);
+
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	drm_object_attach_property(&connector->base,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 36d42f5..662024c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -250,6 +250,109 @@ static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
 	return ret;
 }
 
+/**
+ * vmw_sou_crtc_mode_set_nofb - Create new screen
+ *
+ * @crtc: CRTC associated with the new screen
+ *
+ * This function creates/destroys a screen.  This function cannot fail, so if
+ * somehow we run into a failure, just do the best we can to get out.
+ */
+static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_object_unit *sou;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+	struct drm_plane_state *ps;
+	struct vmw_plane_state *vps;
+	int ret;
+
+
+	sou      = vmw_crtc_to_sou(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+	ps       = crtc->primary->state;
+	fb       = ps->fb;
+	vps      = vmw_plane_state_to_vps(ps);
+
+	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
+
+	if (sou->defined) {
+		ret = vmw_sou_fifo_destroy(dev_priv, sou);
+		if (ret) {
+			DRM_ERROR("Failed to destroy Screen Object\n");
+			return;
+		}
+	}
+
+	if (vfb) {
+		sou->buffer = vps->dmabuf;
+		sou->buffer_size = vps->dmabuf_size;
+
+		ret = vmw_sou_fifo_create(dev_priv, sou, crtc->x, crtc->y,
+					  &crtc->mode);
+		if (ret)
+			DRM_ERROR("Failed to define Screen Object %dx%d\n",
+				  crtc->x, crtc->y);
+
+		vmw_kms_add_active(dev_priv, &sou->base, vfb);
+	} else {
+		sou->buffer = NULL;
+		sou->buffer_size = 0;
+
+		vmw_kms_del_active(dev_priv, &sou->base);
+	}
+}
+
+/**
+ * vmw_sou_crtc_helper_prepare - Noop
+ *
+ * @crtc: CRTC associated with the new screen
+ *
+ * Prepares the CRTC for a mode set, but we don't need to do anything here.
+ */
+static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc)
+{
+}
+
+/**
+ * vmw_sou_crtc_helper_commit - Noop
+ *
+ * @crtc: CRTC associated with the new screen
+ *
+ * This is called after a mode set has been completed.
+ */
+static void vmw_sou_crtc_helper_commit(struct drm_crtc *crtc)
+{
+}
+
+/**
+ * vmw_sou_crtc_helper_disable - Turns off CRTC
+ *
+ * @crtc: CRTC to be turned off
+ */
+static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_object_unit *sou;
+	int ret;
+
+
+	if (!crtc) {
+		DRM_ERROR("CRTC is NULL\n");
+		return;
+	}
+
+	sou = vmw_crtc_to_sou(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (sou->defined) {
+		ret = vmw_sou_fifo_destroy(dev_priv, sou);
+		if (ret)
+			DRM_ERROR("Failed to destroy Screen Object\n");
+	}
+}
+
 static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
 {
 	struct vmw_private *dev_priv;
@@ -527,6 +630,20 @@ static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
 	.atomic_destroy_state = vmw_du_plane_destroy_state,
 };
 
+/*
+ * Atomic Helpers
+ */
+static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
+	.prepare = vmw_sou_crtc_helper_prepare,
+	.commit = vmw_sou_crtc_helper_commit,
+	.disable = vmw_sou_crtc_helper_disable,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = vmw_sou_crtc_mode_set_nofb,
+	.atomic_check = vmw_du_crtc_atomic_check,
+	.atomic_begin = vmw_du_crtc_atomic_begin,
+	.atomic_flush = vmw_du_crtc_atomic_flush,
+};
+
 
 static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 {
@@ -626,6 +743,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_unregister;
 	}
 
+	drm_crtc_helper_add(crtc, &vmw_sou_crtc_helper_funcs);
+
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	drm_object_attach_property(&connector->base,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index b1fae49..6e3cfad 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -500,6 +500,106 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
 	return ret;
 }
 
+
+/**
+ * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
+ *
+ * @crtc: CRTC associated with the screen target
+ *
+ * This function defines/destroys a screen target
+ *
+ */
+static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_target_display_unit *stdu;
+	int ret;
+
+
+	stdu     = vmw_crtc_to_stdu(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (stdu->defined) {
+		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
+		if (ret)
+			DRM_ERROR("Failed to blank CRTC\n");
+
+		(void) vmw_stdu_update_st(dev_priv, stdu);
+
+		ret = vmw_stdu_destroy_st(dev_priv, stdu);
+		if (ret)
+			DRM_ERROR("Failed to destroy Screen Target\n");
+
+		stdu->content_fb_type = SAME_AS_DISPLAY;
+	}
+
+	if (!crtc->state->enable)
+		return;
+
+	vmw_svga_enable(dev_priv);
+	ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, crtc->x, crtc->y);
+
+	if (ret)
+		DRM_ERROR("Failed to define Screen Target of size %dx%d\n",
+			  crtc->x, crtc->y);
+}
+
+
+static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc)
+{
+}
+
+
+static void vmw_stdu_crtc_helper_commit(struct drm_crtc *crtc)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_target_display_unit *stdu;
+	struct vmw_framebuffer *vfb;
+	struct drm_framebuffer *fb;
+
+
+	stdu     = vmw_crtc_to_stdu(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+	fb       = crtc->primary->fb;
+
+	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
+
+	if (vfb)
+		vmw_kms_add_active(dev_priv, &stdu->base, vfb);
+	else
+		vmw_kms_del_active(dev_priv, &stdu->base);
+}
+
+static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_target_display_unit *stdu;
+	int ret;
+
+
+	if (!crtc) {
+		DRM_ERROR("CRTC is NULL\n");
+		return;
+	}
+
+	stdu     = vmw_crtc_to_stdu(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+
+	if (stdu->defined) {
+		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
+		if (ret)
+			DRM_ERROR("Failed to blank CRTC\n");
+
+		(void) vmw_stdu_update_st(dev_priv, stdu);
+
+		ret = vmw_stdu_destroy_st(dev_priv, stdu);
+		if (ret)
+			DRM_ERROR("Failed to destroy Screen Target\n");
+
+		stdu->content_fb_type = SAME_AS_DISPLAY;
+	}
+}
+
 /**
  * vmw_stdu_crtc_set_config - Sets a mode
  *
@@ -1113,6 +1213,21 @@ static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
 };
 
 
+/*
+ * Atomic Helpers
+ */
+static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
+	.prepare = vmw_stdu_crtc_helper_prepare,
+	.commit = vmw_stdu_crtc_helper_commit,
+	.disable = vmw_stdu_crtc_helper_disable,
+	.mode_set = drm_helper_crtc_mode_set,
+	.mode_set_nofb = vmw_stdu_crtc_mode_set_nofb,
+	.atomic_check = vmw_du_crtc_atomic_check,
+	.atomic_begin = vmw_du_crtc_atomic_begin,
+	.atomic_flush = vmw_du_crtc_atomic_flush,
+};
+
+
 /**
  * vmw_stdu_init - Sets up a Screen Target Display Unit
  *
@@ -1219,6 +1334,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free_unregister;
 	}
 
+	drm_crtc_helper_add(crtc, &vmw_stdu_crtc_helper_funcs);
+
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	drm_object_attach_property(&connector->base,
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 06/11] drm/vmwgfx: Add and connect plane helper functions
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (4 preceding siblings ...)
  2017-03-27 22:00 ` [PATCH 05/11] drm/vmwgfx: Add and connect CRTC helper functions Sinclair Yeh
@ 2017-03-27 22:00 ` Sinclair Yeh
  2017-03-28  7:40   ` Daniel Vetter
  2017-03-27 22:01 ` [PATCH 07/11] drm/vmwgfx: Add and connect connector helper function Sinclair Yeh
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:00 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Refactor previous FB and cursor plane update code into their
atomic counterparts: check, update, prepare, cleanup, and disable.

These helpers won't be called until we flip on the atomic support
flag or set drm_crtc_funcs->set_config to using the atomic
helper.

v2:
* Removed unnecessary pinning of cursor surface
* Added a few function headers

v3:
* Set clip region equal to the destination region
* Fixed surface pinning policy
* Enable SVGA mode in vmw_sou_primary_plane_prepare_fb

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 256 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  15 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  66 ++++++++-
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 115 ++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 244 +++++++++++++++++++++++++++++++++
 5 files changed, 695 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 6f0f160..d00ff21 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -26,8 +26,10 @@
  **************************************************************************/
 
 #include "vmwgfx_kms.h"
+#include <drm/drm_plane_helper.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_rect.h>
 
 
 /* Might need a hrtimer here? */
@@ -399,6 +401,260 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
 }
 
 
+/**
+ * vmw_du_vps_unpin_surf - unpins resource associated with a framebuffer surface
+ *
+ * @vps: plane state associated with the display surface
+ * @unreference: true if we also want to unreference the display.
+ */
+void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps,
+			     bool unreference)
+{
+	if (vps->surf) {
+		if (vps->pinned) {
+			vmw_resource_unpin(&vps->surf->res);
+			vps->pinned--;
+		}
+
+		if (unreference) {
+			if (vps->pinned)
+				DRM_ERROR("Surface still pinned\n");
+			vmw_surface_unreference(&vps->surf);
+		}
+	}
+}
+
+
+/**
+ * vmw_du_plane_cleanup_fb - Unpins the cursor
+ *
+ * @plane:  display plane
+ * @old_state: Contains the FB to clean up
+ *
+ * Unpins the framebuffer surface
+ *
+ * Returns 0 on success
+ */
+void
+vmw_du_plane_cleanup_fb(struct drm_plane *plane,
+			struct drm_plane_state *old_state)
+{
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
+
+	vmw_du_plane_unpin_surf(vps, false);
+}
+
+
+/**
+ * vmw_du_cursor_plane_prepare_fb - Readies the cursor by referencing it
+ *
+ * @plane:  display plane
+ * @new_state: info on the new plane state, including the FB
+ *
+ * Returns 0 on success
+ */
+int
+vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
+			       struct drm_plane_state *new_state)
+{
+	struct drm_framebuffer *fb = new_state->fb;
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
+
+
+	if (vps->surf)
+		vmw_surface_unreference(&vps->surf);
+
+	if (vps->dmabuf)
+		vmw_dmabuf_unreference(&vps->dmabuf);
+
+	if (fb) {
+		if (vmw_framebuffer_to_vfb(fb)->dmabuf) {
+			vps->dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
+			vmw_dmabuf_reference(vps->dmabuf);
+		} else {
+			vps->surf = vmw_framebuffer_to_vfbs(fb)->surface;
+			vmw_surface_reference(vps->surf);
+		}
+	}
+
+	return 0;
+}
+
+
+void
+vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
+				   struct drm_plane_state *old_state)
+{
+	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+
+	drm_atomic_set_fb_for_plane(plane->state, NULL);
+	vmw_cursor_update_position(dev_priv, false, 0, 0);
+}
+
+
+void
+vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
+				  struct drm_plane_state *old_state)
+{
+	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
+	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(plane->state);
+	s32 hotspot_x, hotspot_y;
+	int ret = 0;
+
+
+	hotspot_x = du->hotspot_x;
+	hotspot_y = du->hotspot_y;
+	du->cursor_surface = vps->surf;
+	du->cursor_dmabuf = vps->dmabuf;
+
+	/* setup new image */
+	if (vps->surf) {
+		du->cursor_age = du->cursor_surface->snooper.age;
+
+		ret = vmw_cursor_update_image(dev_priv,
+					      vps->surf->snooper.image,
+					      64, 64, hotspot_x, hotspot_y);
+	} else if (vps->dmabuf) {
+		ret = vmw_cursor_update_dmabuf(dev_priv, vps->dmabuf,
+					       plane->state->crtc_w,
+					       plane->state->crtc_h,
+					       hotspot_x, hotspot_y);
+	} else {
+		vmw_cursor_update_position(dev_priv, false, 0, 0);
+		return;
+	}
+
+	if (!ret) {
+		du->cursor_x = plane->state->crtc_x + du->set_gui_x;
+		du->cursor_y = plane->state->crtc_y + du->set_gui_y;
+
+		vmw_cursor_update_position(dev_priv, true,
+					   du->cursor_x + hotspot_x,
+					   du->cursor_y + hotspot_y);
+	} else {
+		DRM_ERROR("Failed to update cursor image\n");
+	}
+}
+
+
+/**
+ * vmw_du_primary_plane_atomic_check - check if the new state is okay
+ *
+ * @plane: display plane
+ * @state: info on the new plane state, including the FB
+ *
+ * Check if the new state is settable given the current state.  Other
+ * than what the atomic helper checks, we care about crtc fitting
+ * the FB and maintaining one active framebuffer.
+ *
+ * Returns 0 on success
+ */
+int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
+				      struct drm_plane_state *state)
+{
+	struct drm_framebuffer *new_fb = state->fb;
+	bool visible;
+
+	struct drm_rect src = {
+		.x1 = state->src_x,
+		.y1 = state->src_y,
+		.x2 = state->src_x + state->src_w,
+		.y2 = state->src_y + state->src_h,
+	};
+	struct drm_rect dest = {
+		.x1 = state->crtc_x,
+		.y1 = state->crtc_y,
+		.x2 = state->crtc_x + state->crtc_w,
+		.y2 = state->crtc_y + state->crtc_h,
+	};
+	struct drm_rect clip = dest;
+	int ret;
+
+	ret = drm_plane_helper_check_update(plane, state->crtc, new_fb,
+					    &src, &dest, &clip,
+					    DRM_ROTATE_0,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    DRM_PLANE_HELPER_NO_SCALING,
+					    false, true, &visible);
+
+
+	if (!ret && new_fb) {
+		struct drm_crtc *crtc = state->crtc;
+		struct vmw_connector_state *vcs;
+		struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
+		struct vmw_private *dev_priv = vmw_priv(crtc->dev);
+		struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
+
+		vcs = vmw_connector_state_to_vcs(du->connector.state);
+
+		if ((dest.x2 > new_fb->width ||
+		     dest.y2 > new_fb->height)) {
+			DRM_ERROR("CRTC area outside of framebuffer\n");
+			return -EINVAL;
+		}
+
+		/* Only one active implicit framebuffer at a time. */
+		mutex_lock(&dev_priv->global_kms_state_mutex);
+		if (vcs->is_implicit && dev_priv->implicit_fb &&
+		    !(dev_priv->num_implicit == 1 && du->active_implicit)
+		    && dev_priv->implicit_fb != vfb) {
+			DRM_ERROR("Multiple implicit framebuffers "
+				  "not supported.\n");
+			ret = -EINVAL;
+		}
+		mutex_unlock(&dev_priv->global_kms_state_mutex);
+	}
+
+
+	return ret;
+}
+
+
+/**
+ * vmw_du_cursor_plane_atomic_check - check if the new state is okay
+ *
+ * @plane: cursor plane
+ * @state: info on the new plane state
+ *
+ * This is a chance to fail if the new cursor state does not fit
+ * our requirements.
+ *
+ * Returns 0 on success
+ */
+int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
+				     struct drm_plane_state *new_state)
+{
+	int ret = 0;
+	struct vmw_surface *surface = NULL;
+	struct drm_framebuffer *fb = new_state->fb;
+
+
+	/* Turning off */
+	if (!fb)
+		return ret;
+
+	/* A lot of the code assumes this */
+	if (new_state->crtc_w != 64 || new_state->crtc_h != 64) {
+		DRM_ERROR("Invalid cursor dimensions (%d, %d)\n",
+			  new_state->crtc_w, new_state->crtc_h);
+		ret = -EINVAL;
+	}
+
+	if (!vmw_framebuffer_to_vfb(fb)->dmabuf)
+		surface = vmw_framebuffer_to_vfbs(fb)->surface;
+
+	if (surface && !surface->snooper.image) {
+		DRM_ERROR("surface not suitable for cursor\n");
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+
 int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
 			     struct drm_crtc_state *new_state)
 {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index f711b5d..de6a0b6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -345,10 +345,25 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
 			       uint32_t src_w, uint32_t src_h);
 
 /* Atomic Helpers */
+int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
+				      struct drm_plane_state *state);
+int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
+				     struct drm_plane_state *state);
+void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
+				       struct drm_plane_state *old_state);
+void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
+					struct drm_plane_state *old_state);
+int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
+				   struct drm_plane_state *new_state);
+void vmw_du_plane_cleanup_fb(struct drm_plane *plane,
+			     struct drm_plane_state *old_state);
 void vmw_du_plane_reset(struct drm_plane *plane);
 struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
 void vmw_du_plane_destroy_state(struct drm_plane *plane,
 				struct drm_plane_state *state);
+void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps,
+			     bool unreference);
+
 int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
 			     struct drm_crtc_state *state);
 void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index d547e80..1d734de 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -234,7 +234,7 @@ static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
 
 	ldu = vmw_crtc_to_ldu(crtc);
 	dev_priv = vmw_priv(crtc->dev);
-	fb       = crtc->primary->fb;
+	fb       = crtc->primary->state->fb;
 
 	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
 
@@ -242,6 +242,8 @@ static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
 		vmw_ldu_add_active(dev_priv, ldu, vfb);
 	else
 		vmw_ldu_del_active(dev_priv, ldu);
+
+	vmw_ldu_commit_list(dev_priv);
 }
 
 /**
@@ -391,6 +393,46 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
  * Legacy Display Plane Functions
  */
 
+/**
+ * vmw_ldu_primary_plane_cleanup_fb - Unpin fb
+ *
+ * @plane:  display plane
+ * @old_state: Contains the FB to clean up
+ *
+ * Unpins the display surface
+ *
+ * Returns 0 on success
+ */
+static void
+vmw_ldu_primary_plane_cleanup_fb(struct drm_plane *plane,
+				 struct drm_plane_state *old_state)
+{
+}
+
+
+/**
+ * vmw_ldu_primary_plane_prepare_fb -
+ *
+ * @plane:  display plane
+ * @new_state: info on the new plane state, including the FB
+ *
+ * Returns 0 on success
+ */
+static int
+vmw_ldu_primary_plane_prepare_fb(struct drm_plane *plane,
+				 struct drm_plane_state *new_state)
+{
+	return 0;
+}
+
+
+static void
+vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
+				    struct drm_plane_state *old_state)
+{
+}
+
+
 static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
 	.update_plane = drm_primary_helper_update,
 	.disable_plane = drm_primary_helper_disable,
@@ -412,6 +454,22 @@ static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
 /*
  * Atomic Helpers
  */
+static const struct
+drm_plane_helper_funcs vmw_ldu_cursor_plane_helper_funcs = {
+	.atomic_check = vmw_du_cursor_plane_atomic_check,
+	.atomic_update = vmw_du_cursor_plane_atomic_update,
+	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
+	.cleanup_fb = vmw_du_plane_cleanup_fb,
+};
+
+static const struct
+drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = {
+	.atomic_check = vmw_du_primary_plane_atomic_check,
+	.atomic_update = vmw_ldu_primary_plane_atomic_update,
+	.prepare_fb = vmw_ldu_primary_plane_prepare_fb,
+	.cleanup_fb = vmw_ldu_primary_plane_cleanup_fb,
+};
+
 static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
 	.prepare = vmw_ldu_crtc_helper_prepare,
 	.commit = vmw_ldu_crtc_helper_commit,
@@ -471,6 +529,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_plane_helper_add(primary, &vmw_ldu_primary_plane_helper_funcs);
+
 	/* Initialize cursor plane */
 	vmw_du_plane_reset(cursor);
 
@@ -485,6 +545,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_plane_helper_add(cursor, &vmw_ldu_cursor_plane_helper_funcs);
+
+
+	vmw_du_connector_reset(connector);
 	ret = drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
 				 DRM_MODE_CONNECTOR_VIRTUAL);
 	if (ret) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index 662024c..eca055e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -612,6 +612,100 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
  * Screen Object Display Plane Functions
  */
 
+/**
+ * vmw_sou_primary_plane_cleanup_fb - Frees sou backing buffer
+ *
+ * @plane:  display plane
+ * @old_state: Contains the FB to clean up
+ *
+ * Unpins the display surface
+ *
+ * Returns 0 on success
+ */
+static void
+vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane,
+				 struct drm_plane_state *old_state)
+{
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
+
+	vmw_dmabuf_unreference(&vps->dmabuf);
+	vps->dmabuf_size = 0;
+
+	vmw_du_plane_cleanup_fb(plane, old_state);
+}
+
+
+/**
+ * vmw_sou_primary_plane_prepare_fb - allocate backing buffer
+ *
+ * @plane:  display plane
+ * @new_state: info on the new plane state, including the FB
+ *
+ * The SOU backing buffer is our equivalent of the display plane.
+ *
+ * Returns 0 on success
+ */
+static int
+vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane,
+				 struct drm_plane_state *new_state)
+{
+	struct drm_framebuffer *new_fb = new_state->fb;
+	struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc;
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
+	struct vmw_private *dev_priv;
+	size_t size;
+	int ret;
+
+
+	if (!new_fb) {
+		vmw_dmabuf_unreference(&vps->dmabuf);
+		vps->dmabuf_size = 0;
+
+		return 0;
+	}
+
+	size = new_state->crtc_w * new_state->crtc_h * 4;
+
+	if (vps->dmabuf) {
+		if (vps->dmabuf_size == size)
+			return 0;
+
+		vmw_dmabuf_unreference(&vps->dmabuf);
+		vps->dmabuf_size = 0;
+	}
+
+	vps->dmabuf = kzalloc(sizeof(*vps->dmabuf), GFP_KERNEL);
+	if (!vps->dmabuf)
+		return -ENOMEM;
+
+	dev_priv = vmw_priv(crtc->dev);
+	vmw_svga_enable(dev_priv);
+
+	/* After we have alloced the backing store might not be able to
+	 * resume the overlays, this is preferred to failing to alloc.
+	 */
+	vmw_overlay_pause_all(dev_priv);
+	ret = vmw_dmabuf_init(dev_priv, vps->dmabuf, size,
+			      &vmw_vram_ne_placement,
+			      false, &vmw_dmabuf_bo_free);
+	vmw_overlay_resume_all(dev_priv);
+
+	if (ret != 0)
+		vps->dmabuf = NULL; /* vmw_dmabuf_init frees on error */
+	else
+		vps->dmabuf_size = size;
+
+	return ret;
+}
+
+
+static void
+vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
+				    struct drm_plane_state *old_state)
+{
+}
+
+
 static const struct drm_plane_funcs vmw_sou_plane_funcs = {
 	.update_plane = drm_primary_helper_update,
 	.disable_plane = drm_primary_helper_disable,
@@ -633,6 +727,22 @@ static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
 /*
  * Atomic Helpers
  */
+static const struct
+drm_plane_helper_funcs vmw_sou_cursor_plane_helper_funcs = {
+	.atomic_check = vmw_du_cursor_plane_atomic_check,
+	.atomic_update = vmw_du_cursor_plane_atomic_update,
+	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
+	.cleanup_fb = vmw_du_plane_cleanup_fb,
+};
+
+static const struct
+drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = {
+	.atomic_check = vmw_du_primary_plane_atomic_check,
+	.atomic_update = vmw_sou_primary_plane_atomic_update,
+	.prepare_fb = vmw_sou_primary_plane_prepare_fb,
+	.cleanup_fb = vmw_sou_primary_plane_cleanup_fb,
+};
+
 static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
 	.prepare = vmw_sou_crtc_helper_prepare,
 	.commit = vmw_sou_crtc_helper_commit,
@@ -691,6 +801,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_plane_helper_add(primary, &vmw_sou_primary_plane_helper_funcs);
+
 	/* Initialize cursor plane */
 	vmw_du_plane_reset(cursor);
 
@@ -705,6 +817,9 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs);
+
+	vmw_du_connector_reset(connector);
 	ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
 				 DRM_MODE_CONNECTOR_VIRTUAL);
 	if (ret) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 6e3cfad..cce5e5b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1194,6 +1194,230 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
  * Screen Target Display Plane Functions
  *****************************************************************************/
 
+
+
+/**
+ * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface
+ *
+ * @plane:  display plane
+ * @old_state: Contains the FB to clean up
+ *
+ * Unpins the display surface
+ *
+ * Returns 0 on success
+ */
+static void
+vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
+				  struct drm_plane_state *old_state)
+{
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
+
+	if (vps->surf)
+		WARN_ON(!vps->pinned);
+
+	vmw_du_plane_cleanup_fb(plane, old_state);
+
+	vps->content_fb_type = SAME_AS_DISPLAY;
+}
+
+
+
+/**
+ * vmw_stdu_primary_plane_prepare_fb - Readies the display surface
+ *
+ * @plane:  display plane
+ * @new_state: info on the new plane state, including the FB
+ *
+ * This function allocates a new display surface if the content is
+ * backed by a DMA.  The display surface is pinned here, and it'll
+ * be unpinned in .cleanup_fb()
+ *
+ * Returns 0 on success
+ */
+static int
+vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
+				  struct drm_plane_state *new_state)
+{
+	struct drm_framebuffer *new_fb = new_state->fb;
+	struct vmw_framebuffer *vfb;
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
+	enum stdu_content_type new_content_type;
+	struct vmw_framebuffer_surface *new_vfbs;
+	struct drm_crtc *crtc = new_state->crtc;
+	uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h;
+	int ret;
+
+	/* No FB to prepare */
+	if (!new_fb) {
+		if (vps->surf) {
+			WARN_ON(vps->pinned != 0);
+			vmw_surface_unreference(&vps->surf);
+		}
+
+		return 0;
+	}
+
+	vfb = vmw_framebuffer_to_vfb(new_fb);
+	new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
+
+	if (new_vfbs && new_vfbs->surface->base_size.width == hdisplay &&
+	    new_vfbs->surface->base_size.height == vdisplay)
+		new_content_type = SAME_AS_DISPLAY;
+	else if (vfb->dmabuf)
+		new_content_type = SEPARATE_DMA;
+	else
+		new_content_type = SEPARATE_SURFACE;
+
+	if (new_content_type != SAME_AS_DISPLAY) {
+		struct vmw_surface content_srf;
+		struct drm_vmw_size display_base_size = {0};
+
+		display_base_size.width  = hdisplay;
+		display_base_size.height = vdisplay;
+		display_base_size.depth  = 1;
+
+		/*
+		 * If content buffer is a DMA buf, then we have to construct
+		 * surface info
+		 */
+		if (new_content_type == SEPARATE_DMA) {
+
+			switch (new_fb->format->cpp[0]*8) {
+			case 32:
+				content_srf.format = SVGA3D_X8R8G8B8;
+				break;
+
+			case 16:
+				content_srf.format = SVGA3D_R5G6B5;
+				break;
+
+			case 8:
+				content_srf.format = SVGA3D_P8;
+				break;
+
+			default:
+				DRM_ERROR("Invalid format\n");
+				return -EINVAL;
+			}
+
+			content_srf.flags             = 0;
+			content_srf.mip_levels[0]     = 1;
+			content_srf.multisample_count = 0;
+		} else {
+			content_srf = *new_vfbs->surface;
+		}
+
+		if (vps->surf) {
+			struct drm_vmw_size cur_base_size = vps->surf->base_size;
+
+			if (cur_base_size.width != display_base_size.width ||
+			    cur_base_size.height != display_base_size.height ||
+			    vps->surf->format != content_srf.format) {
+				WARN_ON(vps->pinned != 0);
+				vmw_surface_unreference(&vps->surf);
+			}
+
+		}
+
+		if (!vps->surf) {
+			ret = vmw_surface_gb_priv_define
+				(crtc->dev,
+				 /* Kernel visible only */
+				 0,
+				 content_srf.flags,
+				 content_srf.format,
+				 true,  /* a scanout buffer */
+				 content_srf.mip_levels[0],
+				 content_srf.multisample_count,
+				 0,
+				 display_base_size,
+				 &vps->surf);
+			if (ret != 0) {
+				DRM_ERROR("Couldn't allocate STDU surface.\n");
+				return ret;
+			}
+		}
+	} else {
+		/*
+		 * prepare_fb and clean_fb should only take care of pinning
+		 * and unpinning.  References are tracked by state objects.
+		 * The only time we add a reference in prepare_fb is if the
+		 * state object doesn't have a reference to begin with
+		 */
+		if (vps->surf) {
+			WARN_ON(vps->pinned != 0);
+			vmw_surface_unreference(&vps->surf);
+		}
+
+		vps->surf = vmw_surface_reference(new_vfbs->surface);
+	}
+
+	if (vps->surf) {
+
+		/* Pin new surface before flipping */
+		ret = vmw_resource_pin(&vps->surf->res, false);
+		if (ret)
+			goto out_srf_unref;
+
+		vps->pinned++;
+	}
+
+	vps->content_fb_type = new_content_type;
+	return 0;
+
+out_srf_unref:
+	vmw_surface_unreference(&vps->surf);
+	return ret;
+}
+
+
+
+/**
+ * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane
+ *
+ * @plane: display plane
+ * @old_state: Only used to get crtc info
+ *
+ * Formally update stdu->display_srf to the new plane, and bind the new
+ * plane STDU.  This function is called during the commit phase when
+ * all the preparation have been done and all the configurations have
+ * been checked.
+ */
+static void
+vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct vmw_private *dev_priv;
+	struct vmw_screen_target_display_unit *stdu;
+	struct vmw_plane_state *vps = vmw_plane_state_to_vps(plane->state);
+	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
+	int ret;
+
+	stdu     = vmw_crtc_to_stdu(crtc);
+	dev_priv = vmw_priv(crtc->dev);
+
+	stdu->display_srf = vps->surf;
+	stdu->content_fb_type = vps->content_fb_type;
+
+	if (!stdu->defined)
+		return;
+
+	if (plane->state->fb)
+		ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
+	else
+		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
+
+	/*
+	 * We cannot really fail this function, so if we do, then output an
+	 * error and quit
+	 */
+	if (ret)
+		DRM_ERROR("Failed to bind surface to STDU.\n");
+	else
+		crtc->primary->fb = plane->state->fb;
+}
+
+
 static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
 	.update_plane = drm_primary_helper_update,
 	.disable_plane = drm_primary_helper_disable,
@@ -1216,6 +1440,22 @@ static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
 /*
  * Atomic Helpers
  */
+static const struct
+drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = {
+	.atomic_check = vmw_du_cursor_plane_atomic_check,
+	.atomic_update = vmw_du_cursor_plane_atomic_update,
+	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
+	.cleanup_fb = vmw_du_plane_cleanup_fb,
+};
+
+static const struct
+drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
+	.atomic_check = vmw_du_primary_plane_atomic_check,
+	.atomic_update = vmw_stdu_primary_plane_atomic_update,
+	.prepare_fb = vmw_stdu_primary_plane_prepare_fb,
+	.cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
+};
+
 static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
 	.prepare = vmw_stdu_crtc_helper_prepare,
 	.commit = vmw_stdu_crtc_helper_commit,
@@ -1283,6 +1523,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs);
+
 	/* Initialize cursor plane */
 	vmw_du_plane_reset(cursor);
 
@@ -1297,6 +1539,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_plane_helper_add(cursor, &vmw_stdu_cursor_plane_helper_funcs);
+
 	vmw_du_connector_reset(connector);
 
 	ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 07/11] drm/vmwgfx: Add and connect connector helper function
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (5 preceding siblings ...)
  2017-03-27 22:00 ` [PATCH 06/11] drm/vmwgfx: Add and connect plane " Sinclair Yeh
@ 2017-03-27 22:01 ` Sinclair Yeh
  2017-03-28  7:41   ` Daniel Vetter
  2017-03-27 22:01 ` [PATCH 08/11] drm/vmwgfx: Add and connect atomic state object check/commit Sinclair Yeh
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:01 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Since the link between connector and encoder is always fixed in our case,
just return the one encoder.

These helpers won't be called until we flip on the atomic support
flag or set drm_crtc_funcs->set_config to using the atomic
helper.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 18 ++++++++++++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  2 ++
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  7 +++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |  9 +++++++++
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  8 ++++++++
 5 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index d00ff21..2250a34a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -2223,6 +2223,24 @@ vmw_du_connector_atomic_get_property(struct drm_connector *connector,
 }
 
 
+/**
+ * vmw_du_connector_best_encoder - there's only one
+ *
+ * @connector - connector the property is associated with
+ *
+ * In our case, there is only one encoder per connector
+ */
+struct drm_encoder *
+vmw_du_connector_best_encoder(struct drm_connector *connector)
+{
+	struct vmw_display_unit *du;
+
+	du = vmw_connector_to_du(connector);
+
+	return &du->encoder;
+}
+
+
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv)
 {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index de6a0b6..3251562 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -267,6 +267,8 @@ vmw_du_connector_atomic_get_property(struct drm_connector *connector,
 				     const struct drm_connector_state *state,
 				     struct drm_property *property,
 				     uint64_t *val);
+struct drm_encoder *
+vmw_du_connector_best_encoder(struct drm_connector *connector);
 int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
 void vmw_du_connector_save(struct drm_connector *connector);
 void vmw_du_connector_restore(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 1d734de..282a0ef 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -389,6 +389,11 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
 	.atomic_get_property = vmw_du_connector_atomic_get_property,
 };
 
+static const struct
+drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
+	.best_encoder = vmw_du_connector_best_encoder,
+};
+
 /*
  * Legacy Display Plane Functions
  */
@@ -555,6 +560,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 		DRM_ERROR("Failed to initialize connector\n");
 		goto err_free;
 	}
+
+	drm_connector_helper_add(connector, &vmw_ldu_connector_helper_funcs);
 	connector->status = vmw_du_connector_detect(connector, true);
 	vmw_connector_state_to_vcs(connector->state)->is_implicit = true;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index eca055e..e4154f1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -608,6 +608,14 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
 	.atomic_get_property = vmw_du_connector_atomic_get_property,
 };
 
+
+static const struct
+drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
+	.best_encoder = vmw_du_connector_best_encoder,
+};
+
+
+
 /*
  * Screen Object Display Plane Functions
  */
@@ -827,6 +835,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 		goto err_free;
 	}
 
+	drm_connector_helper_add(connector, &vmw_sou_connector_helper_funcs);
 	connector->status = vmw_du_connector_detect(connector, true);
 	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
 
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index cce5e5b..708d063 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1189,6 +1189,12 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
 };
 
 
+static const struct
+drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
+	.best_encoder = vmw_du_connector_best_encoder,
+};
+
+
 
 /******************************************************************************
  * Screen Target Display Plane Functions
@@ -1549,6 +1555,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 		DRM_ERROR("Failed to initialize connector\n");
 		goto err_free;
 	}
+
+	drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs);
 	connector->status = vmw_du_connector_detect(connector, false);
 	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
 
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 08/11] drm/vmwgfx: Add and connect atomic state object check/commit
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (6 preceding siblings ...)
  2017-03-27 22:01 ` [PATCH 07/11] drm/vmwgfx: Add and connect connector helper function Sinclair Yeh
@ 2017-03-27 22:01 ` Sinclair Yeh
  2017-03-28  7:45   ` Daniel Vetter
  2017-03-27 22:01 ` [PATCH 09/11] drm/vmwgfx: Fixes to vmwgfx_fb Sinclair Yeh
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:01 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

This connects the main state object check and commit function.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 66 +++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 2250a34a..6b593aaf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1581,8 +1581,74 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
 	return &vfb->base;
 }
 
+
+
+/**
+ * vmw_kms_atomic_check_modeset- validate state object for modeset changes
+ *
+ * @dev: DRM device
+ * @state: the driver state object
+ *
+ * This is a simple wrapper around drm_atomic_helper_check_modeset() for
+ * us to assign a value to mode->crtc_clock so that
+ * drm_calc_timestamping_constants() won't throw an error message
+ *
+ * RETURNS
+ * Zero for success or -errno
+ */
+int
+vmw_kms_atomic_check_modeset(struct drm_device *dev,
+			     struct drm_atomic_state *state)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_crtc *crtc;
+	int i, ret;
+
+
+	for_each_crtc_in_state(state, crtc, crtc_state, i) {
+		if (crtc_state->mode.crtc_clock == 0) {
+			/*
+			 * Our virtual device does not have a dot clock,
+			 * so use the logical clock value as the dot clock.
+			 */
+			crtc_state->mode.crtc_clock = crtc_state->mode.clock;
+		}
+	}
+
+	ret = drm_atomic_helper_check_modeset(dev, state);
+	if (ret)
+		return ret;
+
+	return drm_atomic_helper_check_planes(dev, state);
+}
+
+
+/**
+ * vmw_kms_atomic_commit - Perform an atomic state commit
+ *
+ * @dev: DRM device
+ * @state: the driver state object
+ * @nonblock: Whether nonblocking behaviour is requested
+ *
+ * This is a simple wrapper around drm_atomic_helper_commit() for
+ * us to clear the nonblocking value.
+ * Nonblocking commits should avoid waiting on GPU completion to return.
+ * That is always the case for us.
+ *
+ * RETURNS
+ * Zero for success or negative error code on failure.
+ */
+int vmw_kms_atomic_commit(struct drm_device *dev,
+			  struct drm_atomic_state *state,
+			  bool nonblock)
+{
+	return drm_atomic_helper_commit(dev, state, false);
+}
+
 static const struct drm_mode_config_funcs vmw_kms_funcs = {
 	.fb_create = vmw_kms_fb_create,
+	.atomic_check = vmw_kms_atomic_check_modeset,
+	.atomic_commit = vmw_kms_atomic_commit,
 };
 
 static int vmw_kms_generic_present(struct vmw_private *dev_priv,
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 09/11] drm/vmwgfx: Fixes to vmwgfx_fb
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (7 preceding siblings ...)
  2017-03-27 22:01 ` [PATCH 08/11] drm/vmwgfx: Add and connect atomic state object check/commit Sinclair Yeh
@ 2017-03-27 22:01 ` Sinclair Yeh
  2017-03-27 22:01 ` [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU Sinclair Yeh
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:01 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

1.  When unsetting a mode, num_connector should be set to zero
2.  The pixel_format field needs to be initialized as newer DRM internal
    functions checks this field
3.  Take the drm_modeset_lock_all() because vmw_fb_kms_detach() can
    change current mode

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index e9005b9..7d3d5e3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -434,7 +434,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par,
 		set.y = 0;
 		set.mode = NULL;
 		set.fb = NULL;
-		set.num_connectors = 1;
+		set.num_connectors = 0;
 		set.connectors = &par->con;
 		ret = drm_mode_set_config_internal(&set);
 		if (ret) {
@@ -822,7 +822,9 @@ int vmw_fb_off(struct vmw_private *vmw_priv)
 	flush_delayed_work(&par->local_work);
 
 	mutex_lock(&par->bo_mutex);
+	drm_modeset_lock_all(vmw_priv->dev);
 	(void) vmw_fb_kms_detach(par, true, false);
+	drm_modeset_unlock_all(vmw_priv->dev);
 	mutex_unlock(&par->bo_mutex);
 
 	return 0;
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (8 preceding siblings ...)
  2017-03-27 22:01 ` [PATCH 09/11] drm/vmwgfx: Fixes to vmwgfx_fb Sinclair Yeh
@ 2017-03-27 22:01 ` Sinclair Yeh
  2017-03-28  7:49   ` Daniel Vetter
  2017-03-27 22:01 ` [PATCH 11/11] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU Sinclair Yeh
  2017-03-28  7:54 ` [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Daniel Vetter
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:01 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Switch over to using internal atomic API for mode set.

This removes the legacy set_config API, replacing it with
drm_atomic_helper_set_config().  The DRM helper will use various
vmwgfx-specific atomic functions to set a mode.

DRIVER_ATOMIC capability flag is not yet set, so the user mode
will still use the legacy mode set IOCTL.

v2:
* Avoid a clash between page-flip pinning and setcrtc pinning, modify
the page-flip code to use the page-flip helper and the atomic callbacks.
To enable this, we will need to add a wrapper around atomic_commit.

* Add vmw_kms_set_config() to work around vmwgfx xorg driver bug

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  20 +++
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   1 +
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 325 ++++-------------------------------
 3 files changed, 51 insertions(+), 295 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 6b593aaf..7104796 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -2923,3 +2923,23 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
 					  "implicit_placement", 0, 1);
 
 }
+
+
+/**
+ * vmw_kms_set_config - Wrapper around drm_atomic_helper_set_config
+ *
+ * @set: The configuration to set.
+ *
+ * The vmwgfx Xorg driver doesn't assign the mode::type member, which
+ * when drm_mode_set_crtcinfo is called as part of the configuration setting
+ * causes it to return incorrect crtc dimensions causing severe problems in
+ * the vmwgfx modesetting. So explicitly clear that member before calling
+ * into drm_atomic_helper_set_config.
+ */
+int vmw_kms_set_config(struct drm_mode_set *set)
+{
+	if (set && set->mode)
+		set->mode->type = 0;
+
+	return drm_atomic_helper_set_config(set);
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 3251562..0016f07 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -451,5 +451,6 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
 		     bool to_surface,
 		     bool interruptible);
 
+int vmw_kms_set_config(struct drm_mode_set *set);
 
 #endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 708d063..ff00817 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -104,8 +104,7 @@ struct vmw_stdu_surface_copy {
  */
 struct vmw_screen_target_display_unit {
 	struct vmw_display_unit base;
-
-	struct vmw_surface     *display_srf;
+	const struct vmw_surface *display_srf;
 	enum stdu_content_type content_fb_type;
 
 	bool defined;
@@ -118,32 +117,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);
 
 
 /******************************************************************************
- * Screen Target Display Unit helper Functions
- *****************************************************************************/
-
-/**
- * vmw_stdu_unpin_display - unpins the resource associated with display surface
- *
- * @stdu: contains the display surface
- *
- * If the display surface was privatedly allocated by
- * vmw_surface_gb_priv_define() and not registered as a framebuffer, then it
- * won't be automatically cleaned up when all the framebuffers are freed.  As
- * such, we have to explicitly call vmw_resource_unreference() to get it freed.
- */
-static void vmw_stdu_unpin_display(struct vmw_screen_target_display_unit *stdu)
-{
-	if (stdu->display_srf) {
-		struct vmw_resource *res = &stdu->display_srf->res;
-
-		vmw_resource_unpin(res);
-		vmw_surface_unreference(&stdu->display_srf);
-	}
-}
-
-
-
-/******************************************************************************
  * Screen Target Display Unit CRTC Functions
  *****************************************************************************/
 
@@ -228,7 +201,7 @@ static int vmw_stdu_define_st(struct vmw_private *dev_priv,
  */
 static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
 			    struct vmw_screen_target_display_unit *stdu,
-			    struct vmw_resource *res)
+			    const struct vmw_resource *res)
 {
 	SVGA3dSurfaceImageId image;
 
@@ -377,129 +350,6 @@ static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
 	return ret;
 }
 
-/**
- * vmw_stdu_bind_fb - Bind an fb to a defined screen target
- *
- * @dev_priv: Pointer to a device private struct.
- * @crtc: The crtc holding the screen target.
- * @mode: The mode currently used by the screen target. Must be non-NULL.
- * @new_fb: The new framebuffer to bind. Must be non-NULL.
- *
- * RETURNS:
- * 0 on success, error code on failure.
- */
-static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
-			    struct drm_crtc *crtc,
-			    struct drm_display_mode *mode,
-			    struct drm_framebuffer *new_fb)
-{
-	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
-	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
-	struct vmw_surface *new_display_srf = NULL;
-	enum stdu_content_type new_content_type;
-	struct vmw_framebuffer_surface *new_vfbs;
-	int ret;
-
-	WARN_ON_ONCE(!stdu->defined);
-
-	new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
-
-	if (new_vfbs && new_vfbs->surface->base_size.width == mode->hdisplay &&
-	    new_vfbs->surface->base_size.height == mode->vdisplay)
-		new_content_type = SAME_AS_DISPLAY;
-	else if (vfb->dmabuf)
-		new_content_type = SEPARATE_DMA;
-	else
-		new_content_type = SEPARATE_SURFACE;
-
-	if (new_content_type != SAME_AS_DISPLAY &&
-	    !stdu->display_srf) {
-		struct vmw_surface content_srf;
-		struct drm_vmw_size display_base_size = {0};
-
-		display_base_size.width  = mode->hdisplay;
-		display_base_size.height = mode->vdisplay;
-		display_base_size.depth  = 1;
-
-		/*
-		 * If content buffer is a DMA buf, then we have to construct
-		 * surface info
-		 */
-		if (new_content_type == SEPARATE_DMA) {
-
-			switch (new_fb->format->cpp[0] * 8) {
-			case 32:
-				content_srf.format = SVGA3D_X8R8G8B8;
-				break;
-
-			case 16:
-				content_srf.format = SVGA3D_R5G6B5;
-				break;
-
-			case 8:
-				content_srf.format = SVGA3D_P8;
-				break;
-
-			default:
-				DRM_ERROR("Invalid format\n");
-				return -EINVAL;
-			}
-
-			content_srf.flags             = 0;
-			content_srf.mip_levels[0]     = 1;
-			content_srf.multisample_count = 0;
-		} else {
-			content_srf = *new_vfbs->surface;
-		}
-
-
-		ret = vmw_surface_gb_priv_define(crtc->dev,
-				0, /* because kernel visible only */
-				content_srf.flags,
-				content_srf.format,
-				true, /* a scanout buffer */
-				content_srf.mip_levels[0],
-				content_srf.multisample_count,
-				0,
-				display_base_size,
-				&new_display_srf);
-		if (unlikely(ret != 0)) {
-			DRM_ERROR("Could not allocate screen target surface.\n");
-			return ret;
-		}
-	} else if (new_content_type == SAME_AS_DISPLAY) {
-		new_display_srf = vmw_surface_reference(new_vfbs->surface);
-	}
-
-	if (new_display_srf) {
-		/* Pin new surface before flipping */
-		ret = vmw_resource_pin(&new_display_srf->res, false);
-		if (ret)
-			goto out_srf_unref;
-
-		ret = vmw_stdu_bind_st(dev_priv, stdu, &new_display_srf->res);
-		if (ret)
-			goto out_srf_unpin;
-
-		/* Unpin and unreference old surface */
-		vmw_stdu_unpin_display(stdu);
-
-		/* Transfer the reference */
-		stdu->display_srf = new_display_srf;
-		new_display_srf = NULL;
-	}
-
-	crtc->primary->fb = new_fb;
-	stdu->content_fb_type = new_content_type;
-	return 0;
-
-out_srf_unpin:
-	vmw_resource_unpin(&new_display_srf->res);
-out_srf_unref:
-	vmw_surface_unreference(&new_display_srf);
-	return ret;
-}
-
 
 /**
  * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
@@ -601,136 +451,6 @@ static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc)
 }
 
 /**
- * vmw_stdu_crtc_set_config - Sets a mode
- *
- * @set:  mode parameters
- *
- * This function is the device-specific portion of the DRM CRTC mode set.
- * For the SVGA device, we do this by defining a Screen Target, binding a
- * GB Surface to that target, and finally update the screen target.
- *
- * RETURNS:
- * 0 on success, error code otherwise
- */
-static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
-{
-	struct vmw_private *dev_priv;
-	struct vmw_framebuffer *vfb;
-	struct vmw_screen_target_display_unit *stdu;
-	struct drm_display_mode *mode;
-	struct drm_framebuffer  *new_fb;
-	struct drm_crtc      *crtc;
-	struct drm_encoder   *encoder;
-	struct drm_connector *connector;
-	bool turning_off;
-	int    ret;
-
-
-	if (!set || !set->crtc)
-		return -EINVAL;
-
-	crtc     = set->crtc;
-	stdu     = vmw_crtc_to_stdu(crtc);
-	mode     = set->mode;
-	new_fb   = set->fb;
-	dev_priv = vmw_priv(crtc->dev);
-	turning_off = set->num_connectors == 0 || !mode || !new_fb;
-	vfb = (new_fb) ? vmw_framebuffer_to_vfb(new_fb) : NULL;
-
-	if (set->num_connectors > 1) {
-		DRM_ERROR("Too many connectors\n");
-		return -EINVAL;
-	}
-
-	if (set->num_connectors == 1 &&
-	    set->connectors[0] != &stdu->base.connector) {
-		DRM_ERROR("Connectors don't match %p %p\n",
-			set->connectors[0], &stdu->base.connector);
-		return -EINVAL;
-	}
-
-	if (!turning_off && (set->x + mode->hdisplay > new_fb->width ||
-			     set->y + mode->vdisplay > new_fb->height)) {
-		DRM_ERROR("Set outside of framebuffer\n");
-		return -EINVAL;
-	}
-
-	/* Only one active implicit frame-buffer at a time. */
-	mutex_lock(&dev_priv->global_kms_state_mutex);
-	if (!turning_off && stdu->base.is_implicit && dev_priv->implicit_fb &&
-	    !(dev_priv->num_implicit == 1 && stdu->base.active_implicit)
-	    && dev_priv->implicit_fb != vfb) {
-		mutex_unlock(&dev_priv->global_kms_state_mutex);
-		DRM_ERROR("Multiple implicit framebuffers not supported.\n");
-		return -EINVAL;
-	}
-	mutex_unlock(&dev_priv->global_kms_state_mutex);
-
-	/* Since they always map one to one these are safe */
-	connector = &stdu->base.connector;
-	encoder   = &stdu->base.encoder;
-
-	if (stdu->defined) {
-		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
-		if (ret)
-			return ret;
-
-		vmw_stdu_unpin_display(stdu);
-		(void) vmw_stdu_update_st(dev_priv, stdu);
-		vmw_kms_del_active(dev_priv, &stdu->base);
-
-		ret = vmw_stdu_destroy_st(dev_priv, stdu);
-		if (ret)
-			return ret;
-
-		crtc->primary->fb = NULL;
-		crtc->enabled = false;
-		encoder->crtc = NULL;
-		connector->encoder = NULL;
-		stdu->content_fb_type = SAME_AS_DISPLAY;
-		crtc->x = set->x;
-		crtc->y = set->y;
-	}
-
-	if (turning_off)
-		return 0;
-
-	/*
-	 * Steps to displaying a surface, assume surface is already
-	 * bound:
-	 *   1.  define a screen target
-	 *   2.  bind a fb to the screen target
-	 *   3.  update that screen target (this is done later by
-	 *       vmw_kms_stdu_do_surface_dirty_or_present)
-	 */
-	/*
-	 * Note on error handling: We can't really restore the crtc to
-	 * it's original state on error, but we at least update the
-	 * current state to what's submitted to hardware to enable
-	 * future recovery.
-	 */
-	vmw_svga_enable(dev_priv);
-	ret = vmw_stdu_define_st(dev_priv, stdu, mode, set->x, set->y);
-	if (ret)
-		return ret;
-
-	crtc->x = set->x;
-	crtc->y = set->y;
-	crtc->mode = *mode;
-
-	ret = vmw_stdu_bind_fb(dev_priv, crtc, mode, new_fb);
-	if (ret)
-		return ret;
-
-	vmw_kms_add_active(dev_priv, &stdu->base, vfb);
-	crtc->enabled = true;
-	connector->encoder = encoder;
-	encoder->crtc      = crtc;
-
-	return 0;
-}
-
-/**
  * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
  *
  * @crtc: CRTC to attach FB to
@@ -756,9 +476,9 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
 
 {
 	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
-	struct vmw_screen_target_display_unit *stdu;
-	struct drm_vmw_rect vclips;
+	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
 	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
+	struct drm_vmw_rect vclips;
 	int ret;
 
 	dev_priv          = vmw_priv(crtc->dev);
@@ -767,25 +487,42 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
 	if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc))
 		return -EINVAL;
 
-	ret = vmw_stdu_bind_fb(dev_priv, crtc, &crtc->mode, new_fb);
-	if (ret)
+	/*
+	 * We're always async, but the helper doesn't know how to set async
+	 * so lie to the helper. Also, the helper expects someone
+	 * to pick the event up from the crtc state, and if nobody does,
+	 * it will free it. Since we handle the event in this function,
+	 * don't hand it to the helper.
+	 */
+	flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
+	ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
+	if (ret) {
+		DRM_ERROR("Page flip error %d.\n", ret);
 		return ret;
+	}
 
 	if (stdu->base.is_implicit)
 		vmw_kms_update_implicit_fb(dev_priv, crtc);
 
+	/*
+	 * Now that we've bound a new surface to the screen target,
+	 * update the contents.
+	 */
 	vclips.x = crtc->x;
 	vclips.y = crtc->y;
 	vclips.w = crtc->mode.hdisplay;
 	vclips.h = crtc->mode.vdisplay;
+
 	if (vfb->dmabuf)
 		ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips,
 				       1, 1, true, false);
 	else
 		ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips,
 						 NULL, 0, 0, 1, 1, NULL);
-	if (ret)
+	if (ret) {
+		DRM_ERROR("Page flip update error %d.\n", ret);
 		return ret;
+	}
 
 	if (event) {
 		struct vmw_fence_obj *fence = NULL;
@@ -802,7 +539,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
 						   true);
 		vmw_fence_obj_unreference(&fence);
 	} else {
-		vmw_fifo_flush(dev_priv, false);
+		(void) vmw_fifo_flush(dev_priv, false);
 	}
 
 	return 0;
@@ -1123,7 +860,7 @@ static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
 	.reset = vmw_du_crtc_reset,
 	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
 	.atomic_destroy_state = vmw_du_crtc_destroy_state,
-	.set_config = vmw_stdu_crtc_set_config,
+	.set_config = vmw_kms_set_config,
 	.page_flip = vmw_stdu_crtc_page_flip,
 };
 
@@ -1425,8 +1162,8 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
 
 
 static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
-	.update_plane = drm_primary_helper_update,
-	.disable_plane = drm_primary_helper_disable,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = vmw_du_primary_plane_destroy,
 	.reset = vmw_du_plane_reset,
 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
@@ -1434,8 +1171,8 @@ static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
 };
 
 static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
-	.update_plane = vmw_du_cursor_plane_update,
-	.disable_plane = vmw_du_cursor_plane_disable,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = vmw_du_cursor_plane_destroy,
 	.reset = vmw_du_plane_reset,
 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
@@ -1625,8 +1362,6 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
  */
 static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu)
 {
-	vmw_stdu_unpin_display(stdu);
-
 	vmw_du_cleanup(&stdu->base);
 	kfree(stdu);
 }
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 11/11] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (9 preceding siblings ...)
  2017-03-27 22:01 ` [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU Sinclair Yeh
@ 2017-03-27 22:01 ` Sinclair Yeh
  2017-03-28  7:51   ` Daniel Vetter
  2017-03-28  7:54 ` [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Daniel Vetter
  11 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-27 22:01 UTC (permalink / raw)
  To: dri-devel; +Cc: daniel.vetter, thellstrom

Switch over to internal atomic API.  This completes the atomic
internal atomic switch for all the Display Units.

Signed-off-by: Sinclair Yeh <syeh@vmware.com>
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 103 ++---------------
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 217 +++--------------------------------
 2 files changed, 25 insertions(+), 295 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 282a0ef..4954f26 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -95,7 +95,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
 		if (crtc == NULL)
 			return 0;
-		fb = entry->base.crtc.primary->fb;
+		fb = entry->base.crtc.primary->state->fb;
 
 		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
 					  fb->format->cpp[0] * 8,
@@ -104,7 +104,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
 
 	if (!list_empty(&lds->active)) {
 		entry = list_entry(lds->active.next, typeof(*entry), active);
-		fb = entry->base.crtc.primary->fb;
+		fb = entry->base.crtc.primary->state->fb;
 
 		vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
 				   fb->format->cpp[0] * 8, fb->format->depth);
@@ -255,102 +255,13 @@ static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc)
 {
 }
 
-static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
-{
-	struct vmw_private *dev_priv;
-	struct vmw_legacy_display_unit *ldu;
-	struct drm_connector *connector;
-	struct drm_display_mode *mode;
-	struct drm_encoder *encoder;
-	struct vmw_framebuffer *vfb;
-	struct drm_framebuffer *fb;
-	struct drm_crtc *crtc;
-
-	if (!set)
-		return -EINVAL;
-
-	if (!set->crtc)
-		return -EINVAL;
-
-	/* get the ldu */
-	crtc = set->crtc;
-	ldu = vmw_crtc_to_ldu(crtc);
-	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
-	dev_priv = vmw_priv(crtc->dev);
-
-	if (set->num_connectors > 1) {
-		DRM_ERROR("to many connectors\n");
-		return -EINVAL;
-	}
-
-	if (set->num_connectors == 1 &&
-	    set->connectors[0] != &ldu->base.connector) {
-		DRM_ERROR("connector doesn't match %p %p\n",
-			set->connectors[0], &ldu->base.connector);
-		return -EINVAL;
-	}
-
-	/* ldu only supports one fb active at the time */
-	if (dev_priv->ldu_priv->fb && vfb &&
-	    !(dev_priv->ldu_priv->num_active == 1 &&
-	      !list_empty(&ldu->active)) &&
-	    dev_priv->ldu_priv->fb != vfb) {
-		DRM_ERROR("Multiple framebuffers not supported\n");
-		return -EINVAL;
-	}
-
-	/* since they always map one to one these are safe */
-	connector = &ldu->base.connector;
-	encoder = &ldu->base.encoder;
-
-	/* should we turn the crtc off? */
-	if (set->num_connectors == 0 || !set->mode || !set->fb) {
-
-		connector->encoder = NULL;
-		encoder->crtc = NULL;
-		crtc->primary->fb = NULL;
-		crtc->enabled = false;
-
-		vmw_ldu_del_active(dev_priv, ldu);
-
-		return vmw_ldu_commit_list(dev_priv);
-	}
-
-
-	/* we now know we want to set a mode */
-	mode = set->mode;
-	fb = set->fb;
-
-	if (set->x + mode->hdisplay > fb->width ||
-	    set->y + mode->vdisplay > fb->height) {
-		DRM_ERROR("set outside of framebuffer\n");
-		return -EINVAL;
-	}
-
-	vmw_svga_enable(dev_priv);
-
-	crtc->primary->fb = fb;
-	encoder->crtc = crtc;
-	connector->encoder = encoder;
-	crtc->x = set->x;
-	crtc->y = set->y;
-	crtc->mode = *mode;
-	crtc->enabled = true;
-	ldu->base.set_gui_x = set->x;
-	ldu->base.set_gui_y = set->y;
-
-	vmw_ldu_add_active(dev_priv, ldu, vfb);
-
-	return vmw_ldu_commit_list(dev_priv);
-}
-
 static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
 	.gamma_set = vmw_du_crtc_gamma_set,
 	.destroy = vmw_ldu_crtc_destroy,
 	.reset = vmw_du_crtc_reset,
 	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
 	.atomic_destroy_state = vmw_du_crtc_destroy_state,
-	.set_config = vmw_ldu_crtc_set_config,
+	.set_config = vmw_kms_set_config,
 };
 
 
@@ -439,8 +350,8 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
 
 
 static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
-	.update_plane = drm_primary_helper_update,
-	.disable_plane = drm_primary_helper_disable,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = vmw_du_primary_plane_destroy,
 	.reset = vmw_du_plane_reset,
 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
@@ -448,8 +359,8 @@ static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
 };
 
 static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
-	.update_plane = vmw_du_cursor_plane_update,
-	.disable_plane = vmw_du_cursor_plane_disable,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = vmw_du_cursor_plane_destroy,
 	.reset = vmw_du_plane_reset,
 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index e4154f1..9d73f79 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -205,52 +205,6 @@ static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
 }
 
 /**
- * Free the backing store.
- */
-static void vmw_sou_backing_free(struct vmw_private *dev_priv,
-				 struct vmw_screen_object_unit *sou)
-{
-	vmw_dmabuf_unreference(&sou->buffer);
-	sou->buffer_size = 0;
-}
-
-/**
- * Allocate the backing store for the buffer.
- */
-static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
-				 struct vmw_screen_object_unit *sou,
-				 unsigned long size)
-{
-	int ret;
-
-	if (sou->buffer_size == size)
-		return 0;
-
-	if (sou->buffer)
-		vmw_sou_backing_free(dev_priv, sou);
-
-	sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
-	if (unlikely(sou->buffer == NULL))
-		return -ENOMEM;
-
-	/* After we have alloced the backing store might not be able to
-	 * resume the overlays, this is preferred to failing to alloc.
-	 */
-	vmw_overlay_pause_all(dev_priv);
-	ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
-			      &vmw_vram_ne_placement,
-			      false, &vmw_dmabuf_bo_free);
-	vmw_overlay_resume_all(dev_priv);
-
-	if (unlikely(ret != 0))
-		sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
-	else
-		sou->buffer_size = size;
-
-	return ret;
-}
-
-/**
  * vmw_sou_crtc_mode_set_nofb - Create new screen
  *
  * @crtc: CRTC associated with the new screen
@@ -353,158 +307,14 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
 	}
 }
 
-static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
-{
-	struct vmw_private *dev_priv;
-	struct vmw_screen_object_unit *sou;
-	struct drm_connector *connector;
-	struct drm_display_mode *mode;
-	struct drm_encoder *encoder;
-	struct vmw_framebuffer *vfb;
-	struct drm_framebuffer *fb;
-	struct drm_crtc *crtc;
-	int ret = 0;
-
-	if (!set)
-		return -EINVAL;
-
-	if (!set->crtc)
-		return -EINVAL;
-
-	/* get the sou */
-	crtc = set->crtc;
-	sou = vmw_crtc_to_sou(crtc);
-	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
-	dev_priv = vmw_priv(crtc->dev);
-
-	if (set->num_connectors > 1) {
-		DRM_ERROR("Too many connectors\n");
-		return -EINVAL;
-	}
-
-	if (set->num_connectors == 1 &&
-	    set->connectors[0] != &sou->base.connector) {
-		DRM_ERROR("Connector doesn't match %p %p\n",
-			set->connectors[0], &sou->base.connector);
-		return -EINVAL;
-	}
-
-	/* Only one active implicit frame-buffer at a time. */
-	mutex_lock(&dev_priv->global_kms_state_mutex);
-	if (sou->base.is_implicit &&
-	    dev_priv->implicit_fb && vfb &&
-	    !(dev_priv->num_implicit == 1 &&
-	      sou->base.active_implicit) &&
-	    dev_priv->implicit_fb != vfb) {
-		mutex_unlock(&dev_priv->global_kms_state_mutex);
-		DRM_ERROR("Multiple implicit framebuffers not supported.\n");
-		return -EINVAL;
-	}
-	mutex_unlock(&dev_priv->global_kms_state_mutex);
-
-	/* since they always map one to one these are safe */
-	connector = &sou->base.connector;
-	encoder = &sou->base.encoder;
-
-	/* should we turn the crtc off */
-	if (set->num_connectors == 0 || !set->mode || !set->fb) {
-		ret = vmw_sou_fifo_destroy(dev_priv, sou);
-		/* the hardware has hung don't do anything more */
-		if (unlikely(ret != 0))
-			return ret;
-
-		connector->encoder = NULL;
-		encoder->crtc = NULL;
-		crtc->primary->fb = NULL;
-		crtc->x = 0;
-		crtc->y = 0;
-		crtc->enabled = false;
-
-		vmw_kms_del_active(dev_priv, &sou->base);
-
-		vmw_sou_backing_free(dev_priv, sou);
-
-		return 0;
-	}
-
-
-	/* we now know we want to set a mode */
-	mode = set->mode;
-	fb = set->fb;
-
-	if (set->x + mode->hdisplay > fb->width ||
-	    set->y + mode->vdisplay > fb->height) {
-		DRM_ERROR("set outside of framebuffer\n");
-		return -EINVAL;
-	}
-
-	vmw_svga_enable(dev_priv);
-
-	if (mode->hdisplay != crtc->mode.hdisplay ||
-	    mode->vdisplay != crtc->mode.vdisplay) {
-		/* no need to check if depth is different, because backing
-		 * store depth is forced to 4 by the device.
-		 */
-
-		ret = vmw_sou_fifo_destroy(dev_priv, sou);
-		/* the hardware has hung don't do anything more */
-		if (unlikely(ret != 0))
-			return ret;
-
-		vmw_sou_backing_free(dev_priv, sou);
-	}
-
-	if (!sou->buffer) {
-		/* forced to depth 4 by the device */
-		size_t size = mode->hdisplay * mode->vdisplay * 4;
-		ret = vmw_sou_backing_alloc(dev_priv, sou, size);
-		if (unlikely(ret != 0))
-			return ret;
-	}
-
-	ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
-	if (unlikely(ret != 0)) {
-		/*
-		 * We are in a bit of a situation here, the hardware has
-		 * hung and we may or may not have a buffer hanging of
-		 * the screen object, best thing to do is not do anything
-		 * if we where defined, if not just turn the crtc of.
-		 * Not what userspace wants but it needs to htfu.
-		 */
-		if (sou->defined)
-			return ret;
-
-		connector->encoder = NULL;
-		encoder->crtc = NULL;
-		crtc->primary->fb = NULL;
-		crtc->x = 0;
-		crtc->y = 0;
-		crtc->enabled = false;
-
-		return ret;
-	}
-
-	vmw_kms_add_active(dev_priv, &sou->base, vfb);
-
-	connector->encoder = encoder;
-	encoder->crtc = crtc;
-	crtc->mode = *mode;
-	crtc->primary->fb = fb;
-	crtc->x = set->x;
-	crtc->y = set->y;
-	crtc->enabled = true;
-
-	return 0;
-}
-
 static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
-				  struct drm_framebuffer *fb,
+				  struct drm_framebuffer *new_fb,
 				  struct drm_pending_vblank_event *event,
 				  uint32_t flags)
 {
 	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
 	struct drm_framebuffer *old_fb = crtc->primary->fb;
-	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
+	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
 	struct vmw_fence_obj *fence = NULL;
 	struct drm_vmw_rect vclips;
 	int ret;
@@ -512,7 +322,12 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 	if (!vmw_kms_crtc_flippable(dev_priv, crtc))
 		return -EINVAL;
 
-	crtc->primary->fb = fb;
+	flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
+	ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
+	if (ret) {
+		DRM_ERROR("Page flip error %d.\n", ret);
+		return ret;
+	}
 
 	/* do a full screen dirty update */
 	vclips.x = crtc->x;
@@ -559,7 +374,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
 	return ret;
 
 out_no_fence:
-	crtc->primary->fb = old_fb;
+	drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb);
 	return ret;
 }
 
@@ -569,7 +384,7 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
 	.reset = vmw_du_crtc_reset,
 	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
 	.atomic_destroy_state = vmw_du_crtc_destroy_state,
-	.set_config = vmw_sou_crtc_set_config,
+	.set_config = vmw_kms_set_config,
 	.page_flip = vmw_sou_crtc_page_flip,
 };
 
@@ -711,12 +526,16 @@ static void
 vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
 				    struct drm_plane_state *old_state)
 {
+	struct drm_crtc *crtc = plane->state->crtc;
+
+	if (crtc)
+		crtc->primary->fb = plane->state->fb;
 }
 
 
 static const struct drm_plane_funcs vmw_sou_plane_funcs = {
-	.update_plane = drm_primary_helper_update,
-	.disable_plane = drm_primary_helper_disable,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = vmw_du_primary_plane_destroy,
 	.reset = vmw_du_plane_reset,
 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
@@ -724,8 +543,8 @@ static const struct drm_plane_funcs vmw_sou_plane_funcs = {
 };
 
 static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
-	.update_plane = vmw_du_cursor_plane_update,
-	.disable_plane = vmw_du_cursor_plane_disable,
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
 	.destroy = vmw_du_cursor_plane_destroy,
 	.reset = vmw_du_plane_reset,
 	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
-- 
2.7.4

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

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* Re: [PATCH 01/11] drm/vmwgfx: Add universal plane support
  2017-03-27 22:00 ` [PATCH 01/11] drm/vmwgfx: Add universal plane support Sinclair Yeh
@ 2017-03-28  7:07   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:07 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:00:54PM -0700, Sinclair Yeh wrote:
> Universal support is prerequisite for atomic mode set.
> 
> Explicitly create planes for the cursor and the primary FB.  With
> a functional cursor plane, the DRM will no longer use the legacy
> cursor_set2 and cursor_move entry points.
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>

So per our discussion I think it'd be good to only have 1 global cursor
plane instead of the fake per-crtc one. At least it sounded like that
would reflect the virtual hw more accurately.
-Daniel

> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.c  |   1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_drv.h  |   1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 271 +++++++++++++++++------------------
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  39 +++--
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 108 ++++++++++----
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |  87 +++++++++--
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  89 ++++++++++--
>  7 files changed, 398 insertions(+), 198 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> index 541a588..45d711e 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> @@ -645,6 +645,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
>  	spin_lock_init(&dev_priv->waiter_lock);
>  	spin_lock_init(&dev_priv->cap_lock);
>  	spin_lock_init(&dev_priv->svga_lock);
> +	spin_lock_init(&dev_priv->cursor_lock);
>  
>  	for (i = vmw_res_context; i < vmw_res_max; ++i) {
>  		idr_init(&dev_priv->res_idr[i]);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> index 9ae4477..ef0181c 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> @@ -414,6 +414,7 @@ struct vmw_private {
>  	unsigned num_implicit;
>  	struct vmw_framebuffer *implicit_fb;
>  	struct mutex global_kms_state_mutex;
> +	spinlock_t cursor_lock;
>  
>  	/*
>  	 * Context and surface management.
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 6bcba56..c9f5dda 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -33,10 +33,9 @@
>  
>  void vmw_du_cleanup(struct vmw_display_unit *du)
>  {
> -	if (du->cursor_surface)
> -		vmw_surface_unreference(&du->cursor_surface);
> -	if (du->cursor_dmabuf)
> -		vmw_dmabuf_unreference(&du->cursor_dmabuf);
> +	drm_plane_cleanup(&du->primary);
> +	drm_plane_cleanup(&du->cursor);
> +
>  	drm_connector_unregister(&du->connector);
>  	drm_crtc_cleanup(&du->crtc);
>  	drm_encoder_cleanup(&du->encoder);
> @@ -47,9 +46,9 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
>   * Display Unit Cursor functions
>   */
>  
> -int vmw_cursor_update_image(struct vmw_private *dev_priv,
> -			    u32 *image, u32 width, u32 height,
> -			    u32 hotspotX, u32 hotspotY)
> +static int vmw_cursor_update_image(struct vmw_private *dev_priv,
> +				   u32 *image, u32 width, u32 height,
> +				   u32 hotspotX, u32 hotspotY)
>  {
>  	struct {
>  		u32 cmd;
> @@ -83,10 +82,10 @@ int vmw_cursor_update_image(struct vmw_private *dev_priv,
>  	return 0;
>  }
>  
> -int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
> -			     struct vmw_dma_buffer *dmabuf,
> -			     u32 width, u32 height,
> -			     u32 hotspotX, u32 hotspotY)
> +static int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
> +				    struct vmw_dma_buffer *dmabuf,
> +				    u32 width, u32 height,
> +				    u32 hotspotX, u32 hotspotY)
>  {
>  	struct ttm_bo_kmap_obj map;
>  	unsigned long kmap_offset;
> @@ -120,145 +119,22 @@ int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
>  }
>  
>  
> -void vmw_cursor_update_position(struct vmw_private *dev_priv,
> -				bool show, int x, int y)
> +static void vmw_cursor_update_position(struct vmw_private *dev_priv,
> +				       bool show, int x, int y)
>  {
>  	u32 *fifo_mem = dev_priv->mmio_virt;
>  	uint32_t count;
>  
> +	spin_lock(&dev_priv->cursor_lock);
>  	vmw_mmio_write(show ? 1 : 0, fifo_mem + SVGA_FIFO_CURSOR_ON);
>  	vmw_mmio_write(x, fifo_mem + SVGA_FIFO_CURSOR_X);
>  	vmw_mmio_write(y, fifo_mem + SVGA_FIFO_CURSOR_Y);
>  	count = vmw_mmio_read(fifo_mem + SVGA_FIFO_CURSOR_COUNT);
>  	vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
> +	spin_unlock(&dev_priv->cursor_lock);
>  }
>  
>  
> -/*
> - * vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
> - */
> -int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
> -			    uint32_t handle, uint32_t width, uint32_t height,
> -			    int32_t hot_x, int32_t hot_y)
> -{
> -	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> -	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
> -	struct vmw_surface *surface = NULL;
> -	struct vmw_dma_buffer *dmabuf = NULL;
> -	s32 hotspot_x, hotspot_y;
> -	int ret;
> -
> -	/*
> -	 * FIXME: Unclear whether there's any global state touched by the
> -	 * cursor_set function, especially vmw_cursor_update_position looks
> -	 * suspicious. For now take the easy route and reacquire all locks. We
> -	 * can do this since the caller in the drm core doesn't check anything
> -	 * which is protected by any looks.
> -	 */
> -	drm_modeset_unlock_crtc(crtc);
> -	drm_modeset_lock_all(dev_priv->dev);
> -	hotspot_x = hot_x + du->hotspot_x;
> -	hotspot_y = hot_y + du->hotspot_y;
> -
> -	/* A lot of the code assumes this */
> -	if (handle && (width != 64 || height != 64)) {
> -		ret = -EINVAL;
> -		goto out;
> -	}
> -
> -	if (handle) {
> -		struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
> -
> -		ret = vmw_user_lookup_handle(dev_priv, tfile,
> -					     handle, &surface, &dmabuf);
> -		if (ret) {
> -			DRM_ERROR("failed to find surface or dmabuf: %i\n", ret);
> -			ret = -EINVAL;
> -			goto out;
> -		}
> -	}
> -
> -	/* need to do this before taking down old image */
> -	if (surface && !surface->snooper.image) {
> -		DRM_ERROR("surface not suitable for cursor\n");
> -		vmw_surface_unreference(&surface);
> -		ret = -EINVAL;
> -		goto out;
> -	}
> -
> -	/* takedown old cursor */
> -	if (du->cursor_surface) {
> -		vmw_surface_unreference(&du->cursor_surface);
> -	}
> -	if (du->cursor_dmabuf)
> -		vmw_dmabuf_unreference(&du->cursor_dmabuf);
> -
> -	/* setup new image */
> -	ret = 0;
> -	if (surface) {
> -		/* vmw_user_surface_lookup takes one reference */
> -		du->cursor_surface = surface;
> -
> -		du->cursor_age = du->cursor_surface->snooper.age;
> -		ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
> -					      64, 64, hotspot_x, hotspot_y);
> -	} else if (dmabuf) {
> -		/* vmw_user_surface_lookup takes one reference */
> -		du->cursor_dmabuf = dmabuf;
> -
> -		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
> -					       hotspot_x, hotspot_y);
> -	} else {
> -		vmw_cursor_update_position(dev_priv, false, 0, 0);
> -		goto out;
> -	}
> -
> -	if (!ret) {
> -		vmw_cursor_update_position(dev_priv, true,
> -					   du->cursor_x + hotspot_x,
> -					   du->cursor_y + hotspot_y);
> -		du->core_hotspot_x = hot_x;
> -		du->core_hotspot_y = hot_y;
> -	}
> -
> -out:
> -	drm_modeset_unlock_all(dev_priv->dev);
> -	drm_modeset_lock_crtc(crtc, crtc->cursor);
> -
> -	return ret;
> -}
> -
> -int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
> -{
> -	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> -	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
> -	bool shown = du->cursor_surface || du->cursor_dmabuf ? true : false;
> -
> -	du->cursor_x = x + du->set_gui_x;
> -	du->cursor_y = y + du->set_gui_y;
> -
> -	/*
> -	 * FIXME: Unclear whether there's any global state touched by the
> -	 * cursor_set function, especially vmw_cursor_update_position looks
> -	 * suspicious. For now take the easy route and reacquire all locks. We
> -	 * can do this since the caller in the drm core doesn't check anything
> -	 * which is protected by any looks.
> -	 */
> -	drm_modeset_unlock_crtc(crtc);
> -	drm_modeset_lock_all(dev_priv->dev);
> -
> -	vmw_cursor_update_position(dev_priv, shown,
> -				   du->cursor_x + du->hotspot_x +
> -				   du->core_hotspot_x,
> -				   du->cursor_y + du->hotspot_y +
> -				   du->core_hotspot_y);
> -
> -	drm_modeset_unlock_all(dev_priv->dev);
> -	drm_modeset_lock_crtc(crtc, crtc->cursor);
> -
> -	return 0;
> -}
> -
>  void vmw_kms_cursor_snoop(struct vmw_surface *srf,
>  			  struct ttm_object_file *tfile,
>  			  struct ttm_buffer_object *bo,
> @@ -393,6 +269,125 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
>  	mutex_unlock(&dev->mode_config.mutex);
>  }
>  
> +
> +
> +/**
> + * vmw_du_cursor_plane_update() - Update cursor image and location
> + *
> + * @plane: plane object to update
> + * @crtc: owning CRTC of @plane
> + * @fb: framebuffer to flip onto plane
> + * @crtc_x: x offset of plane on crtc
> + * @crtc_y: y offset of plane on crtc
> + * @crtc_w: width of plane rectangle on crtc
> + * @crtc_h: height of plane rectangle on crtc
> + * @src_x: Not used
> + * @src_y: Not used
> + * @src_w: Not used
> + * @src_h: Not used
> + *
> + *
> + * RETURNS:
> + * Zero on success, error code on failure
> + */
> +int vmw_du_cursor_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)
> +{
> +	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> +	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
> +	struct vmw_surface *surface = NULL;
> +	struct vmw_dma_buffer *dmabuf = NULL;
> +	s32 hotspot_x, hotspot_y;
> +	int ret;
> +
> +	hotspot_x = du->hotspot_x + fb->hot_x;
> +	hotspot_y = du->hotspot_y + fb->hot_y;
> +
> +	/* A lot of the code assumes this */
> +	if (crtc_w != 64 || crtc_h != 64) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (vmw_framebuffer_to_vfb(fb)->dmabuf)
> +		dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
> +	else
> +		surface = vmw_framebuffer_to_vfbs(fb)->surface;
> +
> +	if (surface && !surface->snooper.image) {
> +		DRM_ERROR("surface not suitable for cursor\n");
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* setup new image */
> +	ret = 0;
> +	if (surface) {
> +		/* vmw_user_surface_lookup takes one reference */
> +		du->cursor_surface = surface;
> +
> +		du->cursor_age = du->cursor_surface->snooper.age;
> +
> +		ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
> +					      64, 64, hotspot_x, hotspot_y);
> +	} else if (dmabuf) {
> +		/* vmw_user_surface_lookup takes one reference */
> +		du->cursor_dmabuf = dmabuf;
> +
> +		ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, crtc_w, crtc_h,
> +					       hotspot_x, hotspot_y);
> +	} else {
> +		vmw_cursor_update_position(dev_priv, false, 0, 0);
> +		goto out;
> +	}
> +
> +	if (!ret) {
> +		du->cursor_x = crtc_x + du->set_gui_x;
> +		du->cursor_y = crtc_y + du->set_gui_y;
> +
> +		vmw_cursor_update_position(dev_priv, true,
> +					   du->cursor_x + hotspot_x,
> +					   du->cursor_y + hotspot_y);
> +	}
> +
> +out:
> +	return ret;
> +}
> +
> +
> +int vmw_du_cursor_plane_disable(struct drm_plane *plane)
> +{
> +	if (plane->fb) {
> +		drm_framebuffer_unreference(plane->fb);
> +		plane->fb = NULL;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +
> +void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
> +{
> +	vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
> +
> +	drm_plane_cleanup(plane);
> +}
> +
> +
> +void vmw_du_primary_plane_destroy(struct drm_plane *plane)
> +{
> +	drm_plane_cleanup(plane);
> +
> +	/* Planes are static in our case so we don't free it */
> +}
> +
> +
>  /*
>   * Generic framebuffer code
>   */
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index cb36e1d..e400bfb 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -33,6 +33,8 @@
>  #include <drm/drm_encoder.h>
>  #include "vmwgfx_drv.h"
>  
> +
> +
>  /**
>   * struct vmw_kms_dirty - closure structure for the vmw_kms_helper_dirty
>   * function.
> @@ -125,19 +127,17 @@ struct vmw_framebuffer_dmabuf {
>  };
>  
>  
> -/*
> - * Basic cursor manipulation
> - */
> -int vmw_cursor_update_image(struct vmw_private *dev_priv,
> -			    u32 *image, u32 width, u32 height,
> -			    u32 hotspotX, u32 hotspotY);
> -int vmw_cursor_update_dmabuf(struct vmw_private *dev_priv,
> -			     struct vmw_dma_buffer *dmabuf,
> -			     u32 width, u32 height,
> -			     u32 hotspotX, u32 hotspotY);
> -void vmw_cursor_update_position(struct vmw_private *dev_priv,
> -				bool show, int x, int y);
> +static const uint32_t vmw_primary_plane_formats[] = {
> +	DRM_FORMAT_XRGB1555,
> +	DRM_FORMAT_RGB565,
> +	DRM_FORMAT_RGB888,
> +	DRM_FORMAT_XRGB8888,
> +	DRM_FORMAT_ARGB8888,
> +};
>  
> +static const uint32_t vmw_cursor_plane_formats[] = {
> +	DRM_FORMAT_ARGB8888,
> +};
>  
>  /**
>   * Base class display unit.
> @@ -150,6 +150,8 @@ struct vmw_display_unit {
>  	struct drm_crtc crtc;
>  	struct drm_encoder encoder;
>  	struct drm_connector connector;
> +	struct drm_plane primary;
> +	struct drm_plane cursor;
>  
>  	struct vmw_surface *cursor_surface;
>  	struct vmw_dma_buffer *cursor_dmabuf;
> @@ -270,6 +272,19 @@ void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv,
>  void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
>  						bool immutable);
>  
> +/* Universal Plane Helpers */
> +void vmw_du_primary_plane_destroy(struct drm_plane *plane);
> +void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
> +int vmw_du_cursor_plane_disable(struct drm_plane *plane);
> +int vmw_du_cursor_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);
> +
>  
>  /*
>   * Legacy display unit functions - vmwgfx_ldu.c
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index 3806148..3efcbe5 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -75,10 +75,9 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
>  {
>  	struct vmw_legacy_display *lds = dev_priv->ldu_priv;
>  	struct vmw_legacy_display_unit *entry;
> -	struct vmw_display_unit *du = NULL;
>  	struct drm_framebuffer *fb = NULL;
>  	struct drm_crtc *crtc = NULL;
> -	int i = 0, ret;
> +	int i = 0;
>  
>  	/* If there is no display topology the host just assumes
>  	 * that the guest will set the same layout as the host.
> @@ -132,25 +131,6 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
>  
>  	lds->last_num_active = lds->num_active;
>  
> -
> -	/* Find the first du with a cursor. */
> -	list_for_each_entry(entry, &lds->active, active) {
> -		du = &entry->base;
> -
> -		if (!du->cursor_dmabuf)
> -			continue;
> -
> -		ret = vmw_cursor_update_dmabuf(dev_priv,
> -					       du->cursor_dmabuf,
> -					       64, 64,
> -					       du->hotspot_x,
> -					       du->hotspot_y);
> -		if (ret == 0)
> -			break;
> -
> -		DRM_ERROR("Could not update cursor image\n");
> -	}
> -
>  	return 0;
>  }
>  
> @@ -298,8 +278,6 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
>  }
>  
>  static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
> -	.cursor_set2 = vmw_du_crtc_cursor_set2,
> -	.cursor_move = vmw_du_crtc_cursor_move,
>  	.gamma_set = vmw_du_crtc_gamma_set,
>  	.destroy = vmw_ldu_crtc_destroy,
>  	.set_config = vmw_ldu_crtc_set_config,
> @@ -336,6 +314,23 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
>  	.destroy = vmw_ldu_connector_destroy,
>  };
>  
> +/*
> + * Legacy Display Plane Functions
> + */
> +
> +static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
> +	.update_plane = drm_primary_helper_update,
> +	.disable_plane = drm_primary_helper_disable,
> +	.destroy = vmw_du_primary_plane_destroy,
> +};
> +
> +static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
> +	.update_plane = vmw_du_cursor_plane_update,
> +	.disable_plane = vmw_du_cursor_plane_disable,
> +	.destroy = vmw_du_cursor_plane_destroy,
> +};
> +
> +
>  static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  {
>  	struct vmw_legacy_display_unit *ldu;
> @@ -343,6 +338,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  	struct drm_connector *connector;
>  	struct drm_encoder *encoder;
>  	struct drm_crtc *crtc;
> +	int ret;
>  
>  	ldu = kzalloc(sizeof(*ldu), GFP_KERNEL);
>  	if (!ldu)
> @@ -361,19 +357,61 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  	ldu->base.pref_mode = NULL;
>  	ldu->base.is_implicit = true;
>  
> -	drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
> -			   DRM_MODE_CONNECTOR_VIRTUAL);
> +	/* Initialize primary plane */
> +	ret = drm_universal_plane_init(dev, &ldu->base.primary,
> +				       0, &vmw_ldu_plane_funcs,
> +				       vmw_primary_plane_formats,
> +				       ARRAY_SIZE(vmw_primary_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize primary plane");
> +		goto err_free;
> +	}
> +
> +	/* Initialize cursor plane */
> +	ret = drm_universal_plane_init(dev, &ldu->base.cursor,
> +			0, &vmw_ldu_cursor_funcs,
> +			vmw_cursor_plane_formats,
> +			ARRAY_SIZE(vmw_cursor_plane_formats),
> +			DRM_PLANE_TYPE_CURSOR, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize cursor plane");
> +		drm_plane_cleanup(&ldu->base.primary);
> +		goto err_free;
> +	}
> +
> +	ret = drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
> +				 DRM_MODE_CONNECTOR_VIRTUAL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector\n");
> +		goto err_free;
> +	}
>  	connector->status = vmw_du_connector_detect(connector, true);
>  
> -	drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
> -			 DRM_MODE_ENCODER_VIRTUAL, NULL);
> -	drm_mode_connector_attach_encoder(connector, encoder);
> +	ret = drm_encoder_init(dev, encoder, &vmw_legacy_encoder_funcs,
> +			       DRM_MODE_ENCODER_VIRTUAL, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize encoder\n");
> +		goto err_free_connector;
> +	}
> +
> +	(void) drm_mode_connector_attach_encoder(connector, encoder);
>  	encoder->possible_crtcs = (1 << unit);
>  	encoder->possible_clones = 0;
>  
> -	(void) drm_connector_register(connector);
> +	ret = drm_connector_register(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to register connector\n");
> +		goto err_free_encoder;
> +	}
>  
> -	drm_crtc_init(dev, crtc, &vmw_legacy_crtc_funcs);
> +	ret = drm_crtc_init_with_planes(dev, crtc, &ldu->base.primary,
> +					&ldu->base.cursor,
> +					&vmw_legacy_crtc_funcs, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize CRTC\n");
> +		goto err_free_unregister;
> +	}
>  
>  	drm_mode_crtc_set_gamma_size(crtc, 256);
>  
> @@ -390,6 +428,16 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  			 1);
>  
>  	return 0;
> +
> +err_free_unregister:
> +	drm_connector_unregister(connector);
> +err_free_encoder:
> +	drm_encoder_cleanup(encoder);
> +err_free_connector:
> +	drm_connector_cleanup(connector);
> +err_free:
> +	kfree(ldu);
> +	return ret;
>  }
>  
>  int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index d4268ef..8ffccb8 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -459,8 +459,6 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
>  }
>  
>  static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
> -	.cursor_set2 = vmw_du_crtc_cursor_set2,
> -	.cursor_move = vmw_du_crtc_cursor_move,
>  	.gamma_set = vmw_du_crtc_gamma_set,
>  	.destroy = vmw_sou_crtc_destroy,
>  	.set_config = vmw_sou_crtc_set_config,
> @@ -497,6 +495,23 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
>  	.destroy = vmw_sou_connector_destroy,
>  };
>  
> +/*
> + * Screen Object Display Plane Functions
> + */
> +
> +static const struct drm_plane_funcs vmw_sou_plane_funcs = {
> +	.update_plane = drm_primary_helper_update,
> +	.disable_plane = drm_primary_helper_disable,
> +	.destroy = vmw_du_primary_plane_destroy,
> +};
> +
> +static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
> +	.update_plane = vmw_du_cursor_plane_update,
> +	.disable_plane = vmw_du_cursor_plane_disable,
> +	.destroy = vmw_du_cursor_plane_destroy,
> +};
> +
> +
>  static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  {
>  	struct vmw_screen_object_unit *sou;
> @@ -504,6 +519,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  	struct drm_connector *connector;
>  	struct drm_encoder *encoder;
>  	struct drm_crtc *crtc;
> +	int ret;
>  
>  	sou = kzalloc(sizeof(*sou), GFP_KERNEL);
>  	if (!sou)
> @@ -521,19 +537,62 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  	sou->base.pref_mode = NULL;
>  	sou->base.is_implicit = false;
>  
> -	drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
> -			   DRM_MODE_CONNECTOR_VIRTUAL);
> +	/* Initialize primary plane */
> +	ret = drm_universal_plane_init(dev, &sou->base.primary,
> +				       0, &vmw_sou_plane_funcs,
> +				       vmw_primary_plane_formats,
> +				       ARRAY_SIZE(vmw_primary_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize primary plane");
> +		goto err_free;
> +	}
> +
> +	/* Initialize cursor plane */
> +	ret = drm_universal_plane_init(dev, &sou->base.cursor,
> +			0, &vmw_sou_cursor_funcs,
> +			vmw_cursor_plane_formats,
> +			ARRAY_SIZE(vmw_cursor_plane_formats),
> +			DRM_PLANE_TYPE_CURSOR, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize cursor plane");
> +		drm_plane_cleanup(&sou->base.primary);
> +		goto err_free;
> +	}
> +
> +	ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
> +				 DRM_MODE_CONNECTOR_VIRTUAL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector\n");
> +		goto err_free;
> +	}
> +
>  	connector->status = vmw_du_connector_detect(connector, true);
>  
> -	drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
> -			 DRM_MODE_ENCODER_VIRTUAL, NULL);
> -	drm_mode_connector_attach_encoder(connector, encoder);
> +	ret = drm_encoder_init(dev, encoder, &vmw_screen_object_encoder_funcs,
> +			       DRM_MODE_ENCODER_VIRTUAL, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize encoder\n");
> +		goto err_free_connector;
> +	}
> +
> +	(void) drm_mode_connector_attach_encoder(connector, encoder);
>  	encoder->possible_crtcs = (1 << unit);
>  	encoder->possible_clones = 0;
>  
> -	(void) drm_connector_register(connector);
> +	ret = drm_connector_register(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to register connector\n");
> +		goto err_free_encoder;
> +	}
>  
> -	drm_crtc_init(dev, crtc, &vmw_screen_object_crtc_funcs);
> +	ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary,
> +					&sou->base.cursor,
> +					&vmw_screen_object_crtc_funcs, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize CRTC\n");
> +		goto err_free_unregister;
> +	}
>  
>  	drm_mode_crtc_set_gamma_size(crtc, 256);
>  
> @@ -550,6 +609,16 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  			 sou->base.is_implicit);
>  
>  	return 0;
> +
> +err_free_unregister:
> +	drm_connector_unregister(connector);
> +err_free_encoder:
> +	drm_encoder_cleanup(encoder);
> +err_free_connector:
> +	drm_connector_cleanup(connector);
> +err_free:
> +	kfree(sou);
> +	return ret;
>  }
>  
>  int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index b27cd18..4d9dd1b 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -1015,8 +1015,6 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
>   *  Screen Target CRTC dispatch table
>   */
>  static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
> -	.cursor_set2 = vmw_du_crtc_cursor_set2,
> -	.cursor_move = vmw_du_crtc_cursor_move,
>  	.gamma_set = vmw_du_crtc_gamma_set,
>  	.destroy = vmw_stdu_crtc_destroy,
>  	.set_config = vmw_stdu_crtc_set_config,
> @@ -1081,6 +1079,23 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
>  
>  
>  
> +/******************************************************************************
> + * Screen Target Display Plane Functions
> + *****************************************************************************/
> +
> +static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
> +	.update_plane = drm_primary_helper_update,
> +	.disable_plane = drm_primary_helper_disable,
> +	.destroy = vmw_du_primary_plane_destroy,
> +};
> +
> +static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
> +	.update_plane = vmw_du_cursor_plane_update,
> +	.disable_plane = vmw_du_cursor_plane_disable,
> +	.destroy = vmw_du_cursor_plane_destroy,
> +};
> +
> +
>  /**
>   * vmw_stdu_init - Sets up a Screen Target Display Unit
>   *
> @@ -1097,7 +1112,9 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  	struct drm_device *dev = dev_priv->dev;
>  	struct drm_connector *connector;
>  	struct drm_encoder *encoder;
> +	struct drm_plane *primary, *cursor;
>  	struct drm_crtc *crtc;
> +	int    ret;
>  
>  
>  	stdu = kzalloc(sizeof(*stdu), GFP_KERNEL);
> @@ -1108,25 +1125,69 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  	crtc = &stdu->base.crtc;
>  	encoder = &stdu->base.encoder;
>  	connector = &stdu->base.connector;
> +	primary = &stdu->base.primary;
> +	cursor = &stdu->base.cursor;
>  
>  	stdu->base.pref_active = (unit == 0);
>  	stdu->base.pref_width  = dev_priv->initial_width;
>  	stdu->base.pref_height = dev_priv->initial_height;
>  	stdu->base.is_implicit = false;
>  
> -	drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
> -			   DRM_MODE_CONNECTOR_VIRTUAL);
> +	/* Initialize primary plane */
> +	ret = drm_universal_plane_init(dev, primary,
> +				       0, &vmw_stdu_plane_funcs,
> +				       vmw_primary_plane_formats,
> +				       ARRAY_SIZE(vmw_primary_plane_formats),
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize primary plane");
> +		goto err_free;
> +	}
> +
> +	/* Initialize cursor plane */
> +	ret = drm_universal_plane_init(dev, cursor,
> +			0, &vmw_stdu_cursor_funcs,
> +			vmw_cursor_plane_formats,
> +			ARRAY_SIZE(vmw_cursor_plane_formats),
> +			DRM_PLANE_TYPE_CURSOR, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize cursor plane");
> +		drm_plane_cleanup(&stdu->base.primary);
> +		goto err_free;
> +	}
> +
> +	ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
> +				 DRM_MODE_CONNECTOR_VIRTUAL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize connector\n");
> +		goto err_free;
> +	}
>  	connector->status = vmw_du_connector_detect(connector, false);
>  
> -	drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
> -			 DRM_MODE_ENCODER_VIRTUAL, NULL);
> -	drm_mode_connector_attach_encoder(connector, encoder);
> +	ret = drm_encoder_init(dev, encoder, &vmw_stdu_encoder_funcs,
> +			       DRM_MODE_ENCODER_VIRTUAL, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize encoder\n");
> +		goto err_free_connector;
> +	}
> +
> +	(void) drm_mode_connector_attach_encoder(connector, encoder);
>  	encoder->possible_crtcs = (1 << unit);
>  	encoder->possible_clones = 0;
>  
> -	(void) drm_connector_register(connector);
> +	ret = drm_connector_register(connector);
> +	if (ret) {
> +		DRM_ERROR("Failed to register connector\n");
> +		goto err_free_encoder;
> +	}
>  
> -	drm_crtc_init(dev, crtc, &vmw_stdu_crtc_funcs);
> +	ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary,
> +					&stdu->base.cursor,
> +					&vmw_stdu_crtc_funcs, NULL);
> +	if (ret) {
> +		DRM_ERROR("Failed to initialize CRTC\n");
> +		goto err_free_unregister;
> +	}
>  
>  	drm_mode_crtc_set_gamma_size(crtc, 256);
>  
> @@ -1142,6 +1203,16 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  			 dev_priv->implicit_placement_property,
>  			 stdu->base.is_implicit);
>  	return 0;
> +
> +err_free_unregister:
> +	drm_connector_unregister(connector);
> +err_free_encoder:
> +	drm_encoder_cleanup(encoder);
> +err_free_connector:
> +	drm_connector_cleanup(connector);
> +err_free:
> +	kfree(stdu);
> +	return ret;
>  }
>  
>  
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 03/11] drm/vmwgfx: Plane atomic state
  2017-03-27 22:00 ` [PATCH 03/11] drm/vmwgfx: Plane " Sinclair Yeh
@ 2017-03-28  7:33   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:33 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:00:56PM -0700, Sinclair Yeh wrote:
> Add plane state handling functions.
> 
> We have to keep track of a few plane states so we cannot use the
> DRM helper for this.
> 
> Created vmw_plane_state along with functions to reset, duplicate,
> and destroty it.
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 99 ++++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  | 24 +++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 13 +++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 13 +++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 10 ++++
>  5 files changed, 159 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 18bd8dc..d2171d9 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -35,6 +35,15 @@
>  
>  void vmw_du_cleanup(struct vmw_display_unit *du)
>  {
> +	if (du->cursor.state && du->cursor.state->fb) {
> +		/*
> +		 * On a layout change, the user mode doesn't call
> +		 * drm_mode_cursor_ioctl() to release the cursor, so
> +		 * we need to manualy release a reference of it.
> +		 */
> +		drm_framebuffer_unreference(du->cursor.state->fb);
> +	}

This looks funny. drm_plane_cleanup correctly destroys the attached and
hence should take care of unrefing the plane. If you really need this,
something did go wrong somewhere ...
-Daniel

> +
>  	drm_plane_cleanup(&du->primary);
>  	drm_plane_cleanup(&du->cursor);
>  
> @@ -468,6 +477,96 @@ vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
>  }
>  
>  
> +/**
> + * vmw_du_plane_duplicate_state - duplicate plane state
> + * @plane: drm plane
> + *
> + * Allocates and returns a copy of the plane state (both common and
> + * vmw-specific) for the specified plane.
> + *
> + * Returns: The newly allocated plane state, or NULL on failure.
> + */
> +struct drm_plane_state *
> +vmw_du_plane_duplicate_state(struct drm_plane *plane)
> +{
> +	struct drm_plane_state *state;
> +	struct vmw_plane_state *vps;
> +
> +	vps = kmemdup(plane->state, sizeof(*vps), GFP_KERNEL);
> +
> +	if (!vps)
> +		return NULL;
> +
> +	vps->pinned = 0;
> +
> +	/* Each ref counted resource needs to be acquired again */
> +	if (vps->surf)
> +		(void) vmw_surface_reference(vps->surf);
> +
> +	if (vps->dmabuf)
> +		(void) vmw_dmabuf_reference(vps->dmabuf);
> +
> +	state = &vps->base;
> +
> +	__drm_atomic_helper_plane_duplicate_state(plane, state);
> +
> +	return state;
> +}
> +
> +
> +/**
> + * vmw_du_plane_reset - creates a blank vmw plane state
> + * @plane: drm plane
> + *
> + * Resets the atomic state for @plane by freeing the state pointer (which might
> + * be NULL, e.g. at driver load time) and allocating a new empty state object.
> + */
> +void vmw_du_plane_reset(struct drm_plane *plane)
> +{
> +	struct vmw_plane_state *vps;
> +
> +
> +	if (plane->state)
> +		vmw_du_plane_destroy_state(plane, plane->state);
> +
> +	vps = kzalloc(sizeof(*vps), GFP_KERNEL);
> +
> +	if (!vps) {
> +		DRM_ERROR("Cannot allocate vmw_plane_state\n");
> +		return;
> +	}
> +
> +	plane->state = &vps->base;
> +	plane->state->plane = plane;
> +	plane->state->rotation = DRM_ROTATE_0;
> +}
> +
> +
> +/**
> + * vmw_du_plane_destroy_state - destroy plane state
> + * @plane: DRM plane
> + * @state: state object to destroy
> + *
> + * Destroys the plane state (both common and vmw-specific) for the
> + * specified plane.
> + */
> +void
> +vmw_du_plane_destroy_state(struct drm_plane *plane,
> +			   struct drm_plane_state *state)
> +{
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
> +
> +
> +	if (vps->surf)
> +		vmw_surface_unreference(&vps->surf);
> +
> +	if (vps->dmabuf)
> +		vmw_dmabuf_unreference(&vps->dmabuf);
> +
> +	drm_atomic_helper_plane_destroy_state(plane, state);
> +}
> +
> +
>  /*
>   * Generic framebuffer code
>   */
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index 370f75c..5602c24 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -141,6 +141,7 @@ static const uint32_t vmw_cursor_plane_formats[] = {
>  
>  
>  #define vmw_crtc_state_to_vcs(x) container_of(x, struct vmw_crtc_state, base)
> +#define vmw_plane_state_to_vps(x) container_of(x, struct vmw_plane_state, base)
>  
>  
>  /**
> @@ -153,6 +154,25 @@ struct vmw_crtc_state {
>  };
>  
>  /**
> + * Derived class for plane state object
> + *
> + * @base DRM plane object
> + * @surf Display surface for STDU
> + * @dmabuf display dmabuf for SOU
> + * @content_fb_type Used by STDU.
> + * @pinned pin count for STDU display surface
> + */
> +struct vmw_plane_state {
> +	struct drm_plane_state base;
> +	struct vmw_surface *surf;
> +	struct vmw_dma_buffer *dmabuf;
> +
> +	int content_fb_type;
> +
> +	int pinned;
> +};
> +
> +/**
>   * Base class display unit.
>   *
>   * Since the SVGA hw doesn't have a concept of a crtc, encoder or connector
> @@ -298,6 +318,10 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
>  			       uint32_t src_x, uint32_t src_y,
>  			       uint32_t src_w, uint32_t src_h);
>  
> +void vmw_du_plane_reset(struct drm_plane *plane);
> +struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
> +void vmw_du_plane_destroy_state(struct drm_plane *plane,
> +				struct drm_plane_state *state);
>  void vmw_du_crtc_reset(struct drm_crtc *crtc);
>  struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
>  void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index 3ee33f0..36cd1fe 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -325,12 +325,18 @@ static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
>  	.update_plane = drm_primary_helper_update,
>  	.disable_plane = drm_primary_helper_disable,
>  	.destroy = vmw_du_primary_plane_destroy,
> +	.reset = vmw_du_plane_reset,
> +	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> +	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
>  static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
>  	.update_plane = vmw_du_cursor_plane_update,
>  	.disable_plane = vmw_du_cursor_plane_disable,
>  	.destroy = vmw_du_cursor_plane_destroy,
> +	.reset = vmw_du_plane_reset,
> +	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> +	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
>  
> @@ -340,6 +346,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  	struct drm_device *dev = dev_priv->dev;
>  	struct drm_connector *connector;
>  	struct drm_encoder *encoder;
> +	struct drm_plane *primary, *cursor;
>  	struct drm_crtc *crtc;
>  	int ret;
>  
> @@ -351,6 +358,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  	crtc = &ldu->base.crtc;
>  	encoder = &ldu->base.encoder;
>  	connector = &ldu->base.connector;
> +	primary = &ldu->base.primary;
> +	cursor = &ldu->base.cursor;
>  
>  	INIT_LIST_HEAD(&ldu->active);
>  
> @@ -366,6 +375,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  	ldu->base.is_implicit = true;
>  
>  	/* Initialize primary plane */
> +	vmw_du_plane_reset(primary);
> +
>  	ret = drm_universal_plane_init(dev, &ldu->base.primary,
>  				       0, &vmw_ldu_plane_funcs,
>  				       vmw_primary_plane_formats,
> @@ -377,6 +388,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  	}
>  
>  	/* Initialize cursor plane */
> +	vmw_du_plane_reset(cursor);
> +
>  	ret = drm_universal_plane_init(dev, &ldu->base.cursor,
>  			0, &vmw_ldu_cursor_funcs,
>  			vmw_cursor_plane_formats,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index 033e17b..cfba59a 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -506,12 +506,18 @@ static const struct drm_plane_funcs vmw_sou_plane_funcs = {
>  	.update_plane = drm_primary_helper_update,
>  	.disable_plane = drm_primary_helper_disable,
>  	.destroy = vmw_du_primary_plane_destroy,
> +	.reset = vmw_du_plane_reset,
> +	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> +	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
>  static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
>  	.update_plane = vmw_du_cursor_plane_update,
>  	.disable_plane = vmw_du_cursor_plane_disable,
>  	.destroy = vmw_du_cursor_plane_destroy,
> +	.reset = vmw_du_plane_reset,
> +	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> +	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
>  
> @@ -521,6 +527,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  	struct drm_device *dev = dev_priv->dev;
>  	struct drm_connector *connector;
>  	struct drm_encoder *encoder;
> +	struct drm_plane *primary, *cursor;
>  	struct drm_crtc *crtc;
>  	int ret;
>  
> @@ -532,6 +539,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  	crtc = &sou->base.crtc;
>  	encoder = &sou->base.encoder;
>  	connector = &sou->base.connector;
> +	primary = &sou->base.primary;
> +	cursor = &sou->base.cursor;
>  
>  	sou->base.active_implicit = false;
>  	sou->base.pref_active = (unit == 0);
> @@ -546,6 +555,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  	sou->base.is_implicit = false;
>  
>  	/* Initialize primary plane */
> +	vmw_du_plane_reset(primary);
> +
>  	ret = drm_universal_plane_init(dev, &sou->base.primary,
>  				       0, &vmw_sou_plane_funcs,
>  				       vmw_primary_plane_formats,
> @@ -557,6 +568,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  	}
>  
>  	/* Initialize cursor plane */
> +	vmw_du_plane_reset(cursor);
> +
>  	ret = drm_universal_plane_init(dev, &sou->base.cursor,
>  			0, &vmw_sou_cursor_funcs,
>  			vmw_cursor_plane_formats,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index 3b8fafe..2a0f550 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -1090,12 +1090,18 @@ static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
>  	.update_plane = drm_primary_helper_update,
>  	.disable_plane = drm_primary_helper_disable,
>  	.destroy = vmw_du_primary_plane_destroy,
> +	.reset = vmw_du_plane_reset,
> +	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> +	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
>  static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
>  	.update_plane = vmw_du_cursor_plane_update,
>  	.disable_plane = vmw_du_cursor_plane_disable,
>  	.destroy = vmw_du_cursor_plane_destroy,
> +	.reset = vmw_du_plane_reset,
> +	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> +	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
>  
> @@ -1142,6 +1148,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  	stdu->base.is_implicit = false;
>  
>  	/* Initialize primary plane */
> +	vmw_du_plane_reset(primary);
> +
>  	ret = drm_universal_plane_init(dev, primary,
>  				       0, &vmw_stdu_plane_funcs,
>  				       vmw_primary_plane_formats,
> @@ -1153,6 +1161,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  	}
>  
>  	/* Initialize cursor plane */
> +	vmw_du_plane_reset(cursor);
> +
>  	ret = drm_universal_plane_init(dev, cursor,
>  			0, &vmw_stdu_cursor_funcs,
>  			vmw_cursor_plane_formats,
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 06/11] drm/vmwgfx: Add and connect plane helper functions
  2017-03-27 22:00 ` [PATCH 06/11] drm/vmwgfx: Add and connect plane " Sinclair Yeh
@ 2017-03-28  7:40   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:40 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:00:59PM -0700, Sinclair Yeh wrote:
> Refactor previous FB and cursor plane update code into their
> atomic counterparts: check, update, prepare, cleanup, and disable.
> 
> These helpers won't be called until we flip on the atomic support
> flag or set drm_crtc_funcs->set_config to using the atomic
> helper.
> 
> v2:
> * Removed unnecessary pinning of cursor surface
> * Added a few function headers
> 
> v3:
> * Set clip region equal to the destination region
> * Fixed surface pinning policy
> * Enable SVGA mode in vmw_sou_primary_plane_prepare_fb
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 256 +++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  15 ++
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  66 ++++++++-
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 115 ++++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 244 +++++++++++++++++++++++++++++++++
>  5 files changed, 695 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 6f0f160..d00ff21 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -26,8 +26,10 @@
>   **************************************************************************/
>  
>  #include "vmwgfx_kms.h"
> +#include <drm/drm_plane_helper.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_atomic_helper.h>
> +#include <drm/drm_rect.h>
>  
>  
>  /* Might need a hrtimer here? */
> @@ -399,6 +401,260 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
>  }
>  
>  
> +/**
> + * vmw_du_vps_unpin_surf - unpins resource associated with a framebuffer surface
> + *
> + * @vps: plane state associated with the display surface
> + * @unreference: true if we also want to unreference the display.
> + */
> +void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps,
> +			     bool unreference)
> +{
> +	if (vps->surf) {
> +		if (vps->pinned) {
> +			vmw_resource_unpin(&vps->surf->res);
> +			vps->pinned--;
> +		}
> +
> +		if (unreference) {
> +			if (vps->pinned)
> +				DRM_ERROR("Surface still pinned\n");
> +			vmw_surface_unreference(&vps->surf);
> +		}
> +	}
> +}
> +
> +
> +/**
> + * vmw_du_plane_cleanup_fb - Unpins the cursor
> + *
> + * @plane:  display plane
> + * @old_state: Contains the FB to clean up
> + *
> + * Unpins the framebuffer surface
> + *
> + * Returns 0 on success
> + */
> +void
> +vmw_du_plane_cleanup_fb(struct drm_plane *plane,
> +			struct drm_plane_state *old_state)
> +{
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
> +
> +	vmw_du_plane_unpin_surf(vps, false);
> +}
> +
> +
> +/**
> + * vmw_du_cursor_plane_prepare_fb - Readies the cursor by referencing it
> + *
> + * @plane:  display plane
> + * @new_state: info on the new plane state, including the FB
> + *
> + * Returns 0 on success
> + */
> +int
> +vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
> +			       struct drm_plane_state *new_state)
> +{
> +	struct drm_framebuffer *fb = new_state->fb;
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
> +
> +
> +	if (vps->surf)
> +		vmw_surface_unreference(&vps->surf);
> +
> +	if (vps->dmabuf)
> +		vmw_dmabuf_unreference(&vps->dmabuf);
> +
> +	if (fb) {
> +		if (vmw_framebuffer_to_vfb(fb)->dmabuf) {
> +			vps->dmabuf = vmw_framebuffer_to_vfbd(fb)->buffer;
> +			vmw_dmabuf_reference(vps->dmabuf);
> +		} else {
> +			vps->surf = vmw_framebuffer_to_vfbs(fb)->surface;
> +			vmw_surface_reference(vps->surf);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +
> +void
> +vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
> +				   struct drm_plane_state *old_state)
> +{
> +	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
> +	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> +
> +	drm_atomic_set_fb_for_plane(plane->state, NULL);
> +	vmw_cursor_update_position(dev_priv, false, 0, 0);
> +}
> +
> +
> +void
> +vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
> +				  struct drm_plane_state *old_state)
> +{
> +	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
> +	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> +	struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(plane->state);
> +	s32 hotspot_x, hotspot_y;
> +	int ret = 0;
> +
> +
> +	hotspot_x = du->hotspot_x;
> +	hotspot_y = du->hotspot_y;
> +	du->cursor_surface = vps->surf;
> +	du->cursor_dmabuf = vps->dmabuf;
> +
> +	/* setup new image */
> +	if (vps->surf) {
> +		du->cursor_age = du->cursor_surface->snooper.age;
> +
> +		ret = vmw_cursor_update_image(dev_priv,
> +					      vps->surf->snooper.image,
> +					      64, 64, hotspot_x, hotspot_y);
> +	} else if (vps->dmabuf) {
> +		ret = vmw_cursor_update_dmabuf(dev_priv, vps->dmabuf,
> +					       plane->state->crtc_w,
> +					       plane->state->crtc_h,
> +					       hotspot_x, hotspot_y);
> +	} else {
> +		vmw_cursor_update_position(dev_priv, false, 0, 0);
> +		return;
> +	}
> +
> +	if (!ret) {
> +		du->cursor_x = plane->state->crtc_x + du->set_gui_x;
> +		du->cursor_y = plane->state->crtc_y + du->set_gui_y;
> +
> +		vmw_cursor_update_position(dev_priv, true,
> +					   du->cursor_x + hotspot_x,
> +					   du->cursor_y + hotspot_y);
> +	} else {
> +		DRM_ERROR("Failed to update cursor image\n");
> +	}
> +}
> +
> +
> +/**
> + * vmw_du_primary_plane_atomic_check - check if the new state is okay
> + *
> + * @plane: display plane
> + * @state: info on the new plane state, including the FB
> + *
> + * Check if the new state is settable given the current state.  Other
> + * than what the atomic helper checks, we care about crtc fitting
> + * the FB and maintaining one active framebuffer.
> + *
> + * Returns 0 on success
> + */
> +int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
> +				      struct drm_plane_state *state)
> +{
> +	struct drm_framebuffer *new_fb = state->fb;
> +	bool visible;
> +
> +	struct drm_rect src = {
> +		.x1 = state->src_x,
> +		.y1 = state->src_y,
> +		.x2 = state->src_x + state->src_w,
> +		.y2 = state->src_y + state->src_h,
> +	};
> +	struct drm_rect dest = {
> +		.x1 = state->crtc_x,
> +		.y1 = state->crtc_y,
> +		.x2 = state->crtc_x + state->crtc_w,
> +		.y2 = state->crtc_y + state->crtc_h,
> +	};
> +	struct drm_rect clip = dest;
> +	int ret;
> +
> +	ret = drm_plane_helper_check_update(plane, state->crtc, new_fb,
> +					    &src, &dest, &clip,
> +					    DRM_ROTATE_0,
> +					    DRM_PLANE_HELPER_NO_SCALING,
> +					    DRM_PLANE_HELPER_NO_SCALING,
> +					    false, true, &visible);

There's a new atomic version of this, drm_plane_helper_check_state(), for
less boilerplate.

> +
> +
> +	if (!ret && new_fb) {
> +		struct drm_crtc *crtc = state->crtc;
> +		struct vmw_connector_state *vcs;
> +		struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
> +		struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> +		struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
> +
> +		vcs = vmw_connector_state_to_vcs(du->connector.state);
> +
> +		if ((dest.x2 > new_fb->width ||
> +		     dest.y2 > new_fb->height)) {
> +			DRM_ERROR("CRTC area outside of framebuffer\n");
> +			return -EINVAL;
> +		}
> +
> +		/* Only one active implicit framebuffer at a time. */
> +		mutex_lock(&dev_priv->global_kms_state_mutex);

It hasn't (yet) merged, but my recommendation for global kms state is to
mirror the main atomic framework, i.e.
- state struct, with duplicate/commit semantics
- separate ww_mutex
We should also be merging a new helper for driver private state objects
rsn, to make this pattern a lot easier/direct to implement.

You can make this work too, but since it's a different way of atomic
commit it means more work trying to understand it.
-Daniel

> +		if (vcs->is_implicit && dev_priv->implicit_fb &&
> +		    !(dev_priv->num_implicit == 1 && du->active_implicit)
> +		    && dev_priv->implicit_fb != vfb) {
> +			DRM_ERROR("Multiple implicit framebuffers "
> +				  "not supported.\n");
> +			ret = -EINVAL;
> +		}
> +		mutex_unlock(&dev_priv->global_kms_state_mutex);
> +	}
> +
> +
> +	return ret;
> +}
> +
> +
> +/**
> + * vmw_du_cursor_plane_atomic_check - check if the new state is okay
> + *
> + * @plane: cursor plane
> + * @state: info on the new plane state
> + *
> + * This is a chance to fail if the new cursor state does not fit
> + * our requirements.
> + *
> + * Returns 0 on success
> + */
> +int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
> +				     struct drm_plane_state *new_state)
> +{
> +	int ret = 0;
> +	struct vmw_surface *surface = NULL;
> +	struct drm_framebuffer *fb = new_state->fb;
> +
> +
> +	/* Turning off */
> +	if (!fb)
> +		return ret;
> +
> +	/* A lot of the code assumes this */
> +	if (new_state->crtc_w != 64 || new_state->crtc_h != 64) {
> +		DRM_ERROR("Invalid cursor dimensions (%d, %d)\n",
> +			  new_state->crtc_w, new_state->crtc_h);
> +		ret = -EINVAL;
> +	}
> +
> +	if (!vmw_framebuffer_to_vfb(fb)->dmabuf)
> +		surface = vmw_framebuffer_to_vfbs(fb)->surface;
> +
> +	if (surface && !surface->snooper.image) {
> +		DRM_ERROR("surface not suitable for cursor\n");
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +
>  int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
>  			     struct drm_crtc_state *new_state)
>  {
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index f711b5d..de6a0b6 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -345,10 +345,25 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
>  			       uint32_t src_w, uint32_t src_h);
>  
>  /* Atomic Helpers */
> +int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
> +				      struct drm_plane_state *state);
> +int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
> +				     struct drm_plane_state *state);
> +void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
> +				       struct drm_plane_state *old_state);
> +void vmw_du_cursor_plane_atomic_disable(struct drm_plane *plane,
> +					struct drm_plane_state *old_state);
> +int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
> +				   struct drm_plane_state *new_state);
> +void vmw_du_plane_cleanup_fb(struct drm_plane *plane,
> +			     struct drm_plane_state *old_state);
>  void vmw_du_plane_reset(struct drm_plane *plane);
>  struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
>  void vmw_du_plane_destroy_state(struct drm_plane *plane,
>  				struct drm_plane_state *state);
> +void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps,
> +			     bool unreference);
> +
>  int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
>  			     struct drm_crtc_state *state);
>  void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index d547e80..1d734de 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -234,7 +234,7 @@ static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
>  
>  	ldu = vmw_crtc_to_ldu(crtc);
>  	dev_priv = vmw_priv(crtc->dev);
> -	fb       = crtc->primary->fb;
> +	fb       = crtc->primary->state->fb;
>  
>  	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
>  
> @@ -242,6 +242,8 @@ static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
>  		vmw_ldu_add_active(dev_priv, ldu, vfb);
>  	else
>  		vmw_ldu_del_active(dev_priv, ldu);
> +
> +	vmw_ldu_commit_list(dev_priv);
>  }
>  
>  /**
> @@ -391,6 +393,46 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
>   * Legacy Display Plane Functions
>   */
>  
> +/**
> + * vmw_ldu_primary_plane_cleanup_fb - Unpin fb
> + *
> + * @plane:  display plane
> + * @old_state: Contains the FB to clean up
> + *
> + * Unpins the display surface
> + *
> + * Returns 0 on success
> + */
> +static void
> +vmw_ldu_primary_plane_cleanup_fb(struct drm_plane *plane,
> +				 struct drm_plane_state *old_state)
> +{
> +}
> +
> +
> +/**
> + * vmw_ldu_primary_plane_prepare_fb -
> + *
> + * @plane:  display plane
> + * @new_state: info on the new plane state, including the FB
> + *
> + * Returns 0 on success
> + */
> +static int
> +vmw_ldu_primary_plane_prepare_fb(struct drm_plane *plane,
> +				 struct drm_plane_state *new_state)
> +{
> +	return 0;
> +}
> +
> +
> +static void
> +vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
> +				    struct drm_plane_state *old_state)
> +{
> +}
> +
> +
>  static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
>  	.update_plane = drm_primary_helper_update,
>  	.disable_plane = drm_primary_helper_disable,
> @@ -412,6 +454,22 @@ static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
>  /*
>   * Atomic Helpers
>   */
> +static const struct
> +drm_plane_helper_funcs vmw_ldu_cursor_plane_helper_funcs = {
> +	.atomic_check = vmw_du_cursor_plane_atomic_check,
> +	.atomic_update = vmw_du_cursor_plane_atomic_update,
> +	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
> +	.cleanup_fb = vmw_du_plane_cleanup_fb,
> +};
> +
> +static const struct
> +drm_plane_helper_funcs vmw_ldu_primary_plane_helper_funcs = {
> +	.atomic_check = vmw_du_primary_plane_atomic_check,
> +	.atomic_update = vmw_ldu_primary_plane_atomic_update,
> +	.prepare_fb = vmw_ldu_primary_plane_prepare_fb,
> +	.cleanup_fb = vmw_ldu_primary_plane_cleanup_fb,
> +};
> +
>  static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
>  	.prepare = vmw_ldu_crtc_helper_prepare,
>  	.commit = vmw_ldu_crtc_helper_commit,
> @@ -471,6 +529,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_plane_helper_add(primary, &vmw_ldu_primary_plane_helper_funcs);
> +
>  	/* Initialize cursor plane */
>  	vmw_du_plane_reset(cursor);
>  
> @@ -485,6 +545,10 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_plane_helper_add(cursor, &vmw_ldu_cursor_plane_helper_funcs);
> +
> +
> +	vmw_du_connector_reset(connector);
>  	ret = drm_connector_init(dev, connector, &vmw_legacy_connector_funcs,
>  				 DRM_MODE_CONNECTOR_VIRTUAL);
>  	if (ret) {
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index 662024c..eca055e 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -612,6 +612,100 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
>   * Screen Object Display Plane Functions
>   */
>  
> +/**
> + * vmw_sou_primary_plane_cleanup_fb - Frees sou backing buffer
> + *
> + * @plane:  display plane
> + * @old_state: Contains the FB to clean up
> + *
> + * Unpins the display surface
> + *
> + * Returns 0 on success
> + */
> +static void
> +vmw_sou_primary_plane_cleanup_fb(struct drm_plane *plane,
> +				 struct drm_plane_state *old_state)
> +{
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
> +
> +	vmw_dmabuf_unreference(&vps->dmabuf);
> +	vps->dmabuf_size = 0;
> +
> +	vmw_du_plane_cleanup_fb(plane, old_state);
> +}
> +
> +
> +/**
> + * vmw_sou_primary_plane_prepare_fb - allocate backing buffer
> + *
> + * @plane:  display plane
> + * @new_state: info on the new plane state, including the FB
> + *
> + * The SOU backing buffer is our equivalent of the display plane.
> + *
> + * Returns 0 on success
> + */
> +static int
> +vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane,
> +				 struct drm_plane_state *new_state)
> +{
> +	struct drm_framebuffer *new_fb = new_state->fb;
> +	struct drm_crtc *crtc = plane->state->crtc ?: new_state->crtc;
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
> +	struct vmw_private *dev_priv;
> +	size_t size;
> +	int ret;
> +
> +
> +	if (!new_fb) {
> +		vmw_dmabuf_unreference(&vps->dmabuf);
> +		vps->dmabuf_size = 0;
> +
> +		return 0;
> +	}
> +
> +	size = new_state->crtc_w * new_state->crtc_h * 4;
> +
> +	if (vps->dmabuf) {
> +		if (vps->dmabuf_size == size)
> +			return 0;
> +
> +		vmw_dmabuf_unreference(&vps->dmabuf);
> +		vps->dmabuf_size = 0;
> +	}
> +
> +	vps->dmabuf = kzalloc(sizeof(*vps->dmabuf), GFP_KERNEL);
> +	if (!vps->dmabuf)
> +		return -ENOMEM;
> +
> +	dev_priv = vmw_priv(crtc->dev);
> +	vmw_svga_enable(dev_priv);
> +
> +	/* After we have alloced the backing store might not be able to
> +	 * resume the overlays, this is preferred to failing to alloc.
> +	 */
> +	vmw_overlay_pause_all(dev_priv);
> +	ret = vmw_dmabuf_init(dev_priv, vps->dmabuf, size,
> +			      &vmw_vram_ne_placement,
> +			      false, &vmw_dmabuf_bo_free);
> +	vmw_overlay_resume_all(dev_priv);
> +
> +	if (ret != 0)
> +		vps->dmabuf = NULL; /* vmw_dmabuf_init frees on error */
> +	else
> +		vps->dmabuf_size = size;
> +
> +	return ret;
> +}
> +
> +
> +static void
> +vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
> +				    struct drm_plane_state *old_state)
> +{
> +}
> +
> +
>  static const struct drm_plane_funcs vmw_sou_plane_funcs = {
>  	.update_plane = drm_primary_helper_update,
>  	.disable_plane = drm_primary_helper_disable,
> @@ -633,6 +727,22 @@ static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
>  /*
>   * Atomic Helpers
>   */
> +static const struct
> +drm_plane_helper_funcs vmw_sou_cursor_plane_helper_funcs = {
> +	.atomic_check = vmw_du_cursor_plane_atomic_check,
> +	.atomic_update = vmw_du_cursor_plane_atomic_update,
> +	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
> +	.cleanup_fb = vmw_du_plane_cleanup_fb,
> +};
> +
> +static const struct
> +drm_plane_helper_funcs vmw_sou_primary_plane_helper_funcs = {
> +	.atomic_check = vmw_du_primary_plane_atomic_check,
> +	.atomic_update = vmw_sou_primary_plane_atomic_update,
> +	.prepare_fb = vmw_sou_primary_plane_prepare_fb,
> +	.cleanup_fb = vmw_sou_primary_plane_cleanup_fb,
> +};
> +
>  static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
>  	.prepare = vmw_sou_crtc_helper_prepare,
>  	.commit = vmw_sou_crtc_helper_commit,
> @@ -691,6 +801,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_plane_helper_add(primary, &vmw_sou_primary_plane_helper_funcs);
> +
>  	/* Initialize cursor plane */
>  	vmw_du_plane_reset(cursor);
>  
> @@ -705,6 +817,9 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs);
> +
> +	vmw_du_connector_reset(connector);
>  	ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs,
>  				 DRM_MODE_CONNECTOR_VIRTUAL);
>  	if (ret) {
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index 6e3cfad..cce5e5b 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -1194,6 +1194,230 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
>   * Screen Target Display Plane Functions
>   *****************************************************************************/
>  
> +
> +
> +/**
> + * vmw_stdu_primary_plane_cleanup_fb - Unpins the display surface
> + *
> + * @plane:  display plane
> + * @old_state: Contains the FB to clean up
> + *
> + * Unpins the display surface
> + *
> + * Returns 0 on success
> + */
> +static void
> +vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
> +				  struct drm_plane_state *old_state)
> +{
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
> +
> +	if (vps->surf)
> +		WARN_ON(!vps->pinned);
> +
> +	vmw_du_plane_cleanup_fb(plane, old_state);
> +
> +	vps->content_fb_type = SAME_AS_DISPLAY;
> +}
> +
> +
> +
> +/**
> + * vmw_stdu_primary_plane_prepare_fb - Readies the display surface
> + *
> + * @plane:  display plane
> + * @new_state: info on the new plane state, including the FB
> + *
> + * This function allocates a new display surface if the content is
> + * backed by a DMA.  The display surface is pinned here, and it'll
> + * be unpinned in .cleanup_fb()
> + *
> + * Returns 0 on success
> + */
> +static int
> +vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
> +				  struct drm_plane_state *new_state)
> +{
> +	struct drm_framebuffer *new_fb = new_state->fb;
> +	struct vmw_framebuffer *vfb;
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
> +	enum stdu_content_type new_content_type;
> +	struct vmw_framebuffer_surface *new_vfbs;
> +	struct drm_crtc *crtc = new_state->crtc;
> +	uint32_t hdisplay = new_state->crtc_w, vdisplay = new_state->crtc_h;
> +	int ret;
> +
> +	/* No FB to prepare */
> +	if (!new_fb) {
> +		if (vps->surf) {
> +			WARN_ON(vps->pinned != 0);
> +			vmw_surface_unreference(&vps->surf);
> +		}
> +
> +		return 0;
> +	}
> +
> +	vfb = vmw_framebuffer_to_vfb(new_fb);
> +	new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
> +
> +	if (new_vfbs && new_vfbs->surface->base_size.width == hdisplay &&
> +	    new_vfbs->surface->base_size.height == vdisplay)
> +		new_content_type = SAME_AS_DISPLAY;
> +	else if (vfb->dmabuf)
> +		new_content_type = SEPARATE_DMA;
> +	else
> +		new_content_type = SEPARATE_SURFACE;
> +
> +	if (new_content_type != SAME_AS_DISPLAY) {
> +		struct vmw_surface content_srf;
> +		struct drm_vmw_size display_base_size = {0};
> +
> +		display_base_size.width  = hdisplay;
> +		display_base_size.height = vdisplay;
> +		display_base_size.depth  = 1;
> +
> +		/*
> +		 * If content buffer is a DMA buf, then we have to construct
> +		 * surface info
> +		 */
> +		if (new_content_type == SEPARATE_DMA) {
> +
> +			switch (new_fb->format->cpp[0]*8) {
> +			case 32:
> +				content_srf.format = SVGA3D_X8R8G8B8;
> +				break;
> +
> +			case 16:
> +				content_srf.format = SVGA3D_R5G6B5;
> +				break;
> +
> +			case 8:
> +				content_srf.format = SVGA3D_P8;
> +				break;
> +
> +			default:
> +				DRM_ERROR("Invalid format\n");
> +				return -EINVAL;
> +			}
> +
> +			content_srf.flags             = 0;
> +			content_srf.mip_levels[0]     = 1;
> +			content_srf.multisample_count = 0;
> +		} else {
> +			content_srf = *new_vfbs->surface;
> +		}
> +
> +		if (vps->surf) {
> +			struct drm_vmw_size cur_base_size = vps->surf->base_size;
> +
> +			if (cur_base_size.width != display_base_size.width ||
> +			    cur_base_size.height != display_base_size.height ||
> +			    vps->surf->format != content_srf.format) {
> +				WARN_ON(vps->pinned != 0);
> +				vmw_surface_unreference(&vps->surf);
> +			}
> +
> +		}
> +
> +		if (!vps->surf) {
> +			ret = vmw_surface_gb_priv_define
> +				(crtc->dev,
> +				 /* Kernel visible only */
> +				 0,
> +				 content_srf.flags,
> +				 content_srf.format,
> +				 true,  /* a scanout buffer */
> +				 content_srf.mip_levels[0],
> +				 content_srf.multisample_count,
> +				 0,
> +				 display_base_size,
> +				 &vps->surf);
> +			if (ret != 0) {
> +				DRM_ERROR("Couldn't allocate STDU surface.\n");
> +				return ret;
> +			}
> +		}
> +	} else {
> +		/*
> +		 * prepare_fb and clean_fb should only take care of pinning
> +		 * and unpinning.  References are tracked by state objects.
> +		 * The only time we add a reference in prepare_fb is if the
> +		 * state object doesn't have a reference to begin with
> +		 */
> +		if (vps->surf) {
> +			WARN_ON(vps->pinned != 0);
> +			vmw_surface_unreference(&vps->surf);
> +		}
> +
> +		vps->surf = vmw_surface_reference(new_vfbs->surface);
> +	}
> +
> +	if (vps->surf) {
> +
> +		/* Pin new surface before flipping */
> +		ret = vmw_resource_pin(&vps->surf->res, false);
> +		if (ret)
> +			goto out_srf_unref;
> +
> +		vps->pinned++;
> +	}
> +
> +	vps->content_fb_type = new_content_type;
> +	return 0;
> +
> +out_srf_unref:
> +	vmw_surface_unreference(&vps->surf);
> +	return ret;
> +}
> +
> +
> +
> +/**
> + * vmw_stdu_primary_plane_atomic_update - formally switches STDU to new plane
> + *
> + * @plane: display plane
> + * @old_state: Only used to get crtc info
> + *
> + * Formally update stdu->display_srf to the new plane, and bind the new
> + * plane STDU.  This function is called during the commit phase when
> + * all the preparation have been done and all the configurations have
> + * been checked.
> + */
> +static void
> +vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
> +				     struct drm_plane_state *old_state)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_screen_target_display_unit *stdu;
> +	struct vmw_plane_state *vps = vmw_plane_state_to_vps(plane->state);
> +	struct drm_crtc *crtc = plane->state->crtc ?: old_state->crtc;
> +	int ret;
> +
> +	stdu     = vmw_crtc_to_stdu(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +
> +	stdu->display_srf = vps->surf;
> +	stdu->content_fb_type = vps->content_fb_type;
> +
> +	if (!stdu->defined)
> +		return;
> +
> +	if (plane->state->fb)
> +		ret = vmw_stdu_bind_st(dev_priv, stdu, &stdu->display_srf->res);
> +	else
> +		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
> +
> +	/*
> +	 * We cannot really fail this function, so if we do, then output an
> +	 * error and quit
> +	 */
> +	if (ret)
> +		DRM_ERROR("Failed to bind surface to STDU.\n");
> +	else
> +		crtc->primary->fb = plane->state->fb;
> +}
> +
> +
>  static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
>  	.update_plane = drm_primary_helper_update,
>  	.disable_plane = drm_primary_helper_disable,
> @@ -1216,6 +1440,22 @@ static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
>  /*
>   * Atomic Helpers
>   */
> +static const struct
> +drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = {
> +	.atomic_check = vmw_du_cursor_plane_atomic_check,
> +	.atomic_update = vmw_du_cursor_plane_atomic_update,
> +	.prepare_fb = vmw_du_cursor_plane_prepare_fb,
> +	.cleanup_fb = vmw_du_plane_cleanup_fb,
> +};
> +
> +static const struct
> +drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = {
> +	.atomic_check = vmw_du_primary_plane_atomic_check,
> +	.atomic_update = vmw_stdu_primary_plane_atomic_update,
> +	.prepare_fb = vmw_stdu_primary_plane_prepare_fb,
> +	.cleanup_fb = vmw_stdu_primary_plane_cleanup_fb,
> +};
> +
>  static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
>  	.prepare = vmw_stdu_crtc_helper_prepare,
>  	.commit = vmw_stdu_crtc_helper_commit,
> @@ -1283,6 +1523,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_plane_helper_add(primary, &vmw_stdu_primary_plane_helper_funcs);
> +
>  	/* Initialize cursor plane */
>  	vmw_du_plane_reset(cursor);
>  
> @@ -1297,6 +1539,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_plane_helper_add(cursor, &vmw_stdu_cursor_plane_helper_funcs);
> +
>  	vmw_du_connector_reset(connector);
>  
>  	ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs,
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 07/11] drm/vmwgfx: Add and connect connector helper function
  2017-03-27 22:01 ` [PATCH 07/11] drm/vmwgfx: Add and connect connector helper function Sinclair Yeh
@ 2017-03-28  7:41   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:41 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:01:00PM -0700, Sinclair Yeh wrote:
> Since the link between connector and encoder is always fixed in our case,
> just return the one encoder.
> 
> These helpers won't be called until we flip on the atomic support
> flag or set drm_crtc_funcs->set_config to using the atomic
> helper.
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  | 18 ++++++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |  2 ++
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  7 +++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c |  9 +++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  8 ++++++++
>  5 files changed, 44 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index d00ff21..2250a34a 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -2223,6 +2223,24 @@ vmw_du_connector_atomic_get_property(struct drm_connector *connector,
>  }
>  
>  
> +/**
> + * vmw_du_connector_best_encoder - there's only one
> + *
> + * @connector - connector the property is associated with
> + *
> + * In our case, there is only one encoder per connector
> + */
> +struct drm_encoder *
> +vmw_du_connector_best_encoder(struct drm_connector *connector)
> +{
> +	struct vmw_display_unit *du;
> +
> +	du = vmw_connector_to_du(connector);
> +
> +	return &du->encoder;
> +}

Please just use drm_atomic_helper_best_encoder.
-Daniel

> +
> +
>  int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
>  				struct drm_file *file_priv)
>  {
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index de6a0b6..3251562 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -267,6 +267,8 @@ vmw_du_connector_atomic_get_property(struct drm_connector *connector,
>  				     const struct drm_connector_state *state,
>  				     struct drm_property *property,
>  				     uint64_t *val);
> +struct drm_encoder *
> +vmw_du_connector_best_encoder(struct drm_connector *connector);
>  int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
>  void vmw_du_connector_save(struct drm_connector *connector);
>  void vmw_du_connector_restore(struct drm_connector *connector);
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index 1d734de..282a0ef 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -389,6 +389,11 @@ static const struct drm_connector_funcs vmw_legacy_connector_funcs = {
>  	.atomic_get_property = vmw_du_connector_atomic_get_property,
>  };
>  
> +static const struct
> +drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = {
> +	.best_encoder = vmw_du_connector_best_encoder,
> +};
> +
>  /*
>   * Legacy Display Plane Functions
>   */
> @@ -555,6 +560,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  		DRM_ERROR("Failed to initialize connector\n");
>  		goto err_free;
>  	}
> +
> +	drm_connector_helper_add(connector, &vmw_ldu_connector_helper_funcs);
>  	connector->status = vmw_du_connector_detect(connector, true);
>  	vmw_connector_state_to_vcs(connector->state)->is_implicit = true;
>  
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index eca055e..e4154f1 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -608,6 +608,14 @@ static const struct drm_connector_funcs vmw_sou_connector_funcs = {
>  	.atomic_get_property = vmw_du_connector_atomic_get_property,
>  };
>  
> +
> +static const struct
> +drm_connector_helper_funcs vmw_sou_connector_helper_funcs = {
> +	.best_encoder = vmw_du_connector_best_encoder,
> +};
> +
> +
> +
>  /*
>   * Screen Object Display Plane Functions
>   */
> @@ -827,6 +835,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free;
>  	}
>  
> +	drm_connector_helper_add(connector, &vmw_sou_connector_helper_funcs);
>  	connector->status = vmw_du_connector_detect(connector, true);
>  	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
>  
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index cce5e5b..708d063 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -1189,6 +1189,12 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = {
>  };
>  
>  
> +static const struct
> +drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = {
> +	.best_encoder = vmw_du_connector_best_encoder,
> +};
> +
> +
>  
>  /******************************************************************************
>   * Screen Target Display Plane Functions
> @@ -1549,6 +1555,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  		DRM_ERROR("Failed to initialize connector\n");
>  		goto err_free;
>  	}
> +
> +	drm_connector_helper_add(connector, &vmw_stdu_connector_helper_funcs);
>  	connector->status = vmw_du_connector_detect(connector, false);
>  	vmw_connector_state_to_vcs(connector->state)->is_implicit = false;
>  
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 08/11] drm/vmwgfx: Add and connect atomic state object check/commit
  2017-03-27 22:01 ` [PATCH 08/11] drm/vmwgfx: Add and connect atomic state object check/commit Sinclair Yeh
@ 2017-03-28  7:45   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:45 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:01:01PM -0700, Sinclair Yeh wrote:
> This connects the main state object check and commit function.
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 66 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 2250a34a..6b593aaf 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -1581,8 +1581,74 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
>  	return &vfb->base;
>  }
>  
> +
> +
> +/**
> + * vmw_kms_atomic_check_modeset- validate state object for modeset changes
> + *
> + * @dev: DRM device
> + * @state: the driver state object
> + *
> + * This is a simple wrapper around drm_atomic_helper_check_modeset() for
> + * us to assign a value to mode->crtc_clock so that
> + * drm_calc_timestamping_constants() won't throw an error message
> + *
> + * RETURNS
> + * Zero for success or -errno
> + */
> +int
> +vmw_kms_atomic_check_modeset(struct drm_device *dev,
> +			     struct drm_atomic_state *state)
> +{
> +	struct drm_crtc_state *crtc_state;
> +	struct drm_crtc *crtc;
> +	int i, ret;
> +
> +
> +	for_each_crtc_in_state(state, crtc, crtc_state, i) {
> +		if (crtc_state->mode.crtc_clock == 0) {
> +			/*
> +			 * Our virtual device does not have a dot clock,
> +			 * so use the logical clock value as the dot clock.
> +			 */
> +			crtc_state->mode.crtc_clock = crtc_state->mode.clock;

Can't you stuff this into your crtc->atomic_check function? At least I
don't see a depency here ... With that you could forgo this vmw version of
atomic_commit.

> +		}
> +	}
> +
> +	ret = drm_atomic_helper_check_modeset(dev, state);
> +	if (ret)
> +		return ret;
> +
> +	return drm_atomic_helper_check_planes(dev, state);
> +}
> +
> +
> +/**
> + * vmw_kms_atomic_commit - Perform an atomic state commit
> + *
> + * @dev: DRM device
> + * @state: the driver state object
> + * @nonblock: Whether nonblocking behaviour is requested
> + *
> + * This is a simple wrapper around drm_atomic_helper_commit() for
> + * us to clear the nonblocking value.
> + * Nonblocking commits should avoid waiting on GPU completion to return.
> + * That is always the case for us.

That's not all they do, they also avoid any other stalls. Atomic can do an
entire modeset in nonblocking mode.

Since the helpers provide you nonblocking commit for essentially for free
there's also no reason anymore to clear this, or at least I think it
should be a lot better than the one given here :-)
-Daniel

> + *
> + * RETURNS
> + * Zero for success or negative error code on failure.
> + */
> +int vmw_kms_atomic_commit(struct drm_device *dev,
> +			  struct drm_atomic_state *state,
> +			  bool nonblock)
> +{
> +	return drm_atomic_helper_commit(dev, state, false);
> +}
> +
>  static const struct drm_mode_config_funcs vmw_kms_funcs = {
>  	.fb_create = vmw_kms_fb_create,
> +	.atomic_check = vmw_kms_atomic_check_modeset,
> +	.atomic_commit = vmw_kms_atomic_commit,
>  };
>  
>  static int vmw_kms_generic_present(struct vmw_private *dev_priv,
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU
  2017-03-27 22:01 ` [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU Sinclair Yeh
@ 2017-03-28  7:49   ` Daniel Vetter
  2017-03-29 21:05     ` Sinclair Yeh
  0 siblings, 1 reply; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:49 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:01:03PM -0700, Sinclair Yeh wrote:
> Switch over to using internal atomic API for mode set.
> 
> This removes the legacy set_config API, replacing it with
> drm_atomic_helper_set_config().  The DRM helper will use various
> vmwgfx-specific atomic functions to set a mode.
> 
> DRIVER_ATOMIC capability flag is not yet set, so the user mode
> will still use the legacy mode set IOCTL.
> 
> v2:
> * Avoid a clash between page-flip pinning and setcrtc pinning, modify
> the page-flip code to use the page-flip helper and the atomic callbacks.
> To enable this, we will need to add a wrapper around atomic_commit.
> 
> * Add vmw_kms_set_config() to work around vmwgfx xorg driver bug
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  20 +++
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   1 +
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 325 ++++-------------------------------
>  3 files changed, 51 insertions(+), 295 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 6b593aaf..7104796 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -2923,3 +2923,23 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
>  					  "implicit_placement", 0, 1);
>  
>  }
> +
> +
> +/**
> + * vmw_kms_set_config - Wrapper around drm_atomic_helper_set_config
> + *
> + * @set: The configuration to set.
> + *
> + * The vmwgfx Xorg driver doesn't assign the mode::type member, which
> + * when drm_mode_set_crtcinfo is called as part of the configuration setting
> + * causes it to return incorrect crtc dimensions causing severe problems in
> + * the vmwgfx modesetting. So explicitly clear that member before calling
> + * into drm_atomic_helper_set_config.
> + */
> +int vmw_kms_set_config(struct drm_mode_set *set)
> +{
> +	if (set && set->mode)
> +		set->mode->type = 0;

ugh :( Looking at set_crtcinfo the only thing I can see it look at ->type
is to check for built-in modes. Not a single driver is using that afaics,
we might as well remove this and and void the vmw special case here too.
-Daniel

> +
> +	return drm_atomic_helper_set_config(set);
> +}
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index 3251562..0016f07 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -451,5 +451,6 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
>  		     bool to_surface,
>  		     bool interruptible);
>  
> +int vmw_kms_set_config(struct drm_mode_set *set);
>  
>  #endif
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index 708d063..ff00817 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -104,8 +104,7 @@ struct vmw_stdu_surface_copy {
>   */
>  struct vmw_screen_target_display_unit {
>  	struct vmw_display_unit base;
> -
> -	struct vmw_surface     *display_srf;
> +	const struct vmw_surface *display_srf;
>  	enum stdu_content_type content_fb_type;
>  
>  	bool defined;
> @@ -118,32 +117,6 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu);
>  
>  
>  /******************************************************************************
> - * Screen Target Display Unit helper Functions
> - *****************************************************************************/
> -
> -/**
> - * vmw_stdu_unpin_display - unpins the resource associated with display surface
> - *
> - * @stdu: contains the display surface
> - *
> - * If the display surface was privatedly allocated by
> - * vmw_surface_gb_priv_define() and not registered as a framebuffer, then it
> - * won't be automatically cleaned up when all the framebuffers are freed.  As
> - * such, we have to explicitly call vmw_resource_unreference() to get it freed.
> - */
> -static void vmw_stdu_unpin_display(struct vmw_screen_target_display_unit *stdu)
> -{
> -	if (stdu->display_srf) {
> -		struct vmw_resource *res = &stdu->display_srf->res;
> -
> -		vmw_resource_unpin(res);
> -		vmw_surface_unreference(&stdu->display_srf);
> -	}
> -}
> -
> -
> -
> -/******************************************************************************
>   * Screen Target Display Unit CRTC Functions
>   *****************************************************************************/
>  
> @@ -228,7 +201,7 @@ static int vmw_stdu_define_st(struct vmw_private *dev_priv,
>   */
>  static int vmw_stdu_bind_st(struct vmw_private *dev_priv,
>  			    struct vmw_screen_target_display_unit *stdu,
> -			    struct vmw_resource *res)
> +			    const struct vmw_resource *res)
>  {
>  	SVGA3dSurfaceImageId image;
>  
> @@ -377,129 +350,6 @@ static int vmw_stdu_destroy_st(struct vmw_private *dev_priv,
>  	return ret;
>  }
>  
> -/**
> - * vmw_stdu_bind_fb - Bind an fb to a defined screen target
> - *
> - * @dev_priv: Pointer to a device private struct.
> - * @crtc: The crtc holding the screen target.
> - * @mode: The mode currently used by the screen target. Must be non-NULL.
> - * @new_fb: The new framebuffer to bind. Must be non-NULL.
> - *
> - * RETURNS:
> - * 0 on success, error code on failure.
> - */
> -static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
> -			    struct drm_crtc *crtc,
> -			    struct drm_display_mode *mode,
> -			    struct drm_framebuffer *new_fb)
> -{
> -	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
> -	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
> -	struct vmw_surface *new_display_srf = NULL;
> -	enum stdu_content_type new_content_type;
> -	struct vmw_framebuffer_surface *new_vfbs;
> -	int ret;
> -
> -	WARN_ON_ONCE(!stdu->defined);
> -
> -	new_vfbs = (vfb->dmabuf) ? NULL : vmw_framebuffer_to_vfbs(new_fb);
> -
> -	if (new_vfbs && new_vfbs->surface->base_size.width == mode->hdisplay &&
> -	    new_vfbs->surface->base_size.height == mode->vdisplay)
> -		new_content_type = SAME_AS_DISPLAY;
> -	else if (vfb->dmabuf)
> -		new_content_type = SEPARATE_DMA;
> -	else
> -		new_content_type = SEPARATE_SURFACE;
> -
> -	if (new_content_type != SAME_AS_DISPLAY &&
> -	    !stdu->display_srf) {
> -		struct vmw_surface content_srf;
> -		struct drm_vmw_size display_base_size = {0};
> -
> -		display_base_size.width  = mode->hdisplay;
> -		display_base_size.height = mode->vdisplay;
> -		display_base_size.depth  = 1;
> -
> -		/*
> -		 * If content buffer is a DMA buf, then we have to construct
> -		 * surface info
> -		 */
> -		if (new_content_type == SEPARATE_DMA) {
> -
> -			switch (new_fb->format->cpp[0] * 8) {
> -			case 32:
> -				content_srf.format = SVGA3D_X8R8G8B8;
> -				break;
> -
> -			case 16:
> -				content_srf.format = SVGA3D_R5G6B5;
> -				break;
> -
> -			case 8:
> -				content_srf.format = SVGA3D_P8;
> -				break;
> -
> -			default:
> -				DRM_ERROR("Invalid format\n");
> -				return -EINVAL;
> -			}
> -
> -			content_srf.flags             = 0;
> -			content_srf.mip_levels[0]     = 1;
> -			content_srf.multisample_count = 0;
> -		} else {
> -			content_srf = *new_vfbs->surface;
> -		}
> -
> -
> -		ret = vmw_surface_gb_priv_define(crtc->dev,
> -				0, /* because kernel visible only */
> -				content_srf.flags,
> -				content_srf.format,
> -				true, /* a scanout buffer */
> -				content_srf.mip_levels[0],
> -				content_srf.multisample_count,
> -				0,
> -				display_base_size,
> -				&new_display_srf);
> -		if (unlikely(ret != 0)) {
> -			DRM_ERROR("Could not allocate screen target surface.\n");
> -			return ret;
> -		}
> -	} else if (new_content_type == SAME_AS_DISPLAY) {
> -		new_display_srf = vmw_surface_reference(new_vfbs->surface);
> -	}
> -
> -	if (new_display_srf) {
> -		/* Pin new surface before flipping */
> -		ret = vmw_resource_pin(&new_display_srf->res, false);
> -		if (ret)
> -			goto out_srf_unref;
> -
> -		ret = vmw_stdu_bind_st(dev_priv, stdu, &new_display_srf->res);
> -		if (ret)
> -			goto out_srf_unpin;
> -
> -		/* Unpin and unreference old surface */
> -		vmw_stdu_unpin_display(stdu);
> -
> -		/* Transfer the reference */
> -		stdu->display_srf = new_display_srf;
> -		new_display_srf = NULL;
> -	}
> -
> -	crtc->primary->fb = new_fb;
> -	stdu->content_fb_type = new_content_type;
> -	return 0;
> -
> -out_srf_unpin:
> -	vmw_resource_unpin(&new_display_srf->res);
> -out_srf_unref:
> -	vmw_surface_unreference(&new_display_srf);
> -	return ret;
> -}
> -
>  
>  /**
>   * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
> @@ -601,136 +451,6 @@ static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc)
>  }
>  
>  /**
> - * vmw_stdu_crtc_set_config - Sets a mode
> - *
> - * @set:  mode parameters
> - *
> - * This function is the device-specific portion of the DRM CRTC mode set.
> - * For the SVGA device, we do this by defining a Screen Target, binding a
> - * GB Surface to that target, and finally update the screen target.
> - *
> - * RETURNS:
> - * 0 on success, error code otherwise
> - */
> -static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
> -{
> -	struct vmw_private *dev_priv;
> -	struct vmw_framebuffer *vfb;
> -	struct vmw_screen_target_display_unit *stdu;
> -	struct drm_display_mode *mode;
> -	struct drm_framebuffer  *new_fb;
> -	struct drm_crtc      *crtc;
> -	struct drm_encoder   *encoder;
> -	struct drm_connector *connector;
> -	bool turning_off;
> -	int    ret;
> -
> -
> -	if (!set || !set->crtc)
> -		return -EINVAL;
> -
> -	crtc     = set->crtc;
> -	stdu     = vmw_crtc_to_stdu(crtc);
> -	mode     = set->mode;
> -	new_fb   = set->fb;
> -	dev_priv = vmw_priv(crtc->dev);
> -	turning_off = set->num_connectors == 0 || !mode || !new_fb;
> -	vfb = (new_fb) ? vmw_framebuffer_to_vfb(new_fb) : NULL;
> -
> -	if (set->num_connectors > 1) {
> -		DRM_ERROR("Too many connectors\n");
> -		return -EINVAL;
> -	}
> -
> -	if (set->num_connectors == 1 &&
> -	    set->connectors[0] != &stdu->base.connector) {
> -		DRM_ERROR("Connectors don't match %p %p\n",
> -			set->connectors[0], &stdu->base.connector);
> -		return -EINVAL;
> -	}
> -
> -	if (!turning_off && (set->x + mode->hdisplay > new_fb->width ||
> -			     set->y + mode->vdisplay > new_fb->height)) {
> -		DRM_ERROR("Set outside of framebuffer\n");
> -		return -EINVAL;
> -	}
> -
> -	/* Only one active implicit frame-buffer at a time. */
> -	mutex_lock(&dev_priv->global_kms_state_mutex);
> -	if (!turning_off && stdu->base.is_implicit && dev_priv->implicit_fb &&
> -	    !(dev_priv->num_implicit == 1 && stdu->base.active_implicit)
> -	    && dev_priv->implicit_fb != vfb) {
> -		mutex_unlock(&dev_priv->global_kms_state_mutex);
> -		DRM_ERROR("Multiple implicit framebuffers not supported.\n");
> -		return -EINVAL;
> -	}
> -	mutex_unlock(&dev_priv->global_kms_state_mutex);
> -
> -	/* Since they always map one to one these are safe */
> -	connector = &stdu->base.connector;
> -	encoder   = &stdu->base.encoder;
> -
> -	if (stdu->defined) {
> -		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
> -		if (ret)
> -			return ret;
> -
> -		vmw_stdu_unpin_display(stdu);
> -		(void) vmw_stdu_update_st(dev_priv, stdu);
> -		vmw_kms_del_active(dev_priv, &stdu->base);
> -
> -		ret = vmw_stdu_destroy_st(dev_priv, stdu);
> -		if (ret)
> -			return ret;
> -
> -		crtc->primary->fb = NULL;
> -		crtc->enabled = false;
> -		encoder->crtc = NULL;
> -		connector->encoder = NULL;
> -		stdu->content_fb_type = SAME_AS_DISPLAY;
> -		crtc->x = set->x;
> -		crtc->y = set->y;
> -	}
> -
> -	if (turning_off)
> -		return 0;
> -
> -	/*
> -	 * Steps to displaying a surface, assume surface is already
> -	 * bound:
> -	 *   1.  define a screen target
> -	 *   2.  bind a fb to the screen target
> -	 *   3.  update that screen target (this is done later by
> -	 *       vmw_kms_stdu_do_surface_dirty_or_present)
> -	 */
> -	/*
> -	 * Note on error handling: We can't really restore the crtc to
> -	 * it's original state on error, but we at least update the
> -	 * current state to what's submitted to hardware to enable
> -	 * future recovery.
> -	 */
> -	vmw_svga_enable(dev_priv);
> -	ret = vmw_stdu_define_st(dev_priv, stdu, mode, set->x, set->y);
> -	if (ret)
> -		return ret;
> -
> -	crtc->x = set->x;
> -	crtc->y = set->y;
> -	crtc->mode = *mode;
> -
> -	ret = vmw_stdu_bind_fb(dev_priv, crtc, mode, new_fb);
> -	if (ret)
> -		return ret;
> -
> -	vmw_kms_add_active(dev_priv, &stdu->base, vfb);
> -	crtc->enabled = true;
> -	connector->encoder = encoder;
> -	encoder->crtc      = crtc;
> -
> -	return 0;
> -}
> -
> -/**
>   * vmw_stdu_crtc_page_flip - Binds a buffer to a screen target
>   *
>   * @crtc: CRTC to attach FB to
> @@ -756,9 +476,9 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
>  
>  {
>  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
> -	struct vmw_screen_target_display_unit *stdu;
> -	struct drm_vmw_rect vclips;
> +	struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc);
>  	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
> +	struct drm_vmw_rect vclips;
>  	int ret;
>  
>  	dev_priv          = vmw_priv(crtc->dev);
> @@ -767,25 +487,42 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
>  	if (!stdu->defined || !vmw_kms_crtc_flippable(dev_priv, crtc))
>  		return -EINVAL;
>  
> -	ret = vmw_stdu_bind_fb(dev_priv, crtc, &crtc->mode, new_fb);
> -	if (ret)
> +	/*
> +	 * We're always async, but the helper doesn't know how to set async
> +	 * so lie to the helper. Also, the helper expects someone
> +	 * to pick the event up from the crtc state, and if nobody does,
> +	 * it will free it. Since we handle the event in this function,
> +	 * don't hand it to the helper.
> +	 */
> +	flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
> +	ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
> +	if (ret) {
> +		DRM_ERROR("Page flip error %d.\n", ret);
>  		return ret;
> +	}
>  
>  	if (stdu->base.is_implicit)
>  		vmw_kms_update_implicit_fb(dev_priv, crtc);
>  
> +	/*
> +	 * Now that we've bound a new surface to the screen target,
> +	 * update the contents.
> +	 */
>  	vclips.x = crtc->x;
>  	vclips.y = crtc->y;
>  	vclips.w = crtc->mode.hdisplay;
>  	vclips.h = crtc->mode.vdisplay;
> +
>  	if (vfb->dmabuf)
>  		ret = vmw_kms_stdu_dma(dev_priv, NULL, vfb, NULL, NULL, &vclips,
>  				       1, 1, true, false);
>  	else
>  		ret = vmw_kms_stdu_surface_dirty(dev_priv, vfb, NULL, &vclips,
>  						 NULL, 0, 0, 1, 1, NULL);
> -	if (ret)
> +	if (ret) {
> +		DRM_ERROR("Page flip update error %d.\n", ret);
>  		return ret;
> +	}
>  
>  	if (event) {
>  		struct vmw_fence_obj *fence = NULL;
> @@ -802,7 +539,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
>  						   true);
>  		vmw_fence_obj_unreference(&fence);
>  	} else {
> -		vmw_fifo_flush(dev_priv, false);
> +		(void) vmw_fifo_flush(dev_priv, false);
>  	}
>  
>  	return 0;
> @@ -1123,7 +860,7 @@ static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
>  	.reset = vmw_du_crtc_reset,
>  	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
>  	.atomic_destroy_state = vmw_du_crtc_destroy_state,
> -	.set_config = vmw_stdu_crtc_set_config,
> +	.set_config = vmw_kms_set_config,
>  	.page_flip = vmw_stdu_crtc_page_flip,
>  };
>  
> @@ -1425,8 +1162,8 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
>  
>  
>  static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
> -	.update_plane = drm_primary_helper_update,
> -	.disable_plane = drm_primary_helper_disable,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
>  	.destroy = vmw_du_primary_plane_destroy,
>  	.reset = vmw_du_plane_reset,
>  	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> @@ -1434,8 +1171,8 @@ static const struct drm_plane_funcs vmw_stdu_plane_funcs = {
>  };
>  
>  static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
> -	.update_plane = vmw_du_cursor_plane_update,
> -	.disable_plane = vmw_du_cursor_plane_disable,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
>  	.destroy = vmw_du_cursor_plane_destroy,
>  	.reset = vmw_du_plane_reset,
>  	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> @@ -1625,8 +1362,6 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>   */
>  static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu)
>  {
> -	vmw_stdu_unpin_display(stdu);
> -
>  	vmw_du_cleanup(&stdu->base);
>  	kfree(stdu);
>  }
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 11/11] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU
  2017-03-27 22:01 ` [PATCH 11/11] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU Sinclair Yeh
@ 2017-03-28  7:51   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:51 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:01:04PM -0700, Sinclair Yeh wrote:
> Switch over to internal atomic API.  This completes the atomic
> internal atomic switch for all the Display Units.
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  | 103 ++---------------
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 217 +++--------------------------------
>  2 files changed, 25 insertions(+), 295 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index 282a0ef..4954f26 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -95,7 +95,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
>  
>  		if (crtc == NULL)
>  			return 0;
> -		fb = entry->base.crtc.primary->fb;
> +		fb = entry->base.crtc.primary->state->fb;
>  
>  		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
>  					  fb->format->cpp[0] * 8,
> @@ -104,7 +104,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv)
>  
>  	if (!list_empty(&lds->active)) {
>  		entry = list_entry(lds->active.next, typeof(*entry), active);
> -		fb = entry->base.crtc.primary->fb;
> +		fb = entry->base.crtc.primary->state->fb;
>  
>  		vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0],
>  				   fb->format->cpp[0] * 8, fb->format->depth);
> @@ -255,102 +255,13 @@ static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc)
>  {
>  }
>  
> -static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
> -{
> -	struct vmw_private *dev_priv;
> -	struct vmw_legacy_display_unit *ldu;
> -	struct drm_connector *connector;
> -	struct drm_display_mode *mode;
> -	struct drm_encoder *encoder;
> -	struct vmw_framebuffer *vfb;
> -	struct drm_framebuffer *fb;
> -	struct drm_crtc *crtc;
> -
> -	if (!set)
> -		return -EINVAL;
> -
> -	if (!set->crtc)
> -		return -EINVAL;
> -
> -	/* get the ldu */
> -	crtc = set->crtc;
> -	ldu = vmw_crtc_to_ldu(crtc);
> -	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
> -	dev_priv = vmw_priv(crtc->dev);
> -
> -	if (set->num_connectors > 1) {
> -		DRM_ERROR("to many connectors\n");
> -		return -EINVAL;
> -	}
> -
> -	if (set->num_connectors == 1 &&
> -	    set->connectors[0] != &ldu->base.connector) {
> -		DRM_ERROR("connector doesn't match %p %p\n",
> -			set->connectors[0], &ldu->base.connector);
> -		return -EINVAL;
> -	}
> -
> -	/* ldu only supports one fb active at the time */
> -	if (dev_priv->ldu_priv->fb && vfb &&
> -	    !(dev_priv->ldu_priv->num_active == 1 &&
> -	      !list_empty(&ldu->active)) &&
> -	    dev_priv->ldu_priv->fb != vfb) {
> -		DRM_ERROR("Multiple framebuffers not supported\n");
> -		return -EINVAL;
> -	}
> -
> -	/* since they always map one to one these are safe */
> -	connector = &ldu->base.connector;
> -	encoder = &ldu->base.encoder;
> -
> -	/* should we turn the crtc off? */
> -	if (set->num_connectors == 0 || !set->mode || !set->fb) {
> -
> -		connector->encoder = NULL;
> -		encoder->crtc = NULL;
> -		crtc->primary->fb = NULL;
> -		crtc->enabled = false;
> -
> -		vmw_ldu_del_active(dev_priv, ldu);
> -
> -		return vmw_ldu_commit_list(dev_priv);
> -	}
> -
> -
> -	/* we now know we want to set a mode */
> -	mode = set->mode;
> -	fb = set->fb;
> -
> -	if (set->x + mode->hdisplay > fb->width ||
> -	    set->y + mode->vdisplay > fb->height) {
> -		DRM_ERROR("set outside of framebuffer\n");
> -		return -EINVAL;
> -	}
> -
> -	vmw_svga_enable(dev_priv);
> -
> -	crtc->primary->fb = fb;
> -	encoder->crtc = crtc;
> -	connector->encoder = encoder;
> -	crtc->x = set->x;
> -	crtc->y = set->y;
> -	crtc->mode = *mode;
> -	crtc->enabled = true;
> -	ldu->base.set_gui_x = set->x;
> -	ldu->base.set_gui_y = set->y;
> -
> -	vmw_ldu_add_active(dev_priv, ldu, vfb);
> -
> -	return vmw_ldu_commit_list(dev_priv);
> -}
> -
>  static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
>  	.gamma_set = vmw_du_crtc_gamma_set,
>  	.destroy = vmw_ldu_crtc_destroy,
>  	.reset = vmw_du_crtc_reset,
>  	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
>  	.atomic_destroy_state = vmw_du_crtc_destroy_state,
> -	.set_config = vmw_ldu_crtc_set_config,
> +	.set_config = vmw_kms_set_config,
>  };
>  
>  
> @@ -439,8 +350,8 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane,
>  
>  
>  static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
> -	.update_plane = drm_primary_helper_update,
> -	.disable_plane = drm_primary_helper_disable,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
>  	.destroy = vmw_du_primary_plane_destroy,
>  	.reset = vmw_du_plane_reset,
>  	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> @@ -448,8 +359,8 @@ static const struct drm_plane_funcs vmw_ldu_plane_funcs = {
>  };
>  
>  static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
> -	.update_plane = vmw_du_cursor_plane_update,
> -	.disable_plane = vmw_du_cursor_plane_disable,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
>  	.destroy = vmw_du_cursor_plane_destroy,
>  	.reset = vmw_du_plane_reset,
>  	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index e4154f1..9d73f79 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -205,52 +205,6 @@ static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv,
>  }
>  
>  /**
> - * Free the backing store.
> - */
> -static void vmw_sou_backing_free(struct vmw_private *dev_priv,
> -				 struct vmw_screen_object_unit *sou)
> -{
> -	vmw_dmabuf_unreference(&sou->buffer);
> -	sou->buffer_size = 0;
> -}
> -
> -/**
> - * Allocate the backing store for the buffer.
> - */
> -static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
> -				 struct vmw_screen_object_unit *sou,
> -				 unsigned long size)
> -{
> -	int ret;
> -
> -	if (sou->buffer_size == size)
> -		return 0;
> -
> -	if (sou->buffer)
> -		vmw_sou_backing_free(dev_priv, sou);
> -
> -	sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL);
> -	if (unlikely(sou->buffer == NULL))
> -		return -ENOMEM;
> -
> -	/* After we have alloced the backing store might not be able to
> -	 * resume the overlays, this is preferred to failing to alloc.
> -	 */
> -	vmw_overlay_pause_all(dev_priv);
> -	ret = vmw_dmabuf_init(dev_priv, sou->buffer, size,
> -			      &vmw_vram_ne_placement,
> -			      false, &vmw_dmabuf_bo_free);
> -	vmw_overlay_resume_all(dev_priv);
> -
> -	if (unlikely(ret != 0))
> -		sou->buffer = NULL; /* vmw_dmabuf_init frees on error */
> -	else
> -		sou->buffer_size = size;
> -
> -	return ret;
> -}
> -
> -/**
>   * vmw_sou_crtc_mode_set_nofb - Create new screen
>   *
>   * @crtc: CRTC associated with the new screen
> @@ -353,158 +307,14 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
>  	}
>  }
>  
> -static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
> -{
> -	struct vmw_private *dev_priv;
> -	struct vmw_screen_object_unit *sou;
> -	struct drm_connector *connector;
> -	struct drm_display_mode *mode;
> -	struct drm_encoder *encoder;
> -	struct vmw_framebuffer *vfb;
> -	struct drm_framebuffer *fb;
> -	struct drm_crtc *crtc;
> -	int ret = 0;
> -
> -	if (!set)
> -		return -EINVAL;
> -
> -	if (!set->crtc)
> -		return -EINVAL;
> -
> -	/* get the sou */
> -	crtc = set->crtc;
> -	sou = vmw_crtc_to_sou(crtc);
> -	vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL;
> -	dev_priv = vmw_priv(crtc->dev);
> -
> -	if (set->num_connectors > 1) {
> -		DRM_ERROR("Too many connectors\n");
> -		return -EINVAL;
> -	}
> -
> -	if (set->num_connectors == 1 &&
> -	    set->connectors[0] != &sou->base.connector) {
> -		DRM_ERROR("Connector doesn't match %p %p\n",
> -			set->connectors[0], &sou->base.connector);
> -		return -EINVAL;
> -	}
> -
> -	/* Only one active implicit frame-buffer at a time. */
> -	mutex_lock(&dev_priv->global_kms_state_mutex);
> -	if (sou->base.is_implicit &&
> -	    dev_priv->implicit_fb && vfb &&
> -	    !(dev_priv->num_implicit == 1 &&
> -	      sou->base.active_implicit) &&
> -	    dev_priv->implicit_fb != vfb) {
> -		mutex_unlock(&dev_priv->global_kms_state_mutex);
> -		DRM_ERROR("Multiple implicit framebuffers not supported.\n");
> -		return -EINVAL;
> -	}
> -	mutex_unlock(&dev_priv->global_kms_state_mutex);
> -
> -	/* since they always map one to one these are safe */
> -	connector = &sou->base.connector;
> -	encoder = &sou->base.encoder;
> -
> -	/* should we turn the crtc off */
> -	if (set->num_connectors == 0 || !set->mode || !set->fb) {
> -		ret = vmw_sou_fifo_destroy(dev_priv, sou);
> -		/* the hardware has hung don't do anything more */
> -		if (unlikely(ret != 0))
> -			return ret;
> -
> -		connector->encoder = NULL;
> -		encoder->crtc = NULL;
> -		crtc->primary->fb = NULL;
> -		crtc->x = 0;
> -		crtc->y = 0;
> -		crtc->enabled = false;
> -
> -		vmw_kms_del_active(dev_priv, &sou->base);
> -
> -		vmw_sou_backing_free(dev_priv, sou);
> -
> -		return 0;
> -	}
> -
> -
> -	/* we now know we want to set a mode */
> -	mode = set->mode;
> -	fb = set->fb;
> -
> -	if (set->x + mode->hdisplay > fb->width ||
> -	    set->y + mode->vdisplay > fb->height) {
> -		DRM_ERROR("set outside of framebuffer\n");
> -		return -EINVAL;
> -	}
> -
> -	vmw_svga_enable(dev_priv);
> -
> -	if (mode->hdisplay != crtc->mode.hdisplay ||
> -	    mode->vdisplay != crtc->mode.vdisplay) {
> -		/* no need to check if depth is different, because backing
> -		 * store depth is forced to 4 by the device.
> -		 */
> -
> -		ret = vmw_sou_fifo_destroy(dev_priv, sou);
> -		/* the hardware has hung don't do anything more */
> -		if (unlikely(ret != 0))
> -			return ret;
> -
> -		vmw_sou_backing_free(dev_priv, sou);
> -	}
> -
> -	if (!sou->buffer) {
> -		/* forced to depth 4 by the device */
> -		size_t size = mode->hdisplay * mode->vdisplay * 4;
> -		ret = vmw_sou_backing_alloc(dev_priv, sou, size);
> -		if (unlikely(ret != 0))
> -			return ret;
> -	}
> -
> -	ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode);
> -	if (unlikely(ret != 0)) {
> -		/*
> -		 * We are in a bit of a situation here, the hardware has
> -		 * hung and we may or may not have a buffer hanging of
> -		 * the screen object, best thing to do is not do anything
> -		 * if we where defined, if not just turn the crtc of.
> -		 * Not what userspace wants but it needs to htfu.
> -		 */
> -		if (sou->defined)
> -			return ret;
> -
> -		connector->encoder = NULL;
> -		encoder->crtc = NULL;
> -		crtc->primary->fb = NULL;
> -		crtc->x = 0;
> -		crtc->y = 0;
> -		crtc->enabled = false;
> -
> -		return ret;
> -	}
> -
> -	vmw_kms_add_active(dev_priv, &sou->base, vfb);
> -
> -	connector->encoder = encoder;
> -	encoder->crtc = crtc;
> -	crtc->mode = *mode;
> -	crtc->primary->fb = fb;
> -	crtc->x = set->x;
> -	crtc->y = set->y;
> -	crtc->enabled = true;
> -
> -	return 0;
> -}
> -
>  static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
> -				  struct drm_framebuffer *fb,
> +				  struct drm_framebuffer *new_fb,
>  				  struct drm_pending_vblank_event *event,
>  				  uint32_t flags)
>  {
>  	struct vmw_private *dev_priv = vmw_priv(crtc->dev);
>  	struct drm_framebuffer *old_fb = crtc->primary->fb;
> -	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb);
> +	struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb);
>  	struct vmw_fence_obj *fence = NULL;
>  	struct drm_vmw_rect vclips;
>  	int ret;
> @@ -512,7 +322,12 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
>  	if (!vmw_kms_crtc_flippable(dev_priv, crtc))
>  		return -EINVAL;
>  
> -	crtc->primary->fb = fb;
> +	flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
> +	ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
> +	if (ret) {
> +		DRM_ERROR("Page flip error %d.\n", ret);
> +		return ret;
> +	}

You don't set mode_config.async_page_flip, why do you need to filter this
here?
-Daniel

>  
>  	/* do a full screen dirty update */
>  	vclips.x = crtc->x;
> @@ -559,7 +374,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
>  	return ret;
>  
>  out_no_fence:
> -	crtc->primary->fb = old_fb;
> +	drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb);
>  	return ret;
>  }
>  
> @@ -569,7 +384,7 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
>  	.reset = vmw_du_crtc_reset,
>  	.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
>  	.atomic_destroy_state = vmw_du_crtc_destroy_state,
> -	.set_config = vmw_sou_crtc_set_config,
> +	.set_config = vmw_kms_set_config,
>  	.page_flip = vmw_sou_crtc_page_flip,
>  };
>  
> @@ -711,12 +526,16 @@ static void
>  vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
>  				    struct drm_plane_state *old_state)
>  {
> +	struct drm_crtc *crtc = plane->state->crtc;
> +
> +	if (crtc)
> +		crtc->primary->fb = plane->state->fb;
>  }
>  
>  
>  static const struct drm_plane_funcs vmw_sou_plane_funcs = {
> -	.update_plane = drm_primary_helper_update,
> -	.disable_plane = drm_primary_helper_disable,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
>  	.destroy = vmw_du_primary_plane_destroy,
>  	.reset = vmw_du_plane_reset,
>  	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> @@ -724,8 +543,8 @@ static const struct drm_plane_funcs vmw_sou_plane_funcs = {
>  };
>  
>  static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
> -	.update_plane = vmw_du_cursor_plane_update,
> -	.disable_plane = vmw_du_cursor_plane_disable,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
>  	.destroy = vmw_du_cursor_plane_destroy,
>  	.reset = vmw_du_plane_reset,
>  	.atomic_duplicate_state = vmw_du_plane_duplicate_state,
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 00/11] Enable Atomic Mode Set on vmwgfx
  2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
                   ` (10 preceding siblings ...)
  2017-03-27 22:01 ` [PATCH 11/11] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU Sinclair Yeh
@ 2017-03-28  7:54 ` Daniel Vetter
  11 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:54 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:00:53PM -0700, Sinclair Yeh wrote:
> This series enables atomic mode set on vmwgfx.  Developed in
> collaboration with Thomas Hellstrom and the VMWare Graphics
> Team.

Yay!

I've given it a quick read-thru and sprinkled some comments over a bunch
of places. One top-level suggestion would be to review all the hooks you
have and vmw-specific callbacks and make sure you really need them all. A
bunch can definitely be removed after the transition, and in general we've
tried really hard to make the atomic helpers not get in the way so much
and require pointless boilerplate.

I haven't seen them, but I assume you have suspend/resume and stuff like
that too. Might be good to look into the suspend/resume/shutdown helpers
we now have in drm-misc.

On the series, with my comments addressed or ignored to your judgment:

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 05/11] drm/vmwgfx: Add and connect CRTC helper functions
  2017-03-27 22:00 ` [PATCH 05/11] drm/vmwgfx: Add and connect CRTC helper functions Sinclair Yeh
@ 2017-03-28  7:56   ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-28  7:56 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Mon, Mar 27, 2017 at 03:00:58PM -0700, Sinclair Yeh wrote:
> Atomic mode set requires us to refactor existing vmw_stdu_crtc_set_config
> code into sections that check the validity of the new mode, and sections
> that actually program the hardware state.
> 
> vmw_du_crtc_atomic_check() takes CRTC-related checking code.  In a later
> patch, vmw_du_primary_plane_atomic_check() will take framebuffer-related
> checking code.
> 
> These helpers won't be called until we flip on the atomic support
> flag or set drm_crtc_funcs->set_config to using the atomic
> helper.
> 
> v2:
> * The state->num_connector is actually the total number of potential
>   connectors, not just the one associated with the display unit.
>   The proper one to check is ->connector_mask.
> 
> * Add the check to only allow plane state to be the same as crtc state
>   (Thanks to mlankhorst)
> 
> * Make sure to turn on SVGA mode before using VRAM.  SVGA mode is
>   disabled in master_drop if dbdev is not running.
> 
> Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  48 ++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   9 +++
>  drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  79 +++++++++++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 119 +++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 117 ++++++++++++++++++++++++++++++++++
>  5 files changed, 372 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index a8e0909..6f0f160 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -399,6 +399,54 @@ void vmw_du_primary_plane_destroy(struct drm_plane *plane)
>  }
>  
>  
> +int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
> +			     struct drm_crtc_state *new_state)
> +{
> +	struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
> +	int connector_mask = 1 << drm_connector_index(&du->connector);
> +	bool has_primary = new_state->plane_mask &
> +			   BIT(drm_plane_index(crtc->primary));
> +
> +	/* We always want to have an active plane with an active CRTC */
> +	if (has_primary != new_state->enable)
> +		return -EINVAL;
> +
> +
> +	if (new_state->connector_mask != connector_mask &&
> +	    new_state->connector_mask != 0) {
> +		DRM_ERROR("Invalid connectors configuration\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +
> +void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
> +			      struct drm_crtc_state *old_crtc_state)
> +{
> +}
> +
> +
> +void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
> +			      struct drm_crtc_state *old_crtc_state)
> +{
> +	struct drm_pending_vblank_event *event = crtc->state->event;
> +
> +	if (event) {
> +		crtc->state->event = NULL;
> +
> +		spin_lock_irq(&crtc->dev->event_lock);
> +		if (drm_crtc_vblank_get(crtc) == 0)
> +			drm_crtc_arm_vblank_event(crtc, event);
> +		else
> +			drm_crtc_send_vblank_event(crtc, event);
> +		spin_unlock_irq(&crtc->dev->event_lock);
> +	}
> +
> +}
> +
> +
>  /**
>   * vmw_du_crtc_duplicate_state - duplicate crtc state
>   * @crtc: DRM crtc
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index cc50bf3..f711b5d 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -161,6 +161,7 @@ struct vmw_crtc_state {
>   * @surf Display surface for STDU
>   * @dmabuf display dmabuf for SOU
>   * @content_fb_type Used by STDU.
> + * @dmabuf_size Size of the dmabuf, used by Screen Object Display Unit
>   * @pinned pin count for STDU display surface
>   */
>  struct vmw_plane_state {
> @@ -169,6 +170,7 @@ struct vmw_plane_state {
>  	struct vmw_dma_buffer *dmabuf;
>  
>  	int content_fb_type;
> +	unsigned long dmabuf_size;
>  
>  	int pinned;
>  };
> @@ -342,10 +344,17 @@ int vmw_du_cursor_plane_update(struct drm_plane *plane,
>  			       uint32_t src_x, uint32_t src_y,
>  			       uint32_t src_w, uint32_t src_h);
>  
> +/* Atomic Helpers */
>  void vmw_du_plane_reset(struct drm_plane *plane);
>  struct drm_plane_state *vmw_du_plane_duplicate_state(struct drm_plane *plane);
>  void vmw_du_plane_destroy_state(struct drm_plane *plane,
>  				struct drm_plane_state *state);
> +int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
> +			     struct drm_crtc_state *state);
> +void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
> +			      struct drm_crtc_state *old_crtc_state);
> +void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
> +			      struct drm_crtc_state *old_crtc_state);
>  void vmw_du_crtc_reset(struct drm_crtc *crtc);
>  struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc);
>  void vmw_du_crtc_destroy_state(struct drm_crtc *crtc,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> index 276c744..d547e80 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
> @@ -167,6 +167,7 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
>  	if (vfb != ld->fb) {
>  		if (ld->fb && ld->fb->unpin)
>  			ld->fb->unpin(ld->fb);
> +		vmw_svga_enable(vmw_priv);
>  		if (vfb->pin)
>  			vfb->pin(vfb);
>  		ld->fb = vfb;
> @@ -190,6 +191,68 @@ static int vmw_ldu_add_active(struct vmw_private *vmw_priv,
>  	return 0;
>  }
>  
> +/**
> + * vmw_ldu_crtc_mode_set_nofb - Enable svga
> + *
> + * @crtc: CRTC associated with the new screen
> + *
> + * For LDU, just enable the svga
> + */
> +static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +}
> +
> +/**
> + * vmw_ldu_crtc_helper_prepare - Noop
> + *
> + * @crtc: CRTC associated with the new screen
> + *
> + * Prepares the CRTC for a mode set, but we don't need to do anything here.
> + *
> + */
> +static void vmw_ldu_crtc_helper_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/**
> + * vmw_ldu_crtc_helper_commit - Noop
> + *
> + * @crtc: CRTC associated with the new screen
> + *
> + * This is called after a mode set has been completed.  Here's
> + * usually a good place to call vmw_ldu_add_active/vmw_ldu_del_active
> + * but since for LDU the display plane is closely tied to the
> + * CRTC, it makes more sense to do those at plane update time.
> + */
> +static void vmw_ldu_crtc_helper_commit(struct drm_crtc *crtc)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_legacy_display_unit *ldu;
> +	struct vmw_framebuffer *vfb;
> +	struct drm_framebuffer *fb;
> +
> +
> +	ldu = vmw_crtc_to_ldu(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +	fb       = crtc->primary->fb;
> +
> +	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
> +
> +	if (vfb)
> +		vmw_ldu_add_active(dev_priv, ldu, vfb);
> +	else
> +		vmw_ldu_del_active(dev_priv, ldu);
> +}
> +
> +/**
> + * vmw_ldu_crtc_helper_disable - Turns off CRTC
> + *
> + * @crtc: CRTC to be turned off
> + */
> +static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc)
> +{
> +}
> +
>  static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
>  {
>  	struct vmw_private *dev_priv;
> @@ -346,6 +409,20 @@ static const struct drm_plane_funcs vmw_ldu_cursor_funcs = {
>  	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
> +/*
> + * Atomic Helpers
> + */
> +static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = {
> +	.prepare = vmw_ldu_crtc_helper_prepare,
> +	.commit = vmw_ldu_crtc_helper_commit,
> +	.disable = vmw_ldu_crtc_helper_disable,
> +	.mode_set = drm_helper_crtc_mode_set,

Note this is only needed for the transitional helpers. You can/should
remove the .mode_set hook once you're fully atomic. I didn't see that
anywhere later on, might have missed it.
-Daniel

> +	.mode_set_nofb = vmw_ldu_crtc_mode_set_nofb,
> +	.atomic_check = vmw_du_crtc_atomic_check,
> +	.atomic_begin = vmw_du_crtc_atomic_begin,
> +	.atomic_flush = vmw_du_crtc_atomic_flush,
> +};
> +
>  
>  static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  {
> @@ -445,6 +522,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free_unregister;
>  	}
>  
> +	drm_crtc_helper_add(crtc, &vmw_ldu_crtc_helper_funcs);
> +
>  	drm_mode_crtc_set_gamma_size(crtc, 256);
>  
>  	drm_object_attach_property(&connector->base,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> index 36d42f5..662024c 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
> @@ -250,6 +250,109 @@ static int vmw_sou_backing_alloc(struct vmw_private *dev_priv,
>  	return ret;
>  }
>  
> +/**
> + * vmw_sou_crtc_mode_set_nofb - Create new screen
> + *
> + * @crtc: CRTC associated with the new screen
> + *
> + * This function creates/destroys a screen.  This function cannot fail, so if
> + * somehow we run into a failure, just do the best we can to get out.
> + */
> +static void vmw_sou_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_screen_object_unit *sou;
> +	struct vmw_framebuffer *vfb;
> +	struct drm_framebuffer *fb;
> +	struct drm_plane_state *ps;
> +	struct vmw_plane_state *vps;
> +	int ret;
> +
> +
> +	sou      = vmw_crtc_to_sou(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +	ps       = crtc->primary->state;
> +	fb       = ps->fb;
> +	vps      = vmw_plane_state_to_vps(ps);
> +
> +	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
> +
> +	if (sou->defined) {
> +		ret = vmw_sou_fifo_destroy(dev_priv, sou);
> +		if (ret) {
> +			DRM_ERROR("Failed to destroy Screen Object\n");
> +			return;
> +		}
> +	}
> +
> +	if (vfb) {
> +		sou->buffer = vps->dmabuf;
> +		sou->buffer_size = vps->dmabuf_size;
> +
> +		ret = vmw_sou_fifo_create(dev_priv, sou, crtc->x, crtc->y,
> +					  &crtc->mode);
> +		if (ret)
> +			DRM_ERROR("Failed to define Screen Object %dx%d\n",
> +				  crtc->x, crtc->y);
> +
> +		vmw_kms_add_active(dev_priv, &sou->base, vfb);
> +	} else {
> +		sou->buffer = NULL;
> +		sou->buffer_size = 0;
> +
> +		vmw_kms_del_active(dev_priv, &sou->base);
> +	}
> +}
> +
> +/**
> + * vmw_sou_crtc_helper_prepare - Noop
> + *
> + * @crtc: CRTC associated with the new screen
> + *
> + * Prepares the CRTC for a mode set, but we don't need to do anything here.
> + */
> +static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +/**
> + * vmw_sou_crtc_helper_commit - Noop
> + *
> + * @crtc: CRTC associated with the new screen
> + *
> + * This is called after a mode set has been completed.
> + */
> +static void vmw_sou_crtc_helper_commit(struct drm_crtc *crtc)
> +{
> +}
> +
> +/**
> + * vmw_sou_crtc_helper_disable - Turns off CRTC
> + *
> + * @crtc: CRTC to be turned off
> + */
> +static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_screen_object_unit *sou;
> +	int ret;
> +
> +
> +	if (!crtc) {
> +		DRM_ERROR("CRTC is NULL\n");
> +		return;
> +	}
> +
> +	sou = vmw_crtc_to_sou(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +
> +	if (sou->defined) {
> +		ret = vmw_sou_fifo_destroy(dev_priv, sou);
> +		if (ret)
> +			DRM_ERROR("Failed to destroy Screen Object\n");
> +	}
> +}
> +
>  static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
>  {
>  	struct vmw_private *dev_priv;
> @@ -527,6 +630,20 @@ static const struct drm_plane_funcs vmw_sou_cursor_funcs = {
>  	.atomic_destroy_state = vmw_du_plane_destroy_state,
>  };
>  
> +/*
> + * Atomic Helpers
> + */
> +static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = {
> +	.prepare = vmw_sou_crtc_helper_prepare,
> +	.commit = vmw_sou_crtc_helper_commit,
> +	.disable = vmw_sou_crtc_helper_disable,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = vmw_sou_crtc_mode_set_nofb,
> +	.atomic_check = vmw_du_crtc_atomic_check,
> +	.atomic_begin = vmw_du_crtc_atomic_begin,
> +	.atomic_flush = vmw_du_crtc_atomic_flush,
> +};
> +
>  
>  static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  {
> @@ -626,6 +743,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free_unregister;
>  	}
>  
> +	drm_crtc_helper_add(crtc, &vmw_sou_crtc_helper_funcs);
> +
>  	drm_mode_crtc_set_gamma_size(crtc, 256);
>  
>  	drm_object_attach_property(&connector->base,
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> index b1fae49..6e3cfad 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
> @@ -500,6 +500,106 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
>  	return ret;
>  }
>  
> +
> +/**
> + * vmw_stdu_crtc_mode_set_nofb - Updates screen target size
> + *
> + * @crtc: CRTC associated with the screen target
> + *
> + * This function defines/destroys a screen target
> + *
> + */
> +static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_screen_target_display_unit *stdu;
> +	int ret;
> +
> +
> +	stdu     = vmw_crtc_to_stdu(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +
> +	if (stdu->defined) {
> +		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
> +		if (ret)
> +			DRM_ERROR("Failed to blank CRTC\n");
> +
> +		(void) vmw_stdu_update_st(dev_priv, stdu);
> +
> +		ret = vmw_stdu_destroy_st(dev_priv, stdu);
> +		if (ret)
> +			DRM_ERROR("Failed to destroy Screen Target\n");
> +
> +		stdu->content_fb_type = SAME_AS_DISPLAY;
> +	}
> +
> +	if (!crtc->state->enable)
> +		return;
> +
> +	vmw_svga_enable(dev_priv);
> +	ret = vmw_stdu_define_st(dev_priv, stdu, &crtc->mode, crtc->x, crtc->y);
> +
> +	if (ret)
> +		DRM_ERROR("Failed to define Screen Target of size %dx%d\n",
> +			  crtc->x, crtc->y);
> +}
> +
> +
> +static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc)
> +{
> +}
> +
> +
> +static void vmw_stdu_crtc_helper_commit(struct drm_crtc *crtc)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_screen_target_display_unit *stdu;
> +	struct vmw_framebuffer *vfb;
> +	struct drm_framebuffer *fb;
> +
> +
> +	stdu     = vmw_crtc_to_stdu(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +	fb       = crtc->primary->fb;
> +
> +	vfb = (fb) ? vmw_framebuffer_to_vfb(fb) : NULL;
> +
> +	if (vfb)
> +		vmw_kms_add_active(dev_priv, &stdu->base, vfb);
> +	else
> +		vmw_kms_del_active(dev_priv, &stdu->base);
> +}
> +
> +static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc)
> +{
> +	struct vmw_private *dev_priv;
> +	struct vmw_screen_target_display_unit *stdu;
> +	int ret;
> +
> +
> +	if (!crtc) {
> +		DRM_ERROR("CRTC is NULL\n");
> +		return;
> +	}
> +
> +	stdu     = vmw_crtc_to_stdu(crtc);
> +	dev_priv = vmw_priv(crtc->dev);
> +
> +	if (stdu->defined) {
> +		ret = vmw_stdu_bind_st(dev_priv, stdu, NULL);
> +		if (ret)
> +			DRM_ERROR("Failed to blank CRTC\n");
> +
> +		(void) vmw_stdu_update_st(dev_priv, stdu);
> +
> +		ret = vmw_stdu_destroy_st(dev_priv, stdu);
> +		if (ret)
> +			DRM_ERROR("Failed to destroy Screen Target\n");
> +
> +		stdu->content_fb_type = SAME_AS_DISPLAY;
> +	}
> +}
> +
>  /**
>   * vmw_stdu_crtc_set_config - Sets a mode
>   *
> @@ -1113,6 +1213,21 @@ static const struct drm_plane_funcs vmw_stdu_cursor_funcs = {
>  };
>  
>  
> +/*
> + * Atomic Helpers
> + */
> +static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = {
> +	.prepare = vmw_stdu_crtc_helper_prepare,
> +	.commit = vmw_stdu_crtc_helper_commit,
> +	.disable = vmw_stdu_crtc_helper_disable,
> +	.mode_set = drm_helper_crtc_mode_set,
> +	.mode_set_nofb = vmw_stdu_crtc_mode_set_nofb,
> +	.atomic_check = vmw_du_crtc_atomic_check,
> +	.atomic_begin = vmw_du_crtc_atomic_begin,
> +	.atomic_flush = vmw_du_crtc_atomic_flush,
> +};
> +
> +
>  /**
>   * vmw_stdu_init - Sets up a Screen Target Display Unit
>   *
> @@ -1219,6 +1334,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
>  		goto err_free_unregister;
>  	}
>  
> +	drm_crtc_helper_add(crtc, &vmw_stdu_crtc_helper_funcs);
> +
>  	drm_mode_crtc_set_gamma_size(crtc, 256);
>  
>  	drm_object_attach_property(&connector->base,
> -- 
> 2.7.4
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU
  2017-03-28  7:49   ` Daniel Vetter
@ 2017-03-29 21:05     ` Sinclair Yeh
  2017-03-30  7:42       ` Daniel Vetter
  0 siblings, 1 reply; 23+ messages in thread
From: Sinclair Yeh @ 2017-03-29 21:05 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: daniel.vetter, thellstrom, dri-devel

Hi Daniel,

On Tue, Mar 28, 2017 at 09:49:38AM +0200, Daniel Vetter wrote:
> On Mon, Mar 27, 2017 at 03:01:03PM -0700, Sinclair Yeh wrote:
> > Switch over to using internal atomic API for mode set.
> > 
> > This removes the legacy set_config API, replacing it with
> > drm_atomic_helper_set_config().  The DRM helper will use various
> > vmwgfx-specific atomic functions to set a mode.
> > 
> > DRIVER_ATOMIC capability flag is not yet set, so the user mode
> > will still use the legacy mode set IOCTL.
> > 
> > v2:
> > * Avoid a clash between page-flip pinning and setcrtc pinning, modify
> > the page-flip code to use the page-flip helper and the atomic callbacks.
> > To enable this, we will need to add a wrapper around atomic_commit.
> > 
> > * Add vmw_kms_set_config() to work around vmwgfx xorg driver bug
> > 
> > Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> > Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> > Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> > ---
> >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  20 +++
> >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   1 +
> >  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 325 ++++-------------------------------
> >  3 files changed, 51 insertions(+), 295 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > index 6b593aaf..7104796 100644
> > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > @@ -2923,3 +2923,23 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
> >  					  "implicit_placement", 0, 1);
> >  
> >  }
> > +
> > +
> > +/**
> > + * vmw_kms_set_config - Wrapper around drm_atomic_helper_set_config
> > + *
> > + * @set: The configuration to set.
> > + *
> > + * The vmwgfx Xorg driver doesn't assign the mode::type member, which
> > + * when drm_mode_set_crtcinfo is called as part of the configuration setting
> > + * causes it to return incorrect crtc dimensions causing severe problems in
> > + * the vmwgfx modesetting. So explicitly clear that member before calling
> > + * into drm_atomic_helper_set_config.
> > + */
> > +int vmw_kms_set_config(struct drm_mode_set *set)
> > +{
> > +	if (set && set->mode)
> > +		set->mode->type = 0;
> 
> ugh :( Looking at set_crtcinfo the only thing I can see it look at ->type
> is to check for built-in modes. Not a single driver is using that afaics,
> we might as well remove this and and void the vmw special case here too.

Do you mean remove drm_display_mode->type field altogether or just
the check in drm_mode_set_crtcinfo?

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

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU
  2017-03-29 21:05     ` Sinclair Yeh
@ 2017-03-30  7:42       ` Daniel Vetter
  0 siblings, 0 replies; 23+ messages in thread
From: Daniel Vetter @ 2017-03-30  7:42 UTC (permalink / raw)
  To: Sinclair Yeh; +Cc: daniel.vetter, thellstrom, dri-devel

On Wed, Mar 29, 2017 at 02:05:26PM -0700, Sinclair Yeh wrote:
> Hi Daniel,
> 
> On Tue, Mar 28, 2017 at 09:49:38AM +0200, Daniel Vetter wrote:
> > On Mon, Mar 27, 2017 at 03:01:03PM -0700, Sinclair Yeh wrote:
> > > Switch over to using internal atomic API for mode set.
> > > 
> > > This removes the legacy set_config API, replacing it with
> > > drm_atomic_helper_set_config().  The DRM helper will use various
> > > vmwgfx-specific atomic functions to set a mode.
> > > 
> > > DRIVER_ATOMIC capability flag is not yet set, so the user mode
> > > will still use the legacy mode set IOCTL.
> > > 
> > > v2:
> > > * Avoid a clash between page-flip pinning and setcrtc pinning, modify
> > > the page-flip code to use the page-flip helper and the atomic callbacks.
> > > To enable this, we will need to add a wrapper around atomic_commit.
> > > 
> > > * Add vmw_kms_set_config() to work around vmwgfx xorg driver bug
> > > 
> > > Signed-off-by: Sinclair Yeh <syeh@vmware.com>
> > > Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
> > > Reviewed-by: Thomas Hellstrom <thellstrom@vmware.com>
> > > ---
> > >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.c  |  20 +++
> > >  drivers/gpu/drm/vmwgfx/vmwgfx_kms.h  |   1 +
> > >  drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 325 ++++-------------------------------
> > >  3 files changed, 51 insertions(+), 295 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > index 6b593aaf..7104796 100644
> > > --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> > > @@ -2923,3 +2923,23 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
> > >  					  "implicit_placement", 0, 1);
> > >  
> > >  }
> > > +
> > > +
> > > +/**
> > > + * vmw_kms_set_config - Wrapper around drm_atomic_helper_set_config
> > > + *
> > > + * @set: The configuration to set.
> > > + *
> > > + * The vmwgfx Xorg driver doesn't assign the mode::type member, which
> > > + * when drm_mode_set_crtcinfo is called as part of the configuration setting
> > > + * causes it to return incorrect crtc dimensions causing severe problems in
> > > + * the vmwgfx modesetting. So explicitly clear that member before calling
> > > + * into drm_atomic_helper_set_config.
> > > + */
> > > +int vmw_kms_set_config(struct drm_mode_set *set)
> > > +{
> > > +	if (set && set->mode)
> > > +		set->mode->type = 0;
> > 
> > ugh :( Looking at set_crtcinfo the only thing I can see it look at ->type
> > is to check for built-in modes. Not a single driver is using that afaics,
> > we might as well remove this and and void the vmw special case here too.
> 
> Do you mean remove drm_display_mode->type field altogether or just
> the check in drm_mode_set_crtcinfo?

I only checked whether we could remove the check from
drm_mode_set_crtcinfo. I thought we need ->type still for stuff like
preferred modes. But there's definitely a pile of #defines for that field
which go back to the original kms commit in 2.6.32 and seem to have not
ever been used. Cleaning out that garbage would be good (since it's all
internal stuff afaics).
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2017-03-30  7:42 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-27 22:00 [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Sinclair Yeh
2017-03-27 22:00 ` [PATCH 01/11] drm/vmwgfx: Add universal plane support Sinclair Yeh
2017-03-28  7:07   ` Daniel Vetter
2017-03-27 22:00 ` [PATCH 02/11] drm/vmwgfx: CRTC atomic state Sinclair Yeh
2017-03-27 22:00 ` [PATCH 03/11] drm/vmwgfx: Plane " Sinclair Yeh
2017-03-28  7:33   ` Daniel Vetter
2017-03-27 22:00 ` [PATCH 04/11] drm/vmwgfx: Connector " Sinclair Yeh
2017-03-27 22:00 ` [PATCH 05/11] drm/vmwgfx: Add and connect CRTC helper functions Sinclair Yeh
2017-03-28  7:56   ` Daniel Vetter
2017-03-27 22:00 ` [PATCH 06/11] drm/vmwgfx: Add and connect plane " Sinclair Yeh
2017-03-28  7:40   ` Daniel Vetter
2017-03-27 22:01 ` [PATCH 07/11] drm/vmwgfx: Add and connect connector helper function Sinclair Yeh
2017-03-28  7:41   ` Daniel Vetter
2017-03-27 22:01 ` [PATCH 08/11] drm/vmwgfx: Add and connect atomic state object check/commit Sinclair Yeh
2017-03-28  7:45   ` Daniel Vetter
2017-03-27 22:01 ` [PATCH 09/11] drm/vmwgfx: Fixes to vmwgfx_fb Sinclair Yeh
2017-03-27 22:01 ` [PATCH 10/11] drm/vmwgfx: Switch over to internal atomic API for STDU Sinclair Yeh
2017-03-28  7:49   ` Daniel Vetter
2017-03-29 21:05     ` Sinclair Yeh
2017-03-30  7:42       ` Daniel Vetter
2017-03-27 22:01 ` [PATCH 11/11] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU Sinclair Yeh
2017-03-28  7:51   ` Daniel Vetter
2017-03-28  7:54 ` [PATCH 00/11] Enable Atomic Mode Set on vmwgfx Daniel Vetter

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.