drm: add atomic properties

Once a driver is using atomic helpers for modeset, the next step is to
switch over to atomic properties.  To do this, make sure that any
modeset objects have their ->atomic_{get,set}_property() vfuncs suitably
populated if they have custom properties (you did already remember to
plug in atomic-helper func for the legacy ->set_property() vfuncs,
right?), and then set DRIVER_ATOMIC bit in driver_features flag.

A new cap is introduced, DRM_CLIENT_CAP_ATOMIC, for the purposes of
shielding legacy userspace from atomic properties.  Mostly for the
benefit of legacy DDX drivers that do silly things like getting/setting
each property at startup (since some of the new atomic properties will
be able to trigger modeset).

Signed-off-by: Rob Clark <robdclark@gmail.com>
[danvet: Squash in fixup patch to check for DRM_MODE_PROP_ATOMIC
instaed of the CAP define when filtering properties. Reported by
Tvrtko Uruslin, acked by Rob.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 8ba35c6..0f7115e 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -143,6 +143,7 @@
 #define DRIVER_MODESET     0x2000
 #define DRIVER_PRIME       0x4000
 #define DRIVER_RENDER      0x8000
+#define DRIVER_ATOMIC      0x10000
 
 /***********************************************************************/
 /** \name Macros to make printk easier */
@@ -283,6 +284,8 @@
 	 * in the plane list
 	 */
 	unsigned universal_planes:1;
+	/* true if client understands atomic properties */
+	unsigned atomic:1;
 
 	struct pid *pid;
 	kuid_t uid;
@@ -950,6 +953,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 bool drm_atomic;
 
 				/* Debugfs support */
 #if defined(CONFIG_DEBUG_FS)
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index d41233c..231fb48 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -63,6 +63,9 @@
 		const struct drm_connector_state *state,
 		struct drm_property *property, uint64_t *val);
 
+int drm_atomic_get_property(struct drm_mode_object *obj,
+			   struct drm_property *property, uint64_t *val);
+
 int __must_check
 drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
 			      struct drm_crtc *crtc);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e1f3469..b5ab673 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -63,7 +63,7 @@
 
 #define DRM_OBJECT_MAX_PROPERTY 24
 struct drm_object_properties {
-	int count;
+	int count, atomic_count;
 	/* NOTE: if we ever start dynamically destroying properties (ie.
 	 * not at drm_mode_config_cleanup() time), then we'd have to do
 	 * a better job of detaching property from mode objects to avoid
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index b0b8556..f7b2baf7 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -654,6 +654,13 @@
  */
 #define DRM_CLIENT_CAP_UNIVERSAL_PLANES  2
 
+/**
+ * DRM_CLIENT_CAP_ATOMIC
+ *
+ * If set to 1, the DRM core will expose atomic properties to userspace
+ */
+#define DRM_CLIENT_CAP_ATOMIC	3
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
 	__u64 capability;
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index aae71cb..b8f9c0f 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -272,6 +272,13 @@
 #define DRM_MODE_PROP_OBJECT		DRM_MODE_PROP_TYPE(1)
 #define DRM_MODE_PROP_SIGNED_RANGE	DRM_MODE_PROP_TYPE(2)
 
+/* the PROP_ATOMIC flag is used to hide properties from userspace that
+ * is not aware of atomic properties.  This is mostly to work around
+ * older userspace (DDX drivers) that read/write each prop they find,
+ * witout being aware that this could be triggering a lengthy modeset.
+ */
+#define DRM_MODE_PROP_ATOMIC        0x80000000
+
 struct drm_mode_property_enum {
 	__u64 value;
 	char name[DRM_PROP_NAME_LEN];