diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 18321fb16e8c..d8b7099abece 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -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); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index f4dc9b7a3831..93a42040bedb 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -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; } diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index fac6f9834257..4c24c3ac1efa 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -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); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e97fc998374c..a7c2a862b4f4 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -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; diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index b06c8ed68707..6e4952b20e2e 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -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;