mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
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> Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
@@ -318,6 +318,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;
|
||||
|
||||
@@ -225,7 +225,17 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
|
||||
if (!prop)
|
||||
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)
|
||||
|
||||
@@ -332,6 +332,97 @@ 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,
|
||||
NULL, 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
|
||||
@@ -359,7 +450,12 @@ void drm_plane_cleanup(struct drm_plane *plane)
|
||||
|
||||
list_del(&plane->head);
|
||||
dev->mode_config.num_total_plane--;
|
||||
if (plane->parent) {
|
||||
dev->mode_config.num_share_plane--;
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_OVERLAY)
|
||||
dev->mode_config.num_share_overlay_plane--;
|
||||
}
|
||||
WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
|
||||
if (plane->state && plane->funcs->atomic_destroy_state)
|
||||
plane->funcs->atomic_destroy_state(plane, plane->state);
|
||||
@@ -487,6 +583,8 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
|
||||
!file_priv->universal_planes)
|
||||
continue;
|
||||
|
||||
if (plane->parent && !file_priv->share_planes)
|
||||
continue;
|
||||
if (drm_lease_held(file_priv, plane->base.id)) {
|
||||
if (count < plane_resp->count_planes &&
|
||||
put_user(plane->base.id, plane_ptr + count))
|
||||
|
||||
@@ -181,6 +181,12 @@ struct drm_file {
|
||||
*/
|
||||
unsigned universal_planes:1;
|
||||
|
||||
/**
|
||||
* True if client understands share planes and
|
||||
* hardware support share planes.
|
||||
*/
|
||||
unsigned share_planes:1;
|
||||
|
||||
/** @atomic: True if client understands atomic properties. */
|
||||
unsigned atomic:1;
|
||||
|
||||
|
||||
@@ -474,6 +474,12 @@ struct drm_mode_config {
|
||||
* need any locks.
|
||||
*/
|
||||
int num_total_plane;
|
||||
/**
|
||||
* @num_share_plane: number of share planes on this device
|
||||
* @num_share_overlay_plane: number of overlay planes on this device
|
||||
*/
|
||||
int num_share_plane;
|
||||
int num_share_overlay_plane;
|
||||
/**
|
||||
* @plane_list:
|
||||
*
|
||||
@@ -525,6 +531,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;
|
||||
|
||||
/**
|
||||
* @property_blob_list:
|
||||
*
|
||||
|
||||
@@ -536,6 +536,9 @@ struct drm_plane {
|
||||
/** @dev: DRM device this plane belongs to */
|
||||
struct drm_device *dev;
|
||||
|
||||
/* @parent: this plane share some resources with parent plane */
|
||||
struct drm_plane *parent;
|
||||
|
||||
/**
|
||||
* @head:
|
||||
*
|
||||
@@ -696,6 +699,13 @@ 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);
|
||||
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);
|
||||
void drm_plane_cleanup(struct drm_plane *plane);
|
||||
|
||||
/**
|
||||
|
||||
@@ -696,6 +696,13 @@ struct drm_get_cap {
|
||||
*/
|
||||
#define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5
|
||||
|
||||
/*
|
||||
* DRM_CLIENT_CAP_SHARE_PLANES
|
||||
*
|
||||
* If set to 1, the DRM core will expose share planes to userspace.
|
||||
*/
|
||||
#define DRM_CLIENT_CAP_SHARE_PLANES 6
|
||||
|
||||
/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
|
||||
struct drm_set_client_cap {
|
||||
__u64 capability;
|
||||
|
||||
Reference in New Issue
Block a user