All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  7:46 ` Mark Yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: Mark Yao

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@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

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

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  7:46 ` Mark Yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

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@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


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

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

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  7:46 ` Mark Yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: linux-arm-kernel

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@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

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

* [PATCH 2/3] drm/rockchip: vop: support multi area plane
  2016-07-26  7:46 ` Mark Yao
@ 2016-07-26  7:46   ` Mark Yao
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: Mark Yao

The series vop of VOP_FULL framework support area plane, such as
RK3288 and RK3399, one group of area planes share same hardware,
reuse the hardware on different scanout time, this design is
useful to support mulit planes with low hardware consume.

Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 191 +++++++++++++++++-----------
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   4 +-
 2 files changed, 123 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 91305eb..bd084c0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -41,17 +41,19 @@
 #define __REG_SET_NORMAL(x, off, mask, shift, v) \
 		vop_mask_write(x, off, (mask) << shift, (v) << shift)
 
-#define REG_SET(x, base, reg, v, mode) \
-		__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
-#define REG_SET_MASK(x, base, reg, mask, v, mode) \
-		__REG_SET_##mode(x, base + reg.offset, mask, reg.shift, v)
+#define REG_SET(x, off, reg, v, mode) \
+		__REG_SET_##mode(x, off + reg.offset, \
+				 reg.mask, reg.shift, v)
+#define REG_SET_MASK(x, off, reg, mask, v, mode) \
+		__REG_SET_##mode(x, off + reg.offset, mask, reg.shift, v)
 
 #define VOP_WIN_SET(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->name, v, RELAXED)
+		REG_SET(x, win->offset, VOP_WIN_NAME(win, name), v, RELAXED)
 #define VOP_SCL_SET(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
+		REG_SET(x, win->offset, win->phy->scl->name, v, RELAXED)
 #define VOP_SCL_SET_EXT(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->scl->ext->name, v, RELAXED)
+		REG_SET(x, win->offset, win->phy->scl->ext->name, v, RELAXED)
+
 #define VOP_CTRL_SET(x, name, v) \
 		REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
@@ -75,10 +77,13 @@
 		vop_get_intr_type(vop, &vop->data->intr->name, type)
 
 #define VOP_WIN_GET(x, win, name) \
-		vop_read_reg(x, win->base, &win->phy->name)
+		vop_read_reg(x, win->offset, &VOP_WIN_NAME(win, name))
+
+#define VOP_WIN_NAME(win, name) \
+		(vop_get_win_phy(win, &win->phy->name)->name)
 
 #define VOP_WIN_GET_YRGBADDR(vop, win) \
-		vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
+		vop_readl(vop, win->offset + VOP_WIN_NAME(win, yrgb_mst).offset)
 
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
@@ -94,8 +99,14 @@ struct vop_plane_state {
 };
 
 struct vop_win {
+	struct vop_win *parent;
 	struct drm_plane base;
-	const struct vop_win_data *data;
+
+	uint32_t offset;
+	enum drm_plane_type type;
+	const struct vop_win_phy *phy;
+	const uint32_t *data_formats;
+	uint32_t nformats;
 	struct vop *vop;
 
 	/* protected by dev->event_lock */
@@ -119,6 +130,7 @@ struct vop {
 	struct drm_pending_vblank_event *event;
 
 	const struct vop_data *data;
+	int num_wins;
 
 	uint32_t *regsbak;
 	void __iomem *regs;
@@ -187,6 +199,15 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
 	}
 }
 
+static inline const struct vop_win_phy *
+vop_get_win_phy(struct vop_win *win, const struct vop_reg *reg)
+{
+	if (!reg->mask && win->parent)
+		return win->parent->phy;
+
+	return win->phy;
+}
+
 static inline uint32_t vop_get_intr_type(struct vop *vop,
 					 const struct vop_reg *reg, int type)
 {
@@ -299,9 +320,9 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
 	return val;
 }
 
-static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
-			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
-			     uint32_t dst_h, uint32_t pixel_format)
+static void scl_vop_cal_scl_fac(struct vop *vop, struct vop_win *win,
+				uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+				uint32_t dst_h, uint32_t pixel_format)
 {
 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
 	uint16_t cbcr_hor_scl_mode = SCALE_NONE;
@@ -316,6 +337,9 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
 	uint32_t val;
 	int vskiplines = 0;
 
+	if (!win->phy->scl)
+		return;
+
 	if (dst_w > 3840) {
 		DRM_ERROR("Maximum destination width (3840) exceeded\n");
 		return;
@@ -509,9 +533,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 	 * disable that crtc. Otherwise we might try to scan from a destroyed
 	 * buffer later.
 	 */
-	for (i = 0; i < vop->data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-		const struct vop_win_data *win = vop_win->data;
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 
 		spin_lock(&vop->reg_lock);
 		VOP_WIN_SET(vop, win, enable, 0);
@@ -590,9 +613,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 	struct drm_crtc *crtc = state->crtc;
 	struct drm_crtc_state *crtc_state;
 	struct drm_framebuffer *fb = state->fb;
-	struct vop_win *vop_win = to_vop_win(plane);
+	struct vop_win *win = to_vop_win(plane);
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
-	const struct vop_win_data *win = vop_win->data;
 	bool visible;
 	int ret;
 	struct drm_rect *dest = &vop_plane_state->dest;
@@ -660,16 +682,15 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
 				     struct drm_plane_state *old_state)
 {
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
-	struct vop_win *vop_win = to_vop_win(plane);
-	const struct vop_win_data *win = vop_win->data;
+	struct vop_win *win = to_vop_win(plane);
 	struct vop *vop = to_vop(old_state->crtc);
 
 	if (!old_state->crtc)
 		return;
 
 	spin_lock_irq(&plane->dev->event_lock);
-	vop_win->enable = false;
-	vop_win->yrgb_mst = 0;
+	win->enable = false;
+	win->yrgb_mst = 0;
 	spin_unlock_irq(&plane->dev->event_lock);
 
 	spin_lock(&vop->reg_lock);
@@ -686,9 +707,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 {
 	struct drm_plane_state *state = plane->state;
 	struct drm_crtc *crtc = state->crtc;
-	struct vop_win *vop_win = to_vop_win(plane);
+	struct vop_win *win = to_vop_win(plane);
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
-	const struct vop_win_data *win = vop_win->data;
 	struct vop *vop = to_vop(state->crtc);
 	struct drm_framebuffer *fb = state->fb;
 	unsigned int actual_w, actual_h;
@@ -736,8 +756,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 
 	spin_lock_irq(&plane->dev->event_lock);
-	vop_win->enable = true;
-	vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
+	win->enable = true;
+	win->yrgb_mst = vop_plane_state->yrgb_mst;
 	spin_unlock_irq(&plane->dev->event_lock);
 
 	spin_lock(&vop->reg_lock);
@@ -761,10 +781,9 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 		VOP_WIN_SET(vop, win, uv_mst, dma_addr);
 	}
 
-	if (win->phy->scl)
-		scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
-				    drm_rect_width(dest), drm_rect_height(dest),
-				    fb->pixel_format);
+	scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
+			    drm_rect_width(dest), drm_rect_height(dest),
+			    fb->pixel_format);
 
 	VOP_WIN_SET(vop, win, act_info, act_info);
 	VOP_WIN_SET(vop, win, dsp_info, dsp_info);
@@ -1098,9 +1117,9 @@ static bool vop_win_pending_is_complete(struct vop_win *vop_win)
 	dma_addr_t yrgb_mst;
 
 	if (!vop_win->enable)
-		return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
+		return VOP_WIN_GET(vop_win->vop, vop_win, enable) == 0;
 
-	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
+	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win);
 
 	return yrgb_mst == vop_win->yrgb_mst;
 }
@@ -1112,7 +1131,7 @@ static void vop_handle_vblank(struct vop *vop)
 	unsigned long flags;
 	int i;
 
-	for (i = 0; i < vop->data->win_size; i++) {
+	for (i = 0; i < vop->num_wins; i++) {
 		if (!vop_win_pending_is_complete(&vop->win[i]))
 			return;
 	}
@@ -1176,15 +1195,35 @@ static irqreturn_t vop_isr(int irq, void *data)
 	return ret;
 }
 
+static int vop_plane_init(struct vop *vop, struct vop_win *win,
+			  unsigned long possible_crtcs)
+{
+	struct drm_plane *share = NULL;
+	int ret;
+
+	if (win->parent)
+		share = &win->parent->base;
+
+	ret = drm_share_plane_init(vop->drm_dev, &win->base, share,
+				   possible_crtcs, &vop_plane_funcs,
+				   win->data_formats, win->nformats, win->type);
+	if (ret) {
+		DRM_ERROR("failed to initialize plane\n");
+		return ret;
+	}
+	drm_plane_helper_add(&win->base, &plane_helper_funcs);
+
+	return 0;
+}
+
 static int vop_create_crtc(struct vop *vop)
 {
-	const struct vop_data *vop_data = vop->data;
 	struct device *dev = vop->dev;
 	struct drm_device *drm_dev = vop->drm_dev;
 	struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
 	struct drm_crtc *crtc = &vop->crtc;
 	struct device_node *port;
-	int ret;
+	int ret = 0;
 	int i;
 
 	/*
@@ -1192,30 +1231,22 @@ static int vop_create_crtc(struct vop *vop)
 	 * to pass them to drm_crtc_init_with_planes, which sets the
 	 * "possible_crtcs" to the newly initialized crtc.
 	 */
-	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-		const struct vop_win_data *win_data = vop_win->data;
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 
-		if (win_data->type != DRM_PLANE_TYPE_PRIMARY &&
-		    win_data->type != DRM_PLANE_TYPE_CURSOR)
+		if (win->type != DRM_PLANE_TYPE_PRIMARY &&
+		    win->type != DRM_PLANE_TYPE_CURSOR)
 			continue;
 
-		ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,
-					       0, &vop_plane_funcs,
-					       win_data->phy->data_formats,
-					       win_data->phy->nformats,
-					       win_data->type, NULL);
-		if (ret) {
-			DRM_ERROR("failed to initialize plane\n");
+		if (vop_plane_init(vop, win, 0))
 			goto err_cleanup_planes;
-		}
 
-		plane = &vop_win->base;
-		drm_plane_helper_add(plane, &plane_helper_funcs);
+		plane = &win->base;
 		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
 			primary = plane;
 		else if (plane->type == DRM_PLANE_TYPE_CURSOR)
 			cursor = plane;
+
 	}
 
 	ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
@@ -1229,25 +1260,15 @@ static int vop_create_crtc(struct vop *vop)
 	 * Create drm_planes for overlay windows with possible_crtcs restricted
 	 * to the newly created crtc.
 	 */
-	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-		const struct vop_win_data *win_data = vop_win->data;
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 		unsigned long possible_crtcs = 1 << drm_crtc_index(crtc);
 
-		if (win_data->type != DRM_PLANE_TYPE_OVERLAY)
+		if (win->type != DRM_PLANE_TYPE_OVERLAY)
 			continue;
 
-		ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,
-					       possible_crtcs,
-					       &vop_plane_funcs,
-					       win_data->phy->data_formats,
-					       win_data->phy->nformats,
-					       win_data->type, NULL);
-		if (ret) {
-			DRM_ERROR("failed to initialize overlay plane\n");
+		if (vop_plane_init(vop, win, possible_crtcs))
 			goto err_cleanup_crtc;
-		}
-		drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
 	}
 
 	port = of_get_child_by_name(dev->of_node, "port");
@@ -1362,8 +1383,8 @@ static int vop_initial(struct vop *vop)
 	for (i = 0; i < vop_data->table_size; i++)
 		vop_writel(vop, init_table[i].offset, init_table[i].value);
 
-	for (i = 0; i < vop_data->win_size; i++) {
-		const struct vop_win_data *win = &vop_data->win[i];
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 
 		VOP_WIN_SET(vop, win, enable, 0);
 	}
@@ -1405,14 +1426,34 @@ err_unprepare_dclk:
 static void vop_win_init(struct vop *vop)
 {
 	const struct vop_data *vop_data = vop->data;
-	unsigned int i;
+	unsigned int i, j;
+	unsigned int num_wins = 0;
 
 	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
+		struct vop_win *vop_win = &vop->win[num_wins];
 		const struct vop_win_data *win_data = &vop_data->win[i];
 
-		vop_win->data = win_data;
+		vop_win->phy = win_data->phy;
+		vop_win->offset = win_data->base;
+		vop_win->type = win_data->type;
+		vop_win->data_formats = win_data->phy->data_formats;
+		vop_win->nformats = win_data->phy->nformats;
 		vop_win->vop = vop;
+		num_wins++;
+
+		for (j = 0; j < win_data->area_size; j++) {
+			struct vop_win *vop_area = &vop->win[num_wins];
+			const struct vop_win_phy *area = win_data->area[j];
+
+			vop_area->parent = vop_win;
+			vop_area->offset = vop_win->offset;
+			vop_area->phy = area;
+			vop_area->type = DRM_PLANE_TYPE_OVERLAY;
+			vop_area->data_formats = vop_win->data_formats;
+			vop_area->nformats = vop_win->nformats;
+			vop_area->vop = vop;
+			num_wins++;
+		}
 	}
 }
 
@@ -1424,14 +1465,21 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 	struct vop *vop;
 	struct resource *res;
 	size_t alloc_size;
-	int ret, irq;
+	int ret, irq, i;
+	int num_wins = 0;
 
 	vop_data = of_device_get_match_data(dev);
 	if (!vop_data)
 		return -ENODEV;
 
+	for (i = 0; i < vop_data->win_size; i++) {
+		const struct vop_win_data *win_data = &vop_data->win[i];
+
+		num_wins += win_data->area_size + 1;
+	}
+
 	/* Allocate vop struct and its vop_win array */
-	alloc_size = sizeof(*vop) + sizeof(*vop->win) * vop_data->win_size;
+	alloc_size = sizeof(*vop) + sizeof(*vop->win) * num_wins;
 	vop = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
 	if (!vop)
 		return -ENOMEM;
@@ -1439,6 +1487,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 	vop->dev = dev;
 	vop->data = vop_data;
 	vop->drm_dev = drm_dev;
+	vop->num_wins = num_wins;
 	dev_set_drvdata(dev, vop);
 
 	vop_win_init(vop);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 071ff0b..def5afa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -122,8 +122,10 @@ struct vop_win_phy {
 
 struct vop_win_data {
 	uint32_t base;
-	const struct vop_win_phy *phy;
 	enum drm_plane_type type;
+	const struct vop_win_phy *phy;
+	const struct vop_win_phy **area;
+	unsigned int area_size;
 };
 
 struct vop_data {
-- 
1.9.1

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

* [PATCH 2/3] drm/rockchip: vop: support multi area plane
@ 2016-07-26  7:46   ` Mark Yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: linux-arm-kernel

The series vop of VOP_FULL framework support area plane, such as
RK3288 and RK3399, one group of area planes share same hardware,
reuse the hardware on different scanout time, this design is
useful to support mulit planes with low hardware consume.

Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 191 +++++++++++++++++-----------
 drivers/gpu/drm/rockchip/rockchip_drm_vop.h |   4 +-
 2 files changed, 123 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 91305eb..bd084c0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -41,17 +41,19 @@
 #define __REG_SET_NORMAL(x, off, mask, shift, v) \
 		vop_mask_write(x, off, (mask) << shift, (v) << shift)
 
-#define REG_SET(x, base, reg, v, mode) \
-		__REG_SET_##mode(x, base + reg.offset, reg.mask, reg.shift, v)
-#define REG_SET_MASK(x, base, reg, mask, v, mode) \
-		__REG_SET_##mode(x, base + reg.offset, mask, reg.shift, v)
+#define REG_SET(x, off, reg, v, mode) \
+		__REG_SET_##mode(x, off + reg.offset, \
+				 reg.mask, reg.shift, v)
+#define REG_SET_MASK(x, off, reg, mask, v, mode) \
+		__REG_SET_##mode(x, off + reg.offset, mask, reg.shift, v)
 
 #define VOP_WIN_SET(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->name, v, RELAXED)
+		REG_SET(x, win->offset, VOP_WIN_NAME(win, name), v, RELAXED)
 #define VOP_SCL_SET(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->scl->name, v, RELAXED)
+		REG_SET(x, win->offset, win->phy->scl->name, v, RELAXED)
 #define VOP_SCL_SET_EXT(x, win, name, v) \
-		REG_SET(x, win->base, win->phy->scl->ext->name, v, RELAXED)
+		REG_SET(x, win->offset, win->phy->scl->ext->name, v, RELAXED)
+
 #define VOP_CTRL_SET(x, name, v) \
 		REG_SET(x, 0, (x)->data->ctrl->name, v, NORMAL)
 
@@ -75,10 +77,13 @@
 		vop_get_intr_type(vop, &vop->data->intr->name, type)
 
 #define VOP_WIN_GET(x, win, name) \
-		vop_read_reg(x, win->base, &win->phy->name)
+		vop_read_reg(x, win->offset, &VOP_WIN_NAME(win, name))
+
+#define VOP_WIN_NAME(win, name) \
+		(vop_get_win_phy(win, &win->phy->name)->name)
 
 #define VOP_WIN_GET_YRGBADDR(vop, win) \
-		vop_readl(vop, win->base + win->phy->yrgb_mst.offset)
+		vop_readl(vop, win->offset + VOP_WIN_NAME(win, yrgb_mst).offset)
 
 #define to_vop(x) container_of(x, struct vop, crtc)
 #define to_vop_win(x) container_of(x, struct vop_win, base)
@@ -94,8 +99,14 @@ struct vop_plane_state {
 };
 
 struct vop_win {
+	struct vop_win *parent;
 	struct drm_plane base;
-	const struct vop_win_data *data;
+
+	uint32_t offset;
+	enum drm_plane_type type;
+	const struct vop_win_phy *phy;
+	const uint32_t *data_formats;
+	uint32_t nformats;
 	struct vop *vop;
 
 	/* protected by dev->event_lock */
@@ -119,6 +130,7 @@ struct vop {
 	struct drm_pending_vblank_event *event;
 
 	const struct vop_data *data;
+	int num_wins;
 
 	uint32_t *regsbak;
 	void __iomem *regs;
@@ -187,6 +199,15 @@ static inline void vop_mask_write_relaxed(struct vop *vop, uint32_t offset,
 	}
 }
 
+static inline const struct vop_win_phy *
+vop_get_win_phy(struct vop_win *win, const struct vop_reg *reg)
+{
+	if (!reg->mask && win->parent)
+		return win->parent->phy;
+
+	return win->phy;
+}
+
 static inline uint32_t vop_get_intr_type(struct vop *vop,
 					 const struct vop_reg *reg, int type)
 {
@@ -299,9 +320,9 @@ static uint16_t scl_vop_cal_scale(enum scale_mode mode, uint32_t src,
 	return val;
 }
 
-static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
-			     uint32_t src_w, uint32_t src_h, uint32_t dst_w,
-			     uint32_t dst_h, uint32_t pixel_format)
+static void scl_vop_cal_scl_fac(struct vop *vop, struct vop_win *win,
+				uint32_t src_w, uint32_t src_h, uint32_t dst_w,
+				uint32_t dst_h, uint32_t pixel_format)
 {
 	uint16_t yrgb_hor_scl_mode, yrgb_ver_scl_mode;
 	uint16_t cbcr_hor_scl_mode = SCALE_NONE;
@@ -316,6 +337,9 @@ static void scl_vop_cal_scl_fac(struct vop *vop, const struct vop_win_data *win,
 	uint32_t val;
 	int vskiplines = 0;
 
+	if (!win->phy->scl)
+		return;
+
 	if (dst_w > 3840) {
 		DRM_ERROR("Maximum destination width (3840) exceeded\n");
 		return;
@@ -509,9 +533,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
 	 * disable that crtc. Otherwise we might try to scan from a destroyed
 	 * buffer later.
 	 */
-	for (i = 0; i < vop->data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-		const struct vop_win_data *win = vop_win->data;
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 
 		spin_lock(&vop->reg_lock);
 		VOP_WIN_SET(vop, win, enable, 0);
@@ -590,9 +613,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane,
 	struct drm_crtc *crtc = state->crtc;
 	struct drm_crtc_state *crtc_state;
 	struct drm_framebuffer *fb = state->fb;
-	struct vop_win *vop_win = to_vop_win(plane);
+	struct vop_win *win = to_vop_win(plane);
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
-	const struct vop_win_data *win = vop_win->data;
 	bool visible;
 	int ret;
 	struct drm_rect *dest = &vop_plane_state->dest;
@@ -660,16 +682,15 @@ static void vop_plane_atomic_disable(struct drm_plane *plane,
 				     struct drm_plane_state *old_state)
 {
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(old_state);
-	struct vop_win *vop_win = to_vop_win(plane);
-	const struct vop_win_data *win = vop_win->data;
+	struct vop_win *win = to_vop_win(plane);
 	struct vop *vop = to_vop(old_state->crtc);
 
 	if (!old_state->crtc)
 		return;
 
 	spin_lock_irq(&plane->dev->event_lock);
-	vop_win->enable = false;
-	vop_win->yrgb_mst = 0;
+	win->enable = false;
+	win->yrgb_mst = 0;
 	spin_unlock_irq(&plane->dev->event_lock);
 
 	spin_lock(&vop->reg_lock);
@@ -686,9 +707,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 {
 	struct drm_plane_state *state = plane->state;
 	struct drm_crtc *crtc = state->crtc;
-	struct vop_win *vop_win = to_vop_win(plane);
+	struct vop_win *win = to_vop_win(plane);
 	struct vop_plane_state *vop_plane_state = to_vop_plane_state(state);
-	const struct vop_win_data *win = vop_win->data;
 	struct vop *vop = to_vop(state->crtc);
 	struct drm_framebuffer *fb = state->fb;
 	unsigned int actual_w, actual_h;
@@ -736,8 +756,8 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 	vop_plane_state->yrgb_mst = rk_obj->dma_addr + offset + fb->offsets[0];
 
 	spin_lock_irq(&plane->dev->event_lock);
-	vop_win->enable = true;
-	vop_win->yrgb_mst = vop_plane_state->yrgb_mst;
+	win->enable = true;
+	win->yrgb_mst = vop_plane_state->yrgb_mst;
 	spin_unlock_irq(&plane->dev->event_lock);
 
 	spin_lock(&vop->reg_lock);
@@ -761,10 +781,9 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
 		VOP_WIN_SET(vop, win, uv_mst, dma_addr);
 	}
 
-	if (win->phy->scl)
-		scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
-				    drm_rect_width(dest), drm_rect_height(dest),
-				    fb->pixel_format);
+	scl_vop_cal_scl_fac(vop, win, actual_w, actual_h,
+			    drm_rect_width(dest), drm_rect_height(dest),
+			    fb->pixel_format);
 
 	VOP_WIN_SET(vop, win, act_info, act_info);
 	VOP_WIN_SET(vop, win, dsp_info, dsp_info);
@@ -1098,9 +1117,9 @@ static bool vop_win_pending_is_complete(struct vop_win *vop_win)
 	dma_addr_t yrgb_mst;
 
 	if (!vop_win->enable)
-		return VOP_WIN_GET(vop_win->vop, vop_win->data, enable) == 0;
+		return VOP_WIN_GET(vop_win->vop, vop_win, enable) == 0;
 
-	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win->data);
+	yrgb_mst = VOP_WIN_GET_YRGBADDR(vop_win->vop, vop_win);
 
 	return yrgb_mst == vop_win->yrgb_mst;
 }
@@ -1112,7 +1131,7 @@ static void vop_handle_vblank(struct vop *vop)
 	unsigned long flags;
 	int i;
 
-	for (i = 0; i < vop->data->win_size; i++) {
+	for (i = 0; i < vop->num_wins; i++) {
 		if (!vop_win_pending_is_complete(&vop->win[i]))
 			return;
 	}
@@ -1176,15 +1195,35 @@ static irqreturn_t vop_isr(int irq, void *data)
 	return ret;
 }
 
+static int vop_plane_init(struct vop *vop, struct vop_win *win,
+			  unsigned long possible_crtcs)
+{
+	struct drm_plane *share = NULL;
+	int ret;
+
+	if (win->parent)
+		share = &win->parent->base;
+
+	ret = drm_share_plane_init(vop->drm_dev, &win->base, share,
+				   possible_crtcs, &vop_plane_funcs,
+				   win->data_formats, win->nformats, win->type);
+	if (ret) {
+		DRM_ERROR("failed to initialize plane\n");
+		return ret;
+	}
+	drm_plane_helper_add(&win->base, &plane_helper_funcs);
+
+	return 0;
+}
+
 static int vop_create_crtc(struct vop *vop)
 {
-	const struct vop_data *vop_data = vop->data;
 	struct device *dev = vop->dev;
 	struct drm_device *drm_dev = vop->drm_dev;
 	struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
 	struct drm_crtc *crtc = &vop->crtc;
 	struct device_node *port;
-	int ret;
+	int ret = 0;
 	int i;
 
 	/*
@@ -1192,30 +1231,22 @@ static int vop_create_crtc(struct vop *vop)
 	 * to pass them to drm_crtc_init_with_planes, which sets the
 	 * "possible_crtcs" to the newly initialized crtc.
 	 */
-	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-		const struct vop_win_data *win_data = vop_win->data;
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 
-		if (win_data->type != DRM_PLANE_TYPE_PRIMARY &&
-		    win_data->type != DRM_PLANE_TYPE_CURSOR)
+		if (win->type != DRM_PLANE_TYPE_PRIMARY &&
+		    win->type != DRM_PLANE_TYPE_CURSOR)
 			continue;
 
-		ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,
-					       0, &vop_plane_funcs,
-					       win_data->phy->data_formats,
-					       win_data->phy->nformats,
-					       win_data->type, NULL);
-		if (ret) {
-			DRM_ERROR("failed to initialize plane\n");
+		if (vop_plane_init(vop, win, 0))
 			goto err_cleanup_planes;
-		}
 
-		plane = &vop_win->base;
-		drm_plane_helper_add(plane, &plane_helper_funcs);
+		plane = &win->base;
 		if (plane->type == DRM_PLANE_TYPE_PRIMARY)
 			primary = plane;
 		else if (plane->type == DRM_PLANE_TYPE_CURSOR)
 			cursor = plane;
+
 	}
 
 	ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor,
@@ -1229,25 +1260,15 @@ static int vop_create_crtc(struct vop *vop)
 	 * Create drm_planes for overlay windows with possible_crtcs restricted
 	 * to the newly created crtc.
 	 */
-	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
-		const struct vop_win_data *win_data = vop_win->data;
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 		unsigned long possible_crtcs = 1 << drm_crtc_index(crtc);
 
-		if (win_data->type != DRM_PLANE_TYPE_OVERLAY)
+		if (win->type != DRM_PLANE_TYPE_OVERLAY)
 			continue;
 
-		ret = drm_universal_plane_init(vop->drm_dev, &vop_win->base,
-					       possible_crtcs,
-					       &vop_plane_funcs,
-					       win_data->phy->data_formats,
-					       win_data->phy->nformats,
-					       win_data->type, NULL);
-		if (ret) {
-			DRM_ERROR("failed to initialize overlay plane\n");
+		if (vop_plane_init(vop, win, possible_crtcs))
 			goto err_cleanup_crtc;
-		}
-		drm_plane_helper_add(&vop_win->base, &plane_helper_funcs);
 	}
 
 	port = of_get_child_by_name(dev->of_node, "port");
@@ -1362,8 +1383,8 @@ static int vop_initial(struct vop *vop)
 	for (i = 0; i < vop_data->table_size; i++)
 		vop_writel(vop, init_table[i].offset, init_table[i].value);
 
-	for (i = 0; i < vop_data->win_size; i++) {
-		const struct vop_win_data *win = &vop_data->win[i];
+	for (i = 0; i < vop->num_wins; i++) {
+		struct vop_win *win = &vop->win[i];
 
 		VOP_WIN_SET(vop, win, enable, 0);
 	}
@@ -1405,14 +1426,34 @@ err_unprepare_dclk:
 static void vop_win_init(struct vop *vop)
 {
 	const struct vop_data *vop_data = vop->data;
-	unsigned int i;
+	unsigned int i, j;
+	unsigned int num_wins = 0;
 
 	for (i = 0; i < vop_data->win_size; i++) {
-		struct vop_win *vop_win = &vop->win[i];
+		struct vop_win *vop_win = &vop->win[num_wins];
 		const struct vop_win_data *win_data = &vop_data->win[i];
 
-		vop_win->data = win_data;
+		vop_win->phy = win_data->phy;
+		vop_win->offset = win_data->base;
+		vop_win->type = win_data->type;
+		vop_win->data_formats = win_data->phy->data_formats;
+		vop_win->nformats = win_data->phy->nformats;
 		vop_win->vop = vop;
+		num_wins++;
+
+		for (j = 0; j < win_data->area_size; j++) {
+			struct vop_win *vop_area = &vop->win[num_wins];
+			const struct vop_win_phy *area = win_data->area[j];
+
+			vop_area->parent = vop_win;
+			vop_area->offset = vop_win->offset;
+			vop_area->phy = area;
+			vop_area->type = DRM_PLANE_TYPE_OVERLAY;
+			vop_area->data_formats = vop_win->data_formats;
+			vop_area->nformats = vop_win->nformats;
+			vop_area->vop = vop;
+			num_wins++;
+		}
 	}
 }
 
@@ -1424,14 +1465,21 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 	struct vop *vop;
 	struct resource *res;
 	size_t alloc_size;
-	int ret, irq;
+	int ret, irq, i;
+	int num_wins = 0;
 
 	vop_data = of_device_get_match_data(dev);
 	if (!vop_data)
 		return -ENODEV;
 
+	for (i = 0; i < vop_data->win_size; i++) {
+		const struct vop_win_data *win_data = &vop_data->win[i];
+
+		num_wins += win_data->area_size + 1;
+	}
+
 	/* Allocate vop struct and its vop_win array */
-	alloc_size = sizeof(*vop) + sizeof(*vop->win) * vop_data->win_size;
+	alloc_size = sizeof(*vop) + sizeof(*vop->win) * num_wins;
 	vop = devm_kzalloc(dev, alloc_size, GFP_KERNEL);
 	if (!vop)
 		return -ENOMEM;
@@ -1439,6 +1487,7 @@ static int vop_bind(struct device *dev, struct device *master, void *data)
 	vop->dev = dev;
 	vop->data = vop_data;
 	vop->drm_dev = drm_dev;
+	vop->num_wins = num_wins;
 	dev_set_drvdata(dev, vop);
 
 	vop_win_init(vop);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
index 071ff0b..def5afa 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h
@@ -122,8 +122,10 @@ struct vop_win_phy {
 
 struct vop_win_data {
 	uint32_t base;
-	const struct vop_win_phy *phy;
 	enum drm_plane_type type;
+	const struct vop_win_phy *phy;
+	const struct vop_win_phy **area;
+	unsigned int area_size;
 };
 
 struct vop_data {
-- 
1.9.1

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

* [PATCH 3/3] drm/rockchip: vop: rk3288: add area plane
  2016-07-26  7:46 ` Mark Yao
@ 2016-07-26  7:46   ` Mark Yao
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel
  Cc: Mark Yao

Change-Id: Iac8fde019020d8f1a671d52c1a4d91ad2d050d43
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 52 ++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 919992c..0f53ebd 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -103,7 +103,7 @@ static const struct vop_win_phy rk3288_win01_data = {
 static const struct vop_win_phy rk3288_win23_data = {
 	.data_formats = formats_win_lite,
 	.nformats = ARRAY_SIZE(formats_win_lite),
-	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
 	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
 	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
 	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
@@ -114,6 +114,36 @@ static const struct vop_win_phy rk3288_win23_data = {
 	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
 };
 
+static const struct vop_win_phy rk3288_area1_data = {
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 5),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO1, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST1, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST1, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 16),
+};
+
+static const struct vop_win_phy rk3288_area2_data = {
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 6),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO2, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST2, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST2, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR2_3, 0x1fff, 0),
+};
+
+static const struct vop_win_phy rk3288_area3_data = {
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 7),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO3, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST3, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST3, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR2_3, 0x1fff, 16),
+};
+
+static const struct vop_win_phy *rk3288_area_data[] = {
+	&rk3288_area1_data,
+	&rk3288_area2_data,
+	&rk3288_area3_data
+};
+
 static const struct vop_ctrl rk3288_ctrl_data = {
 	.standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22),
 	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
@@ -141,12 +171,14 @@ static const struct vop_reg_data rk3288_init_reg_table[] = {
 	{RK3288_DSP_CTRL0, 0x00000000},
 	{RK3288_WIN0_CTRL0, 0x00000080},
 	{RK3288_WIN1_CTRL0, 0x00000080},
-	/* TODO: Win2/3 support multiple area function, but we haven't found
-	 * a suitable way to use it yet, so let's just use them as other windows
-	 * with only area 0 enabled.
+	/*
+	 * Bit[0] is win2/3 gate en bit, there is no power consume with this
+	 * bit enable. the bit's function similar with area plane enable bit,
+	 * So default enable this bit, then We can control win2/3 area plane
+	 * with its enable bit.
 	 */
-	{RK3288_WIN2_CTRL0, 0x00000010},
-	{RK3288_WIN3_CTRL0, 0x00000010},
+	{RK3288_WIN2_CTRL0, 0x00000001},
+	{RK3288_WIN3_CTRL0, 0x00000001},
 };
 
 /*
@@ -161,9 +193,13 @@ static const struct vop_win_data rk3288_vop_win_data[] = {
 	{ .base = 0x40, .phy = &rk3288_win01_data,
 	  .type = DRM_PLANE_TYPE_OVERLAY },
 	{ .base = 0x00, .phy = &rk3288_win23_data,
-	  .type = DRM_PLANE_TYPE_OVERLAY },
+	  .type = DRM_PLANE_TYPE_OVERLAY,
+	  .area = rk3288_area_data,
+	  .area_size = ARRAY_SIZE(rk3288_area_data), },
 	{ .base = 0x50, .phy = &rk3288_win23_data,
-	  .type = DRM_PLANE_TYPE_CURSOR },
+	  .type = DRM_PLANE_TYPE_CURSOR,
+	  .area = rk3288_area_data,
+	  .area_size = ARRAY_SIZE(rk3288_area_data), },
 };
 
 static const int rk3288_vop_intrs[] = {
-- 
1.9.1

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

* [PATCH 3/3] drm/rockchip: vop: rk3288: add area plane
@ 2016-07-26  7:46   ` Mark Yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark Yao @ 2016-07-26  7:46 UTC (permalink / raw)
  To: linux-arm-kernel

Change-Id: Iac8fde019020d8f1a671d52c1a4d91ad2d050d43
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
---
 drivers/gpu/drm/rockchip/rockchip_vop_reg.c | 52 ++++++++++++++++++++++++-----
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index 919992c..0f53ebd 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -103,7 +103,7 @@ static const struct vop_win_phy rk3288_win01_data = {
 static const struct vop_win_phy rk3288_win23_data = {
 	.data_formats = formats_win_lite,
 	.nformats = ARRAY_SIZE(formats_win_lite),
-	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 0),
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 4),
 	.format = VOP_REG(RK3288_WIN2_CTRL0, 0x7, 1),
 	.rb_swap = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 12),
 	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO0, 0x0fff0fff, 0),
@@ -114,6 +114,36 @@ static const struct vop_win_phy rk3288_win23_data = {
 	.dst_alpha_ctl = VOP_REG(RK3288_WIN2_DST_ALPHA_CTRL, 0xff, 0),
 };
 
+static const struct vop_win_phy rk3288_area1_data = {
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 5),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO1, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST1, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST1, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR0_1, 0x1fff, 16),
+};
+
+static const struct vop_win_phy rk3288_area2_data = {
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 6),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO2, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST2, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST2, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR2_3, 0x1fff, 0),
+};
+
+static const struct vop_win_phy rk3288_area3_data = {
+	.enable = VOP_REG(RK3288_WIN2_CTRL0, 0x1, 7),
+	.dsp_info = VOP_REG(RK3288_WIN2_DSP_INFO3, 0x0fff0fff, 0),
+	.dsp_st = VOP_REG(RK3288_WIN2_DSP_ST3, 0x1fff1fff, 0),
+	.yrgb_mst = VOP_REG(RK3288_WIN2_MST3, 0xffffffff, 0),
+	.yrgb_vir = VOP_REG(RK3288_WIN2_VIR2_3, 0x1fff, 16),
+};
+
+static const struct vop_win_phy *rk3288_area_data[] = {
+	&rk3288_area1_data,
+	&rk3288_area2_data,
+	&rk3288_area3_data
+};
+
 static const struct vop_ctrl rk3288_ctrl_data = {
 	.standby = VOP_REG(RK3288_SYS_CTRL, 0x1, 22),
 	.gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
@@ -141,12 +171,14 @@ static const struct vop_reg_data rk3288_init_reg_table[] = {
 	{RK3288_DSP_CTRL0, 0x00000000},
 	{RK3288_WIN0_CTRL0, 0x00000080},
 	{RK3288_WIN1_CTRL0, 0x00000080},
-	/* TODO: Win2/3 support multiple area function, but we haven't found
-	 * a suitable way to use it yet, so let's just use them as other windows
-	 * with only area 0 enabled.
+	/*
+	 * Bit[0] is win2/3 gate en bit, there is no power consume with this
+	 * bit enable. the bit's function similar with area plane enable bit,
+	 * So default enable this bit, then We can control win2/3 area plane
+	 * with its enable bit.
 	 */
-	{RK3288_WIN2_CTRL0, 0x00000010},
-	{RK3288_WIN3_CTRL0, 0x00000010},
+	{RK3288_WIN2_CTRL0, 0x00000001},
+	{RK3288_WIN3_CTRL0, 0x00000001},
 };
 
 /*
@@ -161,9 +193,13 @@ static const struct vop_win_data rk3288_vop_win_data[] = {
 	{ .base = 0x40, .phy = &rk3288_win01_data,
 	  .type = DRM_PLANE_TYPE_OVERLAY },
 	{ .base = 0x00, .phy = &rk3288_win23_data,
-	  .type = DRM_PLANE_TYPE_OVERLAY },
+	  .type = DRM_PLANE_TYPE_OVERLAY,
+	  .area = rk3288_area_data,
+	  .area_size = ARRAY_SIZE(rk3288_area_data), },
 	{ .base = 0x50, .phy = &rk3288_win23_data,
-	  .type = DRM_PLANE_TYPE_CURSOR },
+	  .type = DRM_PLANE_TYPE_CURSOR,
+	  .area = rk3288_area_data,
+	  .area_size = ARRAY_SIZE(rk3288_area_data), },
 };
 
 static const int rk3288_vop_intrs[] = {
-- 
1.9.1

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

* Re: [PATCH 1/3] drm: introduce share plane
  2016-07-26  7:46 ` Mark Yao
  (?)
@ 2016-07-26  8:26   ` Daniel Vetter
  -1 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2016-07-26  8:26 UTC (permalink / raw)
  To: Mark Yao
  Cc: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
> 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@rock-chips.com>

This seems extremely hw specific, why exactly do we need to add a new
relationship on planes? What does this buy on _other_ drivers?

Imo this should be solved by virtualizing planes in the driver. Start out
by assigning planes, and if you can reuse one for sharing then do that,
otherwise allocate a new one. If there's not enough real planes, fail the
atomic_check.

This seems way to hw specific to be useful as a generic concept.
-Daniel

> ---
>  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
> 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  8:26   ` Daniel Vetter
  0 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2016-07-26  8:26 UTC (permalink / raw)
  To: Mark Yao; +Cc: linux-kernel, dri-devel, linux-rockchip, linux-arm-kernel

On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
> 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@rock-chips.com>

This seems extremely hw specific, why exactly do we need to add a new
relationship on planes? What does this buy on _other_ drivers?

Imo this should be solved by virtualizing planes in the driver. Start out
by assigning planes, and if you can reuse one for sharing then do that,
otherwise allocate a new one. If there's not enough real planes, fail the
atomic_check.

This seems way to hw specific to be useful as a generic concept.
-Daniel

> ---
>  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
> 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
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] 22+ messages in thread

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  8:26   ` Daniel Vetter
  0 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2016-07-26  8:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
> 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@rock-chips.com>

This seems extremely hw specific, why exactly do we need to add a new
relationship on planes? What does this buy on _other_ drivers?

Imo this should be solved by virtualizing planes in the driver. Start out
by assigning planes, and if you can reuse one for sharing then do that,
otherwise allocate a new one. If there's not enough real planes, fail the
atomic_check.

This seems way to hw specific to be useful as a generic concept.
-Daniel

> ---
>  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
> 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 1/3] drm: introduce share plane
  2016-07-26  8:26   ` Daniel Vetter
  (?)
@ 2016-07-26  9:51     ` Mark yao
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-26  9:51 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

On 2016年07月26日 16:26, Daniel Vetter wrote:
> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>> >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@rock-chips.com>
> This seems extremely hw specific, why exactly do we need to add a new
> relationship on planes? What does this buy on_other_  drivers?
Yes, now it's plane hardware specific, maybe others have same design, 
because this design
would save hardware resource to support multi-planes.

> Imo this should be solved by virtualizing planes in the driver. Start out
> by assigning planes, and if you can reuse one for sharing then do that,
> otherwise allocate a new one. If there's not enough real planes, fail the
> atomic_check.
I think that is too complex, trying with atomic_check I think it's not a 
good idea, userspace try planes every commit would be a heavy work.

Userspace need  know all planes relationship, group them, some display 
windows can put together, some can't,
too many permutation and combination, I think can't just commit with try.

example:
userspace:
windows 1: pos(0, 0)  size(1024, 100)
windows 2: pos(0, 50) size(400, 500)
windows 3: pos(0, 200) size(800, 300)

drm plane resources:
plane 0 and plane 1 is a group of share planes
plane 2 is common plane.

if userspace know the relationship, then they can assign windows 1 and 
window 3 to plane0 and plane 1. that would be success.
but if they don't know, assign window 1/2 to plane 0/1, failed, assign 
window 2/3 to plane 0/1, failed. mostly would get failed.

>
> This seems way to hw specific to be useful as a generic concept.

We want to change the drm_mode_getplane_res behavior, if userspace call 
DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
then we return full planes support to userspace, if don't, just make a 
group of share planes as one plane.
this work is on generic place.

> -Daniel
>
>

-- 
Mark Yao

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

* Re: [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  9:51     ` Mark yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-26  9:51 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

On 2016年07月26日 16:26, Daniel Vetter wrote:
> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>> >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@rock-chips.com>
> This seems extremely hw specific, why exactly do we need to add a new
> relationship on planes? What does this buy on_other_  drivers?
Yes, now it's plane hardware specific, maybe others have same design, 
because this design
would save hardware resource to support multi-planes.

> Imo this should be solved by virtualizing planes in the driver. Start out
> by assigning planes, and if you can reuse one for sharing then do that,
> otherwise allocate a new one. If there's not enough real planes, fail the
> atomic_check.
I think that is too complex, trying with atomic_check I think it's not a 
good idea, userspace try planes every commit would be a heavy work.

Userspace need  know all planes relationship, group them, some display 
windows can put together, some can't,
too many permutation and combination, I think can't just commit with try.

example:
userspace:
windows 1: pos(0, 0)  size(1024, 100)
windows 2: pos(0, 50) size(400, 500)
windows 3: pos(0, 200) size(800, 300)

drm plane resources:
plane 0 and plane 1 is a group of share planes
plane 2 is common plane.

if userspace know the relationship, then they can assign windows 1 and 
window 3 to plane0 and plane 1. that would be success.
but if they don't know, assign window 1/2 to plane 0/1, failed, assign 
window 2/3 to plane 0/1, failed. mostly would get failed.

>
> This seems way to hw specific to be useful as a generic concept.

We want to change the drm_mode_getplane_res behavior, if userspace call 
DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
then we return full planes support to userspace, if don't, just make a 
group of share planes as one plane.
this work is on generic place.

> -Daniel
>
>

-- 
Mark Yao


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

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

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-26  9:51     ` Mark yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-26  9:51 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016?07?26? 16:26, Daniel Vetter wrote:
> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>> >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@rock-chips.com>
> This seems extremely hw specific, why exactly do we need to add a new
> relationship on planes? What does this buy on_other_  drivers?
Yes, now it's plane hardware specific, maybe others have same design, 
because this design
would save hardware resource to support multi-planes.

> Imo this should be solved by virtualizing planes in the driver. Start out
> by assigning planes, and if you can reuse one for sharing then do that,
> otherwise allocate a new one. If there's not enough real planes, fail the
> atomic_check.
I think that is too complex, trying with atomic_check I think it's not a 
good idea, userspace try planes every commit would be a heavy work.

Userspace need  know all planes relationship, group them, some display 
windows can put together, some can't,
too many permutation and combination, I think can't just commit with try.

example:
userspace:
windows 1: pos(0, 0)  size(1024, 100)
windows 2: pos(0, 50) size(400, 500)
windows 3: pos(0, 200) size(800, 300)

drm plane resources:
plane 0 and plane 1 is a group of share planes
plane 2 is common plane.

if userspace know the relationship, then they can assign windows 1 and 
window 3 to plane0 and plane 1. that would be success.
but if they don't know, assign window 1/2 to plane 0/1, failed, assign 
window 2/3 to plane 0/1, failed. mostly would get failed.

>
> This seems way to hw specific to be useful as a generic concept.

We want to change the drm_mode_getplane_res behavior, if userspace call 
DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
then we return full planes support to userspace, if don't, just make a 
group of share planes as one plane.
this work is on generic place.

> -Daniel
>
>

-- 
?ark Yao

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

* Re: [PATCH 1/3] drm: introduce share plane
  2016-07-26  9:51     ` Mark yao
  (?)
@ 2016-07-28  3:01       ` Mark yao
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-28  3:01 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

Any ideas for the share planes?

This function is important for our series of vop full design.
     The series of vop is:
     IP version    chipname
     3.1           rk3288
     3.2           rk3368
     3.4           rk3366
     3.5           rk3399 big
     3.6           rk3399 lit
     3.7           rk322x

example on rk3288:  if not support share plane, each vop only support 
four planes, but if support this function, each vop can support ten planes.

On 2016年07月26日 17:51, Mark yao wrote:
> On 2016年07月26日 16:26, Daniel Vetter wrote:
>> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>>> >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@rock-chips.com>
>> This seems extremely hw specific, why exactly do we need to add a new
>> relationship on planes? What does this buy on_other_  drivers?
> Yes, now it's plane hardware specific, maybe others have same design, 
> because this design
> would save hardware resource to support multi-planes.
>
>> Imo this should be solved by virtualizing planes in the driver. Start 
>> out
>> by assigning planes, and if you can reuse one for sharing then do that,
>> otherwise allocate a new one. If there's not enough real planes, fail 
>> the
>> atomic_check.
> I think that is too complex, trying with atomic_check I think it's not 
> a good idea, userspace try planes every commit would be a heavy work.
>
> Userspace need  know all planes relationship, group them, some display 
> windows can put together, some can't,
> too many permutation and combination, I think can't just commit with try.
>
> example:
> userspace:
> windows 1: pos(0, 0)  size(1024, 100)
> windows 2: pos(0, 50) size(400, 500)
> windows 3: pos(0, 200) size(800, 300)
>
> drm plane resources:
> plane 0 and plane 1 is a group of share planes
> plane 2 is common plane.
>
> if userspace know the relationship, then they can assign windows 1 and 
> window 3 to plane0 and plane 1. that would be success.
> but if they don't know, assign window 1/2 to plane 0/1, failed, assign 
> window 2/3 to plane 0/1, failed. mostly would get failed.
>
>>
>> This seems way to hw specific to be useful as a generic concept.
>
> We want to change the drm_mode_getplane_res behavior, if userspace 
> call DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware 
> limit,
> then we return full planes support to userspace, if don't, just make a 
> group of share planes as one plane.
> this work is on generic place.
>
>> -Daniel
>>
>>
>


-- 
Mark Yao

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

* Re: [PATCH 1/3] drm: introduce share plane
@ 2016-07-28  3:01       ` Mark yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-28  3:01 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

Any ideas for the share planes?

This function is important for our series of vop full design.
     The series of vop is:
     IP version    chipname
     3.1           rk3288
     3.2           rk3368
     3.4           rk3366
     3.5           rk3399 big
     3.6           rk3399 lit
     3.7           rk322x

example on rk3288:  if not support share plane, each vop only support 
four planes, but if support this function, each vop can support ten planes.

On 2016年07月26日 17:51, Mark yao wrote:
> On 2016年07月26日 16:26, Daniel Vetter wrote:
>> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>>> >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@rock-chips.com>
>> This seems extremely hw specific, why exactly do we need to add a new
>> relationship on planes? What does this buy on_other_  drivers?
> Yes, now it's plane hardware specific, maybe others have same design, 
> because this design
> would save hardware resource to support multi-planes.
>
>> Imo this should be solved by virtualizing planes in the driver. Start 
>> out
>> by assigning planes, and if you can reuse one for sharing then do that,
>> otherwise allocate a new one. If there's not enough real planes, fail 
>> the
>> atomic_check.
> I think that is too complex, trying with atomic_check I think it's not 
> a good idea, userspace try planes every commit would be a heavy work.
>
> Userspace need  know all planes relationship, group them, some display 
> windows can put together, some can't,
> too many permutation and combination, I think can't just commit with try.
>
> example:
> userspace:
> windows 1: pos(0, 0)  size(1024, 100)
> windows 2: pos(0, 50) size(400, 500)
> windows 3: pos(0, 200) size(800, 300)
>
> drm plane resources:
> plane 0 and plane 1 is a group of share planes
> plane 2 is common plane.
>
> if userspace know the relationship, then they can assign windows 1 and 
> window 3 to plane0 and plane 1. that would be success.
> but if they don't know, assign window 1/2 to plane 0/1, failed, assign 
> window 2/3 to plane 0/1, failed. mostly would get failed.
>
>>
>> This seems way to hw specific to be useful as a generic concept.
>
> We want to change the drm_mode_getplane_res behavior, if userspace 
> call DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware 
> limit,
> then we return full planes support to userspace, if don't, just make a 
> group of share planes as one plane.
> this work is on generic place.
>
>> -Daniel
>>
>>
>


-- 
Mark Yao


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

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

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-28  3:01       ` Mark yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-28  3:01 UTC (permalink / raw)
  To: linux-arm-kernel

Any ideas for the share planes?

This function is important for our series of vop full design.
     The series of vop is:
     IP version    chipname
     3.1           rk3288
     3.2           rk3368
     3.4           rk3366
     3.5           rk3399 big
     3.6           rk3399 lit
     3.7           rk322x

example on rk3288:  if not support share plane, each vop only support 
four planes, but if support this function, each vop can support ten planes.

On 2016?07?26? 17:51, Mark yao wrote:
> On 2016?07?26? 16:26, Daniel Vetter wrote:
>> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>>> >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@rock-chips.com>
>> This seems extremely hw specific, why exactly do we need to add a new
>> relationship on planes? What does this buy on_other_  drivers?
> Yes, now it's plane hardware specific, maybe others have same design, 
> because this design
> would save hardware resource to support multi-planes.
>
>> Imo this should be solved by virtualizing planes in the driver. Start 
>> out
>> by assigning planes, and if you can reuse one for sharing then do that,
>> otherwise allocate a new one. If there's not enough real planes, fail 
>> the
>> atomic_check.
> I think that is too complex, trying with atomic_check I think it's not 
> a good idea, userspace try planes every commit would be a heavy work.
>
> Userspace need  know all planes relationship, group them, some display 
> windows can put together, some can't,
> too many permutation and combination, I think can't just commit with try.
>
> example:
> userspace:
> windows 1: pos(0, 0)  size(1024, 100)
> windows 2: pos(0, 50) size(400, 500)
> windows 3: pos(0, 200) size(800, 300)
>
> drm plane resources:
> plane 0 and plane 1 is a group of share planes
> plane 2 is common plane.
>
> if userspace know the relationship, then they can assign windows 1 and 
> window 3 to plane0 and plane 1. that would be success.
> but if they don't know, assign window 1/2 to plane 0/1, failed, assign 
> window 2/3 to plane 0/1, failed. mostly would get failed.
>
>>
>> This seems way to hw specific to be useful as a generic concept.
>
> We want to change the drm_mode_getplane_res behavior, if userspace 
> call DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware 
> limit,
> then we return full planes support to userspace, if don't, just make a 
> group of share planes as one plane.
> this work is on generic place.
>
>> -Daniel
>>
>>
>


-- 
?ark Yao

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

* Re: [PATCH 1/3] drm: introduce share plane
  2016-07-28  3:01       ` Mark yao
  (?)
@ 2016-07-28  8:03         ` Daniel Vetter
  -1 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2016-07-28  8:03 UTC (permalink / raw)
  To: Mark yao
  Cc: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

On Thu, Jul 28, 2016 at 11:01:04AM +0800, Mark yao wrote:
> Any ideas for the share planes?
> 
> This function is important for our series of vop full design.
>     The series of vop is:
>     IP version    chipname
>     3.1           rk3288
>     3.2           rk3368
>     3.4           rk3366
>     3.5           rk3399 big
>     3.6           rk3399 lit
>     3.7           rk322x
> 
> example on rk3288:  if not support share plane, each vop only support four
> planes, but if support this function, each vop can support ten planes.

Like I said, register 10 planes in the kernel driver, figure out a good
way to actually allocate them to hw resources. We have a similar issue on
skl/bxt in the i915 driver where there's only a limited amount of
scalers, and we need to dynamically allocate them to drm_plane. Here you
have fancy amount of scanout engines which you need to dynamically
allocate.

> On 2016年07月26日 17:51, Mark yao wrote:
> > On 2016年07月26日 16:26, Daniel Vetter wrote:
> > > On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
> > > > >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@rock-chips.com>
> > > This seems extremely hw specific, why exactly do we need to add a new
> > > relationship on planes? What does this buy on_other_  drivers?
> > Yes, now it's plane hardware specific, maybe others have same design,
> > because this design
> > would save hardware resource to support multi-planes.
> > 
> > > Imo this should be solved by virtualizing planes in the driver.
> > > Start out
> > > by assigning planes, and if you can reuse one for sharing then do that,
> > > otherwise allocate a new one. If there's not enough real planes,
> > > fail the
> > > atomic_check.
> > I think that is too complex, trying with atomic_check I think it's not a
> > good idea, userspace try planes every commit would be a heavy work.
> > 
> > Userspace need  know all planes relationship, group them, some display
> > windows can put together, some can't,
> > too many permutation and combination, I think can't just commit with try.
> > 
> > example:
> > userspace:
> > windows 1: pos(0, 0)  size(1024, 100)
> > windows 2: pos(0, 50) size(400, 500)
> > windows 3: pos(0, 200) size(800, 300)
> > 
> > drm plane resources:
> > plane 0 and plane 1 is a group of share planes
> > plane 2 is common plane.
> > 
> > if userspace know the relationship, then they can assign windows 1 and
> > window 3 to plane0 and plane 1. that would be success.
> > but if they don't know, assign window 1/2 to plane 0/1, failed, assign
> > window 2/3 to plane 0/1, failed. mostly would get failed.

You can still do this with the design I describe. The only difference is
that you allow generic userspace to make optimal use of your planes, too.

> > > This seems way to hw specific to be useful as a generic concept.
> > 
> > We want to change the drm_mode_getplane_res behavior, if userspace call
> > DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
> > then we return full planes support to userspace, if don't, just make a
> > group of share planes as one plane.
> > this work is on generic place.

So ... do you have patches for all the generic kms userspace that's out
there? Are those reviewed and ready for merging?

Adding new userspace abi is much, much, much harder than sovling this in
the vop driver. I'm working on some documentation to make this all clear
(since many arm folks seem unaware of the uapi rules we have in the drm
subsystem). But really, you're trying the much harder route with this
patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 1/3] drm: introduce share plane
@ 2016-07-28  8:03         ` Daniel Vetter
  0 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2016-07-28  8:03 UTC (permalink / raw)
  To: Mark yao; +Cc: linux-kernel, dri-devel, linux-rockchip, linux-arm-kernel

On Thu, Jul 28, 2016 at 11:01:04AM +0800, Mark yao wrote:
> Any ideas for the share planes?
> 
> This function is important for our series of vop full design.
>     The series of vop is:
>     IP version    chipname
>     3.1           rk3288
>     3.2           rk3368
>     3.4           rk3366
>     3.5           rk3399 big
>     3.6           rk3399 lit
>     3.7           rk322x
> 
> example on rk3288:  if not support share plane, each vop only support four
> planes, but if support this function, each vop can support ten planes.

Like I said, register 10 planes in the kernel driver, figure out a good
way to actually allocate them to hw resources. We have a similar issue on
skl/bxt in the i915 driver where there's only a limited amount of
scalers, and we need to dynamically allocate them to drm_plane. Here you
have fancy amount of scanout engines which you need to dynamically
allocate.

> On 2016年07月26日 17:51, Mark yao wrote:
> > On 2016年07月26日 16:26, Daniel Vetter wrote:
> > > On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
> > > > >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@rock-chips.com>
> > > This seems extremely hw specific, why exactly do we need to add a new
> > > relationship on planes? What does this buy on_other_  drivers?
> > Yes, now it's plane hardware specific, maybe others have same design,
> > because this design
> > would save hardware resource to support multi-planes.
> > 
> > > Imo this should be solved by virtualizing planes in the driver.
> > > Start out
> > > by assigning planes, and if you can reuse one for sharing then do that,
> > > otherwise allocate a new one. If there's not enough real planes,
> > > fail the
> > > atomic_check.
> > I think that is too complex, trying with atomic_check I think it's not a
> > good idea, userspace try planes every commit would be a heavy work.
> > 
> > Userspace need  know all planes relationship, group them, some display
> > windows can put together, some can't,
> > too many permutation and combination, I think can't just commit with try.
> > 
> > example:
> > userspace:
> > windows 1: pos(0, 0)  size(1024, 100)
> > windows 2: pos(0, 50) size(400, 500)
> > windows 3: pos(0, 200) size(800, 300)
> > 
> > drm plane resources:
> > plane 0 and plane 1 is a group of share planes
> > plane 2 is common plane.
> > 
> > if userspace know the relationship, then they can assign windows 1 and
> > window 3 to plane0 and plane 1. that would be success.
> > but if they don't know, assign window 1/2 to plane 0/1, failed, assign
> > window 2/3 to plane 0/1, failed. mostly would get failed.

You can still do this with the design I describe. The only difference is
that you allow generic userspace to make optimal use of your planes, too.

> > > This seems way to hw specific to be useful as a generic concept.
> > 
> > We want to change the drm_mode_getplane_res behavior, if userspace call
> > DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
> > then we return full planes support to userspace, if don't, just make a
> > group of share planes as one plane.
> > this work is on generic place.

So ... do you have patches for all the generic kms userspace that's out
there? Are those reviewed and ready for merging?

Adding new userspace abi is much, much, much harder than sovling this in
the vop driver. I'm working on some documentation to make this all clear
(since many arm folks seem unaware of the uapi rules we have in the drm
subsystem). But really, you're trying the much harder route with this
patch.
-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] 22+ messages in thread

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-28  8:03         ` Daniel Vetter
  0 siblings, 0 replies; 22+ messages in thread
From: Daniel Vetter @ 2016-07-28  8:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jul 28, 2016 at 11:01:04AM +0800, Mark yao wrote:
> Any ideas for the share planes?
> 
> This function is important for our series of vop full design.
>     The series of vop is:
>     IP version    chipname
>     3.1           rk3288
>     3.2           rk3368
>     3.4           rk3366
>     3.5           rk3399 big
>     3.6           rk3399 lit
>     3.7           rk322x
> 
> example on rk3288:  if not support share plane, each vop only support four
> planes, but if support this function, each vop can support ten planes.

Like I said, register 10 planes in the kernel driver, figure out a good
way to actually allocate them to hw resources. We have a similar issue on
skl/bxt in the i915 driver where there's only a limited amount of
scalers, and we need to dynamically allocate them to drm_plane. Here you
have fancy amount of scanout engines which you need to dynamically
allocate.

> On 2016?07?26? 17:51, Mark yao wrote:
> > On 2016?07?26? 16:26, Daniel Vetter wrote:
> > > On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
> > > > >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@rock-chips.com>
> > > This seems extremely hw specific, why exactly do we need to add a new
> > > relationship on planes? What does this buy on_other_  drivers?
> > Yes, now it's plane hardware specific, maybe others have same design,
> > because this design
> > would save hardware resource to support multi-planes.
> > 
> > > Imo this should be solved by virtualizing planes in the driver.
> > > Start out
> > > by assigning planes, and if you can reuse one for sharing then do that,
> > > otherwise allocate a new one. If there's not enough real planes,
> > > fail the
> > > atomic_check.
> > I think that is too complex, trying with atomic_check I think it's not a
> > good idea, userspace try planes every commit would be a heavy work.
> > 
> > Userspace need  know all planes relationship, group them, some display
> > windows can put together, some can't,
> > too many permutation and combination, I think can't just commit with try.
> > 
> > example:
> > userspace:
> > windows 1: pos(0, 0)  size(1024, 100)
> > windows 2: pos(0, 50) size(400, 500)
> > windows 3: pos(0, 200) size(800, 300)
> > 
> > drm plane resources:
> > plane 0 and plane 1 is a group of share planes
> > plane 2 is common plane.
> > 
> > if userspace know the relationship, then they can assign windows 1 and
> > window 3 to plane0 and plane 1. that would be success.
> > but if they don't know, assign window 1/2 to plane 0/1, failed, assign
> > window 2/3 to plane 0/1, failed. mostly would get failed.

You can still do this with the design I describe. The only difference is
that you allow generic userspace to make optimal use of your planes, too.

> > > This seems way to hw specific to be useful as a generic concept.
> > 
> > We want to change the drm_mode_getplane_res behavior, if userspace call
> > DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
> > then we return full planes support to userspace, if don't, just make a
> > group of share planes as one plane.
> > this work is on generic place.

So ... do you have patches for all the generic kms userspace that's out
there? Are those reviewed and ready for merging?

Adding new userspace abi is much, much, much harder than sovling this in
the vop driver. I'm working on some documentation to make this all clear
(since many arm folks seem unaware of the uapi rules we have in the drm
subsystem). But really, you're trying the much harder route with this
patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [PATCH 1/3] drm: introduce share plane
  2016-07-28  8:03         ` Daniel Vetter
  (?)
@ 2016-07-28  9:28           ` Mark yao
  -1 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-28  9:28 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

On 2016年07月28日 16:03, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 11:01:04AM +0800, Mark yao wrote:
>> Any ideas for the share planes?
>>
>> This function is important for our series of vop full design.
>>      The series of vop is:
>>      IP version    chipname
>>      3.1           rk3288
>>      3.2           rk3368
>>      3.4           rk3366
>>      3.5           rk3399 big
>>      3.6           rk3399 lit
>>      3.7           rk322x
>>
>> example on rk3288:  if not support share plane, each vop only support four
>> planes, but if support this function, each vop can support ten planes.
> Like I said, register 10 planes in the kernel driver, figure out a good
> way to actually allocate them to hw resources. We have a similar issue on
> skl/bxt in the i915 driver where there's only a limited amount of
> scalers, and we need to dynamically allocate them to drm_plane. Here you
> have fancy amount of scanout engines which you need to dynamically
> allocate.
>
>> On 2016年07月26日 17:51, Mark yao wrote:
>>> On 2016年07月26日 16:26, Daniel Vetter wrote:
>>>> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>>>>>> 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@rock-chips.com>
>>>> This seems extremely hw specific, why exactly do we need to add a new
>>>> relationship on planes? What does this buy on_other_  drivers?
>>> Yes, now it's plane hardware specific, maybe others have same design,
>>> because this design
>>> would save hardware resource to support multi-planes.
>>>
>>>> Imo this should be solved by virtualizing planes in the driver.
>>>> Start out
>>>> by assigning planes, and if you can reuse one for sharing then do that,
>>>> otherwise allocate a new one. If there's not enough real planes,
>>>> fail the
>>>> atomic_check.
>>> I think that is too complex, trying with atomic_check I think it's not a
>>> good idea, userspace try planes every commit would be a heavy work.
>>>
>>> Userspace need  know all planes relationship, group them, some display
>>> windows can put together, some can't,
>>> too many permutation and combination, I think can't just commit with try.
>>>
>>> example:
>>> userspace:
>>> windows 1: pos(0, 0)  size(1024, 100)
>>> windows 2: pos(0, 50) size(400, 500)
>>> windows 3: pos(0, 200) size(800, 300)
>>>
>>> drm plane resources:
>>> plane 0 and plane 1 is a group of share planes
>>> plane 2 is common plane.
>>>
>>> if userspace know the relationship, then they can assign windows 1 and
>>> window 3 to plane0 and plane 1. that would be success.
>>> but if they don't know, assign window 1/2 to plane 0/1, failed, assign
>>> window 2/3 to plane 0/1, failed. mostly would get failed.
> You can still do this with the design I describe. The only difference is
> that you allow generic userspace to make optimal use of your planes, too.
>
>>>> This seems way to hw specific to be useful as a generic concept.
>>> We want to change the drm_mode_getplane_res behavior, if userspace call
>>> DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
>>> then we return full planes support to userspace, if don't, just make a
>>> group of share planes as one plane.
>>> this work is on generic place.
> So ... do you have patches for all the generic kms userspace that's out
> there? Are those reviewed and ready for merging?
No, we have no other patches send to generic kms userspace upstream.

We use it on our internal userspace application now.

on our userspace application:
1, directly call drmSetClientCap(fd(), DRM_CLIENT_CAP_SHARE_PLANES, 1);
2, get planes with drmModeGetResources(fd());
3, get plane share id with drmModeObjectGetProperties,
4, group the planes with share id, if two plane use same "share id", 
that means these plane is on the same group
5, judge the plane's limit when doing plane commit.

on userspace only add a new ioctl macro DRM_CLIENT_CAP_SHARE_PLANES.

> Adding new userspace abi is much, much, much harder than sovling this in
> the vop driver. I'm working on some documentation to make this all clear
> (since many arm folks seem unaware of the uapi rules we have in the drm
> subsystem). But really, you're trying the much harder route with this
> patch.
Hmmm, So sad, you are right, change the generic api is a harder work.

Ok, I will try your advice.

Thanks.

> -Daniel

-- 
Mark Yao

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

* Re: [PATCH 1/3] drm: introduce share plane
@ 2016-07-28  9:28           ` Mark yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-28  9:28 UTC (permalink / raw)
  To: David Airlie, Heiko Stuebner, dri-devel, linux-arm-kernel,
	linux-rockchip, linux-kernel

On 2016年07月28日 16:03, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 11:01:04AM +0800, Mark yao wrote:
>> Any ideas for the share planes?
>>
>> This function is important for our series of vop full design.
>>      The series of vop is:
>>      IP version    chipname
>>      3.1           rk3288
>>      3.2           rk3368
>>      3.4           rk3366
>>      3.5           rk3399 big
>>      3.6           rk3399 lit
>>      3.7           rk322x
>>
>> example on rk3288:  if not support share plane, each vop only support four
>> planes, but if support this function, each vop can support ten planes.
> Like I said, register 10 planes in the kernel driver, figure out a good
> way to actually allocate them to hw resources. We have a similar issue on
> skl/bxt in the i915 driver where there's only a limited amount of
> scalers, and we need to dynamically allocate them to drm_plane. Here you
> have fancy amount of scanout engines which you need to dynamically
> allocate.
>
>> On 2016年07月26日 17:51, Mark yao wrote:
>>> On 2016年07月26日 16:26, Daniel Vetter wrote:
>>>> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>>>>>> 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@rock-chips.com>
>>>> This seems extremely hw specific, why exactly do we need to add a new
>>>> relationship on planes? What does this buy on_other_  drivers?
>>> Yes, now it's plane hardware specific, maybe others have same design,
>>> because this design
>>> would save hardware resource to support multi-planes.
>>>
>>>> Imo this should be solved by virtualizing planes in the driver.
>>>> Start out
>>>> by assigning planes, and if you can reuse one for sharing then do that,
>>>> otherwise allocate a new one. If there's not enough real planes,
>>>> fail the
>>>> atomic_check.
>>> I think that is too complex, trying with atomic_check I think it's not a
>>> good idea, userspace try planes every commit would be a heavy work.
>>>
>>> Userspace need  know all planes relationship, group them, some display
>>> windows can put together, some can't,
>>> too many permutation and combination, I think can't just commit with try.
>>>
>>> example:
>>> userspace:
>>> windows 1: pos(0, 0)  size(1024, 100)
>>> windows 2: pos(0, 50) size(400, 500)
>>> windows 3: pos(0, 200) size(800, 300)
>>>
>>> drm plane resources:
>>> plane 0 and plane 1 is a group of share planes
>>> plane 2 is common plane.
>>>
>>> if userspace know the relationship, then they can assign windows 1 and
>>> window 3 to plane0 and plane 1. that would be success.
>>> but if they don't know, assign window 1/2 to plane 0/1, failed, assign
>>> window 2/3 to plane 0/1, failed. mostly would get failed.
> You can still do this with the design I describe. The only difference is
> that you allow generic userspace to make optimal use of your planes, too.
>
>>>> This seems way to hw specific to be useful as a generic concept.
>>> We want to change the drm_mode_getplane_res behavior, if userspace call
>>> DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
>>> then we return full planes support to userspace, if don't, just make a
>>> group of share planes as one plane.
>>> this work is on generic place.
> So ... do you have patches for all the generic kms userspace that's out
> there? Are those reviewed and ready for merging?
No, we have no other patches send to generic kms userspace upstream.

We use it on our internal userspace application now.

on our userspace application:
1, directly call drmSetClientCap(fd(), DRM_CLIENT_CAP_SHARE_PLANES, 1);
2, get planes with drmModeGetResources(fd());
3, get plane share id with drmModeObjectGetProperties,
4, group the planes with share id, if two plane use same "share id", 
that means these plane is on the same group
5, judge the plane's limit when doing plane commit.

on userspace only add a new ioctl macro DRM_CLIENT_CAP_SHARE_PLANES.

> Adding new userspace abi is much, much, much harder than sovling this in
> the vop driver. I'm working on some documentation to make this all clear
> (since many arm folks seem unaware of the uapi rules we have in the drm
> subsystem). But really, you're trying the much harder route with this
> patch.
Hmmm, So sad, you are right, change the generic api is a harder work.

Ok, I will try your advice.

Thanks.

> -Daniel

-- 
Mark Yao


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

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

* [PATCH 1/3] drm: introduce share plane
@ 2016-07-28  9:28           ` Mark yao
  0 siblings, 0 replies; 22+ messages in thread
From: Mark yao @ 2016-07-28  9:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016?07?28? 16:03, Daniel Vetter wrote:
> On Thu, Jul 28, 2016 at 11:01:04AM +0800, Mark yao wrote:
>> Any ideas for the share planes?
>>
>> This function is important for our series of vop full design.
>>      The series of vop is:
>>      IP version    chipname
>>      3.1           rk3288
>>      3.2           rk3368
>>      3.4           rk3366
>>      3.5           rk3399 big
>>      3.6           rk3399 lit
>>      3.7           rk322x
>>
>> example on rk3288:  if not support share plane, each vop only support four
>> planes, but if support this function, each vop can support ten planes.
> Like I said, register 10 planes in the kernel driver, figure out a good
> way to actually allocate them to hw resources. We have a similar issue on
> skl/bxt in the i915 driver where there's only a limited amount of
> scalers, and we need to dynamically allocate them to drm_plane. Here you
> have fancy amount of scanout engines which you need to dynamically
> allocate.
>
>> On 2016?07?26? 17:51, Mark yao wrote:
>>> On 2016?07?26? 16:26, Daniel Vetter wrote:
>>>> On Tue, Jul 26, 2016 at 03:46:32PM +0800, Mark Yao wrote:
>>>>>> 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@rock-chips.com>
>>>> This seems extremely hw specific, why exactly do we need to add a new
>>>> relationship on planes? What does this buy on_other_  drivers?
>>> Yes, now it's plane hardware specific, maybe others have same design,
>>> because this design
>>> would save hardware resource to support multi-planes.
>>>
>>>> Imo this should be solved by virtualizing planes in the driver.
>>>> Start out
>>>> by assigning planes, and if you can reuse one for sharing then do that,
>>>> otherwise allocate a new one. If there's not enough real planes,
>>>> fail the
>>>> atomic_check.
>>> I think that is too complex, trying with atomic_check I think it's not a
>>> good idea, userspace try planes every commit would be a heavy work.
>>>
>>> Userspace need  know all planes relationship, group them, some display
>>> windows can put together, some can't,
>>> too many permutation and combination, I think can't just commit with try.
>>>
>>> example:
>>> userspace:
>>> windows 1: pos(0, 0)  size(1024, 100)
>>> windows 2: pos(0, 50) size(400, 500)
>>> windows 3: pos(0, 200) size(800, 300)
>>>
>>> drm plane resources:
>>> plane 0 and plane 1 is a group of share planes
>>> plane 2 is common plane.
>>>
>>> if userspace know the relationship, then they can assign windows 1 and
>>> window 3 to plane0 and plane 1. that would be success.
>>> but if they don't know, assign window 1/2 to plane 0/1, failed, assign
>>> window 2/3 to plane 0/1, failed. mostly would get failed.
> You can still do this with the design I describe. The only difference is
> that you allow generic userspace to make optimal use of your planes, too.
>
>>>> This seems way to hw specific to be useful as a generic concept.
>>> We want to change the drm_mode_getplane_res behavior, if userspace call
>>> DRM_CLIENT_CAP_SHARE_PLANES, that means userspace know hardware limit,
>>> then we return full planes support to userspace, if don't, just make a
>>> group of share planes as one plane.
>>> this work is on generic place.
> So ... do you have patches for all the generic kms userspace that's out
> there? Are those reviewed and ready for merging?
No, we have no other patches send to generic kms userspace upstream.

We use it on our internal userspace application now.

on our userspace application:
1, directly call drmSetClientCap(fd(), DRM_CLIENT_CAP_SHARE_PLANES, 1);
2, get planes with drmModeGetResources(fd());
3, get plane share id with drmModeObjectGetProperties,
4, group the planes with share id, if two plane use same "share id", 
that means these plane is on the same group
5, judge the plane's limit when doing plane commit.

on userspace only add a new ioctl macro DRM_CLIENT_CAP_SHARE_PLANES.

> Adding new userspace abi is much, much, much harder than sovling this in
> the vop driver. I'm working on some documentation to make this all clear
> (since many arm folks seem unaware of the uapi rules we have in the drm
> subsystem). But really, you're trying the much harder route with this
> patch.
Hmmm, So sad, you are right, change the generic api is a harder work.

Ok, I will try your advice.

Thanks.

> -Daniel

-- 
?ark Yao

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

end of thread, other threads:[~2016-07-28  9:29 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-26  7:46 [PATCH 1/3] drm: introduce share plane Mark Yao
2016-07-26  7:46 ` Mark Yao
2016-07-26  7:46 ` Mark Yao
2016-07-26  7:46 ` [PATCH 2/3] drm/rockchip: vop: support multi area plane Mark Yao
2016-07-26  7:46   ` Mark Yao
2016-07-26  7:46 ` [PATCH 3/3] drm/rockchip: vop: rk3288: add " Mark Yao
2016-07-26  7:46   ` Mark Yao
2016-07-26  8:26 ` [PATCH 1/3] drm: introduce share plane Daniel Vetter
2016-07-26  8:26   ` Daniel Vetter
2016-07-26  8:26   ` Daniel Vetter
2016-07-26  9:51   ` Mark yao
2016-07-26  9:51     ` Mark yao
2016-07-26  9:51     ` Mark yao
2016-07-28  3:01     ` Mark yao
2016-07-28  3:01       ` Mark yao
2016-07-28  3:01       ` Mark yao
2016-07-28  8:03       ` Daniel Vetter
2016-07-28  8:03         ` Daniel Vetter
2016-07-28  8:03         ` Daniel Vetter
2016-07-28  9:28         ` Mark yao
2016-07-28  9:28           ` Mark yao
2016-07-28  9:28           ` Mark yao

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.