@@ -1959,6 +1959,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
struct drm_plane *plane;
uint32_t __user *plane_ptr;
int copied = 0, ret = 0;
+ unsigned num_planes;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -1966,17 +1967,26 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
config = &dev->mode_config;
+ if (file_priv->universal_planes)
+ num_planes = config->num_total_plane;
+ else
+ num_planes = config->num_overlay_plane;
+
/*
* This ioctl is called twice, once to determine how much space is
* needed, and the 2nd time to fill it.
*/
- if (config->num_overlay_plane &&
- (plane_resp->count_planes >= config->num_overlay_plane)) {
+ if (num_planes &&
+ (plane_resp->count_planes >= num_planes)) {
plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
list_for_each_entry(plane, &config->plane_list, head) {
- /* Only advertise overlays to userspace for now. */
- if (plane->type != DRM_PLANE_TYPE_OVERLAY)
+ /*
+ * Unless userspace set the 'universal planes'
+ * capability bit, only advertise overlays.
+ */
+ if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
+ !file_priv->universal_planes)
continue;
if (put_user(plane->base.id, plane_ptr + copied)) {
@@ -1986,7 +1996,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
copied++;
}
}
- plane_resp->count_planes = config->num_overlay_plane;
+ plane_resp->count_planes = num_planes;
out:
drm_modeset_unlock_all(dev);
@@ -328,6 +328,13 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
return -EINVAL;
file_priv->stereo_allowed = req->value;
break;
+ case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
+ if (!drm_universal_planes)
+ return -EINVAL;
+ if (req->value > 1)
+ return -EINVAL;
+ file_priv->universal_planes = req->value;
+ break;
default:
return -EINVAL;
}
@@ -45,6 +45,10 @@ EXPORT_SYMBOL(drm_debug);
unsigned int drm_rnodes = 0; /* 1 to enable experimental render nodes API */
EXPORT_SYMBOL(drm_rnodes);
+/* 1 to allow user space to request universal planes (experimental) */
+unsigned int drm_universal_planes = 0;
+EXPORT_SYMBOL(drm_universal_planes);
+
unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
EXPORT_SYMBOL(drm_vblank_offdelay);
@@ -68,6 +72,7 @@ MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps");
module_param_named(debug, drm_debug, int, 0600);
module_param_named(rnodes, drm_rnodes, int, 0600);
+module_param_named(universal_planes, drm_universal_planes, int, 0600);
module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
@@ -409,6 +409,11 @@ struct drm_file {
unsigned is_master :1;
/* true when the client has asked us to expose stereo 3D mode flags */
unsigned stereo_allowed :1;
+ /*
+ * true if client understands CRTC primary planes and cursor planes
+ * in the plane list
+ */
+ unsigned universal_planes:1;
struct pid *pid;
kuid_t uid;
@@ -1409,6 +1414,7 @@ extern void drm_put_dev(struct drm_device *dev);
extern void drm_unplug_dev(struct drm_device *dev);
extern unsigned int drm_debug;
extern unsigned int drm_rnodes;
+extern unsigned int drm_universal_planes;
extern unsigned int drm_vblank_offdelay;
extern unsigned int drm_timestamp_precision;
@@ -637,6 +637,14 @@ struct drm_get_cap {
*/
#define DRM_CLIENT_CAP_STEREO_3D 1
+/**
+ * DRM_CLIENT_CAP_UNIVERSAL_PLANES
+ *
+ * If set to 1, the DRM core will expose all planes (overlay, primary, and
+ * cursor) to userspace.
+ */
+#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
+
/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
struct drm_set_client_cap {
__u64 capability;