[PATCH 1/3] drm: introduce share plane

Mark Yao mark.yao at rock-chips.com
Tue Jul 26 00:46:32 PDT 2016


What is share plane:
Plane hardware only be used when the display scanout run into plane active
scanout, that means we can reuse the plane hardware resources on plane
non-active scanout.

     --------------------------------------------------
    |  scanout                                       |
    |         ------------------                     |
    |         | parent plane   |                     |
    |         | active scanout |                     |
    |         |                |   ----------------- |
    |         ------------------   | share plane 1 | |
    |  -----------------           |active scanout | |
    |  | share plane 0 |           |               | |
    |  |active scanout |           ----------------- |
    |  |               |                             |
    |  -----------------                             |
    --------------------------------------------------
One plane hardware can be reuse for multi-planes, we assume the first
plane is parent plane, other planes share the resource with first one.
    parent plane
        |---share plane 0
        |---share plane 1
        ...

Because resource share, There are some limit on share plane: one group
of share planes need use same zpos, can not overlap, etc.

We assume share plane is a universal plane with some limit flags.
people who use the share plane need know the limit, should call the ioctl
DRM_CLIENT_CAP_SHARE_PLANES, and judge the planes limit before use it.

A group of share planes would has same shard id, so userspace can
group them, judge share plane's limit.

Signed-off-by: Mark Yao <mark.yao at rock-chips.com>
---
 drivers/gpu/drm/drm_crtc.c  | 110 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_ioctl.c |   5 ++
 include/drm/drmP.h          |   5 ++
 include/drm/drm_crtc.h      |  14 ++++++
 include/uapi/drm/drm.h      |   7 +++
 5 files changed, 141 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 9d3f80e..3a8257e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1426,6 +1426,96 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 EXPORT_SYMBOL(drm_plane_init);
 
 /**
+ * drm_share_plane_init - Initialize a share plane
+ * @dev: DRM device
+ * @plane: plane object to init
+ * @parent: this plane share some resources with parent plane.
+ * @possible_crtcs: bitmask of possible CRTCs
+ * @funcs: callbacks for the new plane
+ * @formats: array of supported formats (%DRM_FORMAT_*)
+ * @format_count: number of elements in @formats
+ * @type: type of plane (overlay, primary, cursor)
+ *
+ * With this API, the plane can share hardware resources with other planes.
+ *
+ *   --------------------------------------------------
+ *   |  scanout                                       |
+ *   |         ------------------                     |
+ *   |         |  parent plane  |                     |
+ *   |         | active scanout |                     |
+ *   |         |                |   ----------------- |
+ *   |         ------------------   | share plane 1 | |
+ *   |  -----------------           |active scanout | |
+ *   |  | share plane 0 |           |               | |
+ *   |  |active scanout |           ----------------- |
+ *   |  |               |                             |
+ *   |  -----------------                             |
+ *   --------------------------------------------------
+ *
+ *    parent plane
+ *        |---share plane 0
+ *        |---share plane 1
+ *        ...
+ *
+ * The plane hardware is used when the display scanout run into plane active
+ * scanout, that means we can reuse the plane hardware resources on plane
+ * non-active scanout.
+ *
+ * Because resource share, There are some limit on share plane: one group
+ * of share planes need use same zpos, can't not overlap, etc.
+ *
+ * Here assume share plane is a universal plane with some limit flags.
+ * people who use the share plane need know the limit, should call the ioctl
+ * DRM_CLIENT_CAP_SHARE_PLANES, and judge the planes limit before use it.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+
+int drm_share_plane_init(struct drm_device *dev, struct drm_plane *plane,
+			 struct drm_plane *parent,
+			 unsigned long possible_crtcs,
+			 const struct drm_plane_funcs *funcs,
+			 const uint32_t *formats, unsigned int format_count,
+			 enum drm_plane_type type)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	int ret;
+	int share_id;
+
+	/*
+	 * TODO: only verified on ATOMIC drm driver.
+	 */
+	if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
+		return -EINVAL;
+
+	ret = drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
+				       formats, format_count, type, NULL);
+	if (ret)
+		return ret;
+
+	if (parent) {
+		/*
+		 * Can't support more than two level plane share.
+		 */
+		WARN_ON(parent->parent);
+		share_id = parent->base.id;
+		plane->parent = parent;
+
+		config->num_share_plane++;
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+			config->num_share_overlay_plane++;
+	} else {
+		share_id = plane->base.id;
+	}
+
+	drm_object_attach_property(&plane->base,
+				   config->prop_share_id, share_id);
+	return 0;
+}
+EXPORT_SYMBOL(drm_share_plane_init);
+
+/**
  * drm_plane_cleanup - Clean up the core plane usage
  * @plane: plane to cleanup
  *
@@ -1452,6 +1542,11 @@ void drm_plane_cleanup(struct drm_plane *plane)
 	dev->mode_config.num_total_plane--;
 	if (plane->type == DRM_PLANE_TYPE_OVERLAY)
 		dev->mode_config.num_overlay_plane--;
+	if (plane->parent) {
+		dev->mode_config.num_share_plane--;
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+			dev->mode_config.num_share_overlay_plane--;
+	}
 	drm_modeset_unlock_all(dev);
 
 	WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
@@ -1600,6 +1695,13 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
 		return -ENOMEM;
 	dev->mode_config.plane_type_property = prop;
 
+	prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE,
+					 "SHARE_ID", 0, UINT_MAX);
+	if (!prop)
+		return -ENOMEM;
+
+	dev->mode_config.prop_share_id = prop;
+
 	prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
 			"SRC_X", 0, UINT_MAX);
 	if (!prop)
@@ -2431,6 +2533,12 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
 		num_planes = config->num_total_plane;
 	else
 		num_planes = config->num_overlay_plane;
+	if (!file_priv->share_planes) {
+		if (file_priv->universal_planes)
+			num_planes -= config->num_share_plane;
+		else
+			num_planes -= config->num_share_overlay_plane;
+	}
 
 	/*
 	 * This ioctl is called twice, once to determine how much space is
@@ -2449,6 +2557,8 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
 			if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
 			    !file_priv->universal_planes)
 				continue;
+			if (plane->parent && !file_priv->share_planes)
+				continue;
 
 			if (put_user(plane->base.id, plane_ptr + copied))
 				return -EFAULT;
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 33af4a5..8b0120d 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -294,6 +294,11 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 			return -EINVAL;
 		file_priv->universal_planes = req->value;
 		break;
+	case DRM_CLIENT_CAP_SHARE_PLANES:
+		if (req->value > 1)
+			return -EINVAL;
+		file_priv->share_planes = req->value;
+		break;
 	case DRM_CLIENT_CAP_ATOMIC:
 		if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
 			return -EINVAL;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c2fe2cf..285d177 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -314,6 +314,11 @@ struct drm_file {
 	/* true if client understands atomic properties */
 	unsigned atomic:1;
 	/*
+	 * true if client understands share planes and
+	 * hardware support share planes.
+	 */
+	unsigned share_planes:1;
+	/*
 	 * This client is the creator of @master.
 	 * Protected by struct drm_device::master_mutex.
 	 */
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 9e6ab4a..a3fe9b0 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1660,6 +1660,7 @@ enum drm_plane_type {
 /**
  * struct drm_plane - central DRM plane control structure
  * @dev: DRM device this plane belongs to
+ * @parent: this plane share some resources with parent plane.
  * @head: for list management
  * @name: human readable name, can be overwritten by the driver
  * @base: base mode object
@@ -1679,6 +1680,7 @@ enum drm_plane_type {
  */
 struct drm_plane {
 	struct drm_device *dev;
+	struct drm_plane *parent;
 	struct list_head head;
 
 	char *name;
@@ -2408,6 +2410,8 @@ struct drm_mode_config {
 	 */
 	int num_overlay_plane;
 	int num_total_plane;
+	int num_share_plane;
+	int num_share_overlay_plane;
 	struct list_head plane_list;
 
 	int num_crtc;
@@ -2428,6 +2432,9 @@ struct drm_mode_config {
 
 	struct mutex blob_lock;
 
+	/* pointers to share properties */
+	struct drm_property *prop_share_id;
+
 	/* pointers to standard properties */
 	struct list_head property_blob_list;
 	struct drm_property *edid_property;
@@ -2636,6 +2643,13 @@ extern int drm_plane_init(struct drm_device *dev,
 			  const struct drm_plane_funcs *funcs,
 			  const uint32_t *formats, unsigned int format_count,
 			  bool is_primary);
+extern int drm_share_plane_init(struct drm_device *dev, struct drm_plane *plane,
+				struct drm_plane *parent,
+				unsigned long possible_crtcs,
+				const struct drm_plane_funcs *funcs,
+				const uint32_t *formats,
+				unsigned int format_count,
+				enum drm_plane_type type);
 extern void drm_plane_cleanup(struct drm_plane *plane);
 
 /**
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 452675f..01979a4 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -677,6 +677,13 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_ATOMIC	3
 
+/**
+ * DRM_CLIENT_CAP_SHARE_PLANES
+ *
+ * If set to 1, the DRM core will expose share planes to userspace.
+ */
+#define DRM_CLIENT_CAP_SHARE_PLANES	4
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;
-- 
1.9.1





More information about the linux-arm-kernel mailing list