drm: Allow userspace to ask for universal plane list (v2)

Userspace clients which wish to receive all DRM planes (primary and
cursor planes in addition to the traditional overlay planes) may set the
DRM_CLIENT_CAP_UNIVERSAL_PLANES capability.

v2: Hide behind drm.universal_planes module option [suggested by
    Daniel Vetter]

Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Rob Clark <robdclark@gmail.com>
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 18321fb..d8b7099 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1959,6 +1959,7 @@
 	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 @@
 	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 @@
 			copied++;
 		}
 	}
-	plane_resp->count_planes = config->num_overlay_plane;
+	plane_resp->count_planes = num_planes;
 
 out:
 	drm_modeset_unlock_all(dev);