drm: introduce share plane

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.

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.

Change-Id: Iecc3d8e7f1ce29d567cdbad689ba4dbad3d594e1
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
Mark Yao 2016-04-26 19:46:57 +08:00 committed by Huang, Tao
parent e5683dd6c1
commit eaf6764dee
5 changed files with 147 additions and 0 deletions

View File

@ -1249,6 +1249,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
@ -1271,6 +1361,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);
@ -1402,6 +1497,18 @@ 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_IMMUTABLE,
"SHARE_FLAGS", 0, UINT_MAX);
if (!prop)
return -ENOMEM;
dev->mode_config.prop_share_flags = prop;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"SRC_X", 0, UINT_MAX);
if (!prop)
@ -2208,6 +2315,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
@ -2226,6 +2339,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;

View File

@ -337,6 +337,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;

View File

@ -309,6 +309,11 @@ struct drm_file {
unsigned universal_planes:1;
/* 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 allowed to gain master privileges for @master.
* Protected by struct drm_device::master_mutex.

View File

@ -827,6 +827,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
* @base: base mode object
* @possible_crtcs: pipes this plane can be bound to
@ -844,6 +845,7 @@ enum drm_plane_type {
*/
struct drm_plane {
struct drm_device *dev;
struct drm_plane *parent;
struct list_head head;
struct drm_modeset_lock mutex;
@ -1074,6 +1076,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;
@ -1094,6 +1098,10 @@ struct drm_mode_config {
struct mutex blob_lock;
/* pointers to share properties */
struct drm_property *prop_share_id;
struct drm_property *prop_share_flags;
/* pointers to standard properties */
struct list_head property_blob_list;
struct drm_property *edid_property;
@ -1269,6 +1277,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);
extern unsigned int drm_plane_index(struct drm_plane *plane);
extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);

View File

@ -662,6 +662,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;